2009-08-21 22:21:05 +02:00
/*
* This file is part of OpenTTD .
* 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.
* 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 .
* 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/>.
*/
2007-12-27 14:35:39 +01:00
/** @file vehicle_base.h Base class for all vehicles. */
2007-04-04 06:08:47 +02:00
2007-12-27 14:35:39 +01:00
# ifndef VEHICLE_BASE_H
# define VEHICLE_BASE_H
2004-08-09 19:04:08 +02:00
2007-12-18 21:38:16 +01:00
# include "track_type.h"
2007-12-23 11:56:02 +01:00
# include "command_type.h"
2008-03-31 01:24:18 +02:00
# include "order_base.h"
2007-06-22 13:58:59 +02:00
# include "cargopacket.h"
2007-06-21 18:17:47 +02:00
# include "texteff.hpp"
2008-03-28 19:00:38 +01:00
# include "engine_type.h"
2008-04-27 22:09:29 +02:00
# include "order_func.h"
2008-05-07 11:07:19 +02:00
# include "transport_type.h"
2010-08-18 17:15:59 +02:00
# include "group_type.h"
2012-07-29 18:44:39 +02:00
# include "base_consist.h"
2016-05-22 13:30:25 +02:00
# include "network/network.h"
2021-05-31 22:26:44 +02:00
# include "saveload/saveload.h"
2023-04-24 20:33:18 +02:00
# include "timer/timer_game_calendar.h"
2023-05-18 11:20:35 +02:00
# include "core/mem_func.hpp"
2007-02-13 11:26:53 +01:00
2021-11-19 01:07:22 +01:00
const uint TILE_AXIAL_DISTANCE = 192 ; // Logical length of the tile in any DiagDirection used in vehicle movement.
const uint TILE_CORNER_DISTANCE = 128 ; // Logical length of the tile corner crossing in any non-diagonal direction used in vehicle movement.
2010-11-05 17:34:22 +01:00
/** Vehicle status bits in #Vehicle::vehstatus. */
2005-05-03 01:59:11 +02:00
enum VehStatus {
2010-11-05 17:34:22 +01:00
VS_HIDDEN = 0x01 , ///< Vehicle is not visible.
VS_STOPPED = 0x02 , ///< Vehicle is stopped by the player.
VS_UNCLICKABLE = 0x04 , ///< Vehicle is not clickable by the user (shadow vehicles).
VS_DEFPAL = 0x08 , ///< Use default vehicle palette. @see DoDrawVehicle
VS_TRAIN_SLOWING = 0x10 , ///< Train is slowing down.
VS_SHADOW = 0x20 , ///< Vehicle is a shadow vehicle.
VS_AIRCRAFT_BROKEN = 0x40 , ///< Aircraft is broken down.
VS_CRASHED = 0x80 , ///< Vehicle is crashed.
2005-05-03 01:59:11 +02:00
} ;
2010-11-05 17:34:22 +01:00
/** Bit numbers in #Vehicle::vehicle_flags. */
2007-02-28 18:18:36 +01:00
enum VehicleFlags {
2010-11-05 17:34:22 +01:00
VF_LOADING_FINISHED , ///< Vehicle has finished loading.
VF_CARGO_UNLOADING , ///< Vehicle is unloading cargo.
VF_BUILT_AS_PROTOTYPE , ///< Vehicle is a prototype (accepted as exclusive preview).
2008-11-19 00:53:37 +01:00
VF_TIMETABLE_STARTED , ///< Whether the vehicle has started running on the timetable yet.
VF_AUTOFILL_TIMETABLE , ///< Whether the vehicle should fill in the timetable automatically.
VF_AUTOFILL_PRES_WAIT_TIME , ///< Whether non-destructive auto-fill should preserve waiting times
2010-08-16 00:37:30 +02:00
VF_STOP_LOADING , ///< Don't load anymore during the next load cycle.
2010-12-13 22:52:39 +01:00
VF_PATHFINDER_LOST , ///< Vehicle's pathfinder is lost.
2013-02-14 18:24:55 +01:00
VF_SERVINT_IS_CUSTOM , ///< Service interval is custom.
VF_SERVINT_IS_PERCENT , ///< Service interval is percent.
2006-12-02 17:56:32 +01:00
} ;
2010-11-06 13:39:18 +01:00
/** Bit numbers used to indicate which of the #NewGRFCache values are valid. */
enum NewGRFCacheValidValues {
NCVV_POSITION_CONSIST_LENGTH = 0 , ///< This bit will be set if the NewGRF var 40 currently stored is valid.
NCVV_POSITION_SAME_ID_LENGTH = 1 , ///< This bit will be set if the NewGRF var 41 currently stored is valid.
NCVV_CONSIST_CARGO_INFORMATION = 2 , ///< This bit will be set if the NewGRF var 42 currently stored is valid.
NCVV_COMPANY_INFORMATION = 3 , ///< This bit will be set if the NewGRF var 43 currently stored is valid.
2013-12-13 21:21:04 +01:00
NCVV_POSITION_IN_VEHICLE = 4 , ///< This bit will be set if the NewGRF var 4D currently stored is valid.
2010-11-27 22:09:41 +01:00
NCVV_END , ///< End of the bits.
2010-11-06 13:39:18 +01:00
} ;
2010-11-05 16:48:30 +01:00
/** Cached often queried (NewGRF) values */
2010-11-06 13:37:55 +01:00
struct NewGRFCache {
/* Values calculated when they are requested for the first time after invalidating the NewGRF cache. */
2023-05-08 19:01:06 +02:00
uint32_t position_consist_length ; ///< Cache for NewGRF var 40.
uint32_t position_same_id_length ; ///< Cache for NewGRF var 41.
uint32_t consist_cargo_information ; ///< Cache for NewGRF var 42. (Note: The cargotype is untranslated in the cache because the accessing GRF is yet unknown.)
uint32_t company_information ; ///< Cache for NewGRF var 43.
uint32_t position_in_vehicle ; ///< Cache for NewGRF var 4D.
uint8_t cache_valid ; ///< Bitset that indicates which cache values are valid.
2024-04-16 21:57:12 +02:00
auto operator < = > ( const NewGRFCache & ) const = default ;
2009-05-23 11:10:56 +02:00
} ;
2010-11-18 15:04:36 +01:00
/** Meaning of the various bits of the visual effect. */
enum VisualEffect {
VE_OFFSET_START = 0 , ///< First bit that contains the offset (0 = front, 8 = centre, 15 = rear)
VE_OFFSET_COUNT = 4 , ///< Number of bits used for the offset
VE_OFFSET_CENTRE = 8 , ///< Value of offset corresponding to a position above the centre of the vehicle
VE_TYPE_START = 4 , ///< First bit used for the type of effect
VE_TYPE_COUNT = 2 , ///< Number of bits used for the effect type
VE_TYPE_DEFAULT = 0 , ///< Use default from engine class
VE_TYPE_STEAM = 1 , ///< Steam plumes
VE_TYPE_DIESEL = 2 , ///< Diesel fumes
VE_TYPE_ELECTRIC = 3 , ///< Electric sparks
VE_DISABLE_EFFECT = 6 , ///< Flag to disable visual effect
2014-08-17 16:53:11 +02:00
VE_ADVANCED_EFFECT = VE_DISABLE_EFFECT , ///< Flag for advanced effects
2010-11-18 15:04:36 +01:00
VE_DISABLE_WAGON_POWER = 7 , ///< Flag to disable wagon power
2010-11-18 15:20:03 +01:00
VE_DEFAULT = 0xFF , ///< Default value to indicate that visual effect should be based on engine class
2010-11-18 15:04:36 +01:00
} ;
2014-08-17 16:52:48 +02:00
/** Models for spawning visual effects. */
enum VisualEffectSpawnModel {
VESM_NONE = 0 , ///< No visual effect
VESM_STEAM , ///< Steam model
VESM_DIESEL , ///< Diesel model
VESM_ELECTRIC , ///< Electric model
VESM_END
} ;
2011-01-29 18:21:39 +01:00
/**
* Enum to handle ground vehicle subtypes .
* This is defined here instead of at # GroundVehicle because some common function require access to these flags .
* Do not access it directly unless you have to . Use the subtype access functions .
*/
enum GroundVehicleSubtypeFlags {
GVSF_FRONT = 0 , ///< Leading engine of a consist.
GVSF_ARTICULATED_PART = 1 , ///< Articulated part of an engine.
GVSF_WAGON = 2 , ///< Wagon (not used for road vehicles).
GVSF_ENGINE = 3 , ///< Engine that can be front engine, but might be placed behind another engine (not used for road vehicles).
GVSF_FREE_WAGON = 4 , ///< First in a wagon chain (in depot) (not used for road vehicles).
GVSF_MULTIHEADED = 5 , ///< Engine is multiheaded (not used for road vehicles).
} ;
2010-11-06 13:53:31 +01:00
/** Cached often queried values common to all vehicles. */
struct VehicleCache {
2023-05-08 19:01:06 +02:00
uint16_t cached_max_speed ; ///< Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
uint16_t cached_cargo_age_period ; ///< Number of ticks before carried cargo is aged.
2010-11-18 15:04:36 +01:00
2024-03-16 23:59:32 +01:00
uint8_t cached_vis_effect ; ///< Visual effect to show (see #VisualEffect)
2024-04-16 21:57:12 +02:00
auto operator < = > ( const VehicleCache & ) const = default ;
2010-11-06 13:53:31 +01:00
} ;
2016-10-16 16:57:56 +02:00
/** Sprite sequence for a vehicle part. */
struct VehicleSpriteSeq {
2022-04-26 19:07:44 +02:00
PalSpriteID seq [ 8 ] ;
2016-10-16 16:59:44 +02:00
uint count ;
2016-10-16 16:57:56 +02:00
bool operator = = ( const VehicleSpriteSeq & other ) const
{
2016-10-16 16:59:44 +02:00
return this - > count = = other . count & & MemCmpT < PalSpriteID > ( this - > seq , other . seq , this - > count ) = = 0 ;
2016-10-16 16:57:56 +02:00
}
bool operator ! = ( const VehicleSpriteSeq & other ) const
{
return ! this - > operator = = ( other ) ;
}
/**
* Check whether the sequence contains any sprites .
*/
bool IsValid ( ) const
{
2016-10-16 16:59:44 +02:00
return this - > count ! = 0 ;
2016-10-16 16:57:56 +02:00
}
/**
* Clear all information .
*/
void Clear ( )
{
2016-10-16 16:59:44 +02:00
this - > count = 0 ;
2016-10-16 16:57:56 +02:00
}
/**
* Assign a single sprite to the sequence .
*/
void Set ( SpriteID sprite )
{
2016-10-16 16:59:44 +02:00
this - > count = 1 ;
this - > seq [ 0 ] . sprite = sprite ;
this - > seq [ 0 ] . pal = 0 ;
}
/**
* Copy data from another sprite sequence , while dropping all recolouring information .
*/
void CopyWithoutPalette ( const VehicleSpriteSeq & src )
{
this - > count = src . count ;
for ( uint i = 0 ; i < src . count ; + + i ) {
this - > seq [ i ] . sprite = src . seq [ i ] . sprite ;
this - > seq [ i ] . pal = 0 ;
}
2016-10-16 16:57:56 +02:00
}
2016-10-16 16:58:38 +02:00
void GetBounds ( Rect * bounds ) const ;
void Draw ( int x , int y , PaletteID default_pal , bool force_pal ) const ;
2016-10-16 16:57:56 +02:00
} ;
2021-01-03 14:32:58 +01:00
/**
* Cache for vehicle sprites and values relating to whether they should be updated before drawing ,
* or calculating the viewport .
*/
struct MutableSpriteCache {
2021-01-17 19:57:16 +01:00
Direction last_direction ; ///< Last direction we obtained sprites for
bool revalidate_before_draw ; ///< We need to do a GetImage() and check bounds before drawing this sprite
bool is_viewport_candidate ; ///< This vehicle can potentially be drawn on a viewport
2024-03-14 21:40:33 +01:00
Rect old_coord ; ///< Co-ordinates from the last valid bounding box
2021-01-17 19:57:16 +01:00
VehicleSpriteSeq sprite_seq ; ///< Vehicle appearance.
2021-01-03 14:32:58 +01:00
} ;
2010-08-19 22:58:30 +02:00
/** A vehicle pool for a little over 1 million vehicles. */
typedef Pool < Vehicle , VehicleID , 512 , 0xFF000 > VehiclePool ;
2009-05-22 17:13:50 +02:00
extern VehiclePool _vehicle_pool ;
2004-08-09 19:04:08 +02:00
2007-09-08 00:06:52 +02:00
/* Some declarations of functions, so we can make them friendly */
2010-12-14 22:31:00 +01:00
struct GroundVehicleCache ;
2007-09-08 00:06:52 +02:00
struct LoadgameState ;
extern bool LoadOldVehicle ( LoadgameState * ls , int num ) ;
2009-05-22 17:13:50 +02:00
extern void FixOldVehicles ( ) ;
2007-08-30 15:09:44 +02:00
2011-11-01 01:23:41 +01:00
struct GRFFile ;
2013-08-20 23:22:37 +02:00
/**
* Simulated cargo type and capacity for prediction of future links .
*/
struct RefitDesc {
CargoID cargo ; ///< Cargo type the vehicle will be carrying.
2023-05-08 19:01:06 +02:00
uint16_t capacity ; ///< Capacity the vehicle will have.
uint16_t remaining ; ///< Capacity remaining from before the previous refit.
RefitDesc ( CargoID cargo , uint16_t capacity , uint16_t remaining ) :
2013-08-20 23:22:37 +02:00
cargo ( cargo ) , capacity ( capacity ) , remaining ( remaining ) { }
} ;
2023-01-03 22:33:09 +01:00
/**
* Structure to return information about the closest depot location ,
* and whether it could be found .
*/
struct ClosestDepot {
TileIndex location ;
DestinationID destination ; ///< The DestinationID as used for orders.
bool reverse ;
bool found ;
ClosestDepot ( ) :
location ( INVALID_TILE ) , destination ( 0 ) , reverse ( false ) , found ( false ) { }
ClosestDepot ( TileIndex location , DestinationID destination , bool reverse = false ) :
location ( location ) , destination ( destination ) , reverse ( reverse ) , found ( true ) { }
} ;
2011-01-29 22:37:11 +01:00
/** %Vehicle data structure. */
2012-07-29 18:44:39 +02:00
struct Vehicle : VehiclePool : : PoolItem < & _vehicle_pool > , BaseVehicle , BaseConsist {
2007-08-30 15:09:44 +02:00
private :
2013-08-20 23:22:37 +02:00
typedef std : : list < RefitDesc > RefitList ;
2010-11-05 16:48:30 +01:00
Vehicle * next ; ///< pointer to the next vehicle in the chain
Vehicle * previous ; ///< NOSAVE: pointer to the previous vehicle in the chain
Vehicle * first ; ///< NOSAVE: pointer to the first vehicle in the chain
2008-08-17 21:56:17 +02:00
2010-11-05 16:48:30 +01:00
Vehicle * next_shared ; ///< pointer to the next vehicle that shares the order
Vehicle * previous_shared ; ///< NOSAVE: pointer to the previous vehicle in the shared order chain
2013-08-20 23:22:37 +02:00
2007-08-30 15:09:44 +02:00
public :
2009-05-22 17:13:50 +02:00
friend void FixOldVehicles ( ) ;
2011-05-14 20:35:40 +02:00
friend void AfterLoadVehicles ( bool part_of_load ) ; ///< So we can set the #previous and #first pointers while loading
2008-04-21 10:35:27 +02:00
friend bool LoadOldVehicle ( LoadgameState * ls , int num ) ; ///< So we can set the proper next pointer while loading
2021-06-06 16:03:56 +02:00
/* So we can use private/protected variables in the saveload code */
friend class SlVehicleCommon ;
friend class SlVehicleDisaster ;
friend void Ptrs_VEHS ( ) ;
2007-08-30 15:09:44 +02:00
2010-11-05 16:48:30 +01:00
TileIndex tile ; ///< Current tile index
2008-12-20 12:51:52 +01:00
/**
* Heading for this tile .
* For airports and train stations this tile does not necessarily belong to the destination station ,
2011-01-29 22:37:11 +01:00
* but it can be used for heuristic purposes to estimate the distance .
2008-12-20 12:51:52 +01:00
*/
TileIndex dest_tile ;
2008-04-21 10:35:27 +02:00
2010-11-05 16:48:30 +01:00
Money profit_this_year ; ///< Profit this year << 8, low 8 bits are fract
Money profit_last_year ; ///< Profit last year << 8, low 8 bits are fract
Money value ; ///< Value of the vehicle
2009-06-29 21:55:36 +02:00
2010-11-05 16:48:30 +01:00
CargoPayment * cargo_payment ; ///< The cargo payment we're currently in
2004-08-09 19:04:08 +02:00
2021-01-17 19:57:16 +01:00
mutable Rect coord ; ///< NOSAVE: Graphical bounding box of the vehicle, i.e. what to redraw on moves.
2011-01-31 21:27:33 +01:00
2012-01-02 13:07:50 +01:00
Vehicle * hash_viewport_next ; ///< NOSAVE: Next vehicle in the visual location hash.
Vehicle * * hash_viewport_prev ; ///< NOSAVE: Previous vehicle in the visual location hash.
2011-01-31 21:27:33 +01:00
2012-01-02 13:07:50 +01:00
Vehicle * hash_tile_next ; ///< NOSAVE: Next vehicle in the tile location hash.
Vehicle * * hash_tile_prev ; ///< NOSAVE: Previous vehicle in the tile location hash.
Vehicle * * hash_tile_current ; ///< NOSAVE: Cache of the current hash chain.
2008-04-21 10:35:27 +02:00
2010-11-05 16:48:30 +01:00
SpriteID colourmap ; ///< NOSAVE: cached colour mapping
2008-04-21 10:35:27 +02:00
/* Related to age and service time */
2023-04-24 20:33:18 +02:00
TimerGameCalendar : : Year build_year ; ///< Year the vehicle has been built.
2024-03-09 15:38:52 +01:00
TimerGameCalendar : : Date age ; ///< Age in calendar days.
TimerGameEconomy : : Date economy_age ; ///< Age in economy days.
2023-04-24 20:33:18 +02:00
TimerGameCalendar : : Date max_age ; ///< Maximum age
2024-01-22 15:04:34 +01:00
TimerGameEconomy : : Date date_of_last_service ; ///< Last economy date the vehicle had a service at a depot.
TimerGameCalendar : : Date date_of_last_service_newgrf ; ///< Last calendar date the vehicle had a service at a depot, unchanged by the date cheat to protect against unsafe NewGRF behavior.
2023-05-08 19:01:06 +02:00
uint16_t reliability ; ///< Reliability.
uint16_t reliability_spd_dec ; ///< Reliability decrease speed.
2024-03-16 23:59:32 +01:00
uint8_t breakdown_ctr ; ///< Counter for managing breakdown events. @see Vehicle::HandleBreakdown
uint8_t breakdown_delay ; ///< Counter for managing breakdown length.
uint8_t breakdowns_since_last_service ; ///< Counter for the amount of breakdowns.
uint8_t breakdown_chance ; ///< Current chance of breakdowns.
2004-08-09 19:04:08 +02:00
2023-05-08 19:01:06 +02:00
int32_t x_pos ; ///< x coordinate.
int32_t y_pos ; ///< y coordinate.
int32_t z_pos ; ///< z coordinate.
2019-04-22 09:11:28 +02:00
Direction direction ; ///< facing
2010-11-05 16:48:30 +01:00
2019-04-22 10:10:04 +02:00
Owner owner ; ///< Which company owns the vehicle?
2011-12-19 18:40:54 +01:00
/**
* currently displayed sprite index
* 0xfd = = custom sprite , 0xfe = = custom second head sprite
* 0xff = = reserved for another custom sprite
*/
2024-03-16 23:59:32 +01:00
uint8_t spritenum ;
uint8_t x_extent ; ///< x-extent of vehicle bounding box
uint8_t y_extent ; ///< y-extent of vehicle bounding box
uint8_t z_extent ; ///< z-extent of vehicle bounding box
2023-05-08 19:01:06 +02:00
int8_t x_bb_offs ; ///< x offset of vehicle bounding box
int8_t y_bb_offs ; ///< y offset of vehicle bounding box
int8_t x_offs ; ///< x offset for vehicle sprite
int8_t y_offs ; ///< y offset for vehicle sprite
2011-01-31 21:27:33 +01:00
EngineID engine_type ; ///< The type of engine used for this vehicle.
2004-08-09 19:04:08 +02:00
2010-11-05 16:48:30 +01:00
TextEffectID fill_percent_te_id ; ///< a text-effect id to a loading indicator object
UnitID unitnumber ; ///< unit number, for display purposes only
2008-04-21 10:35:27 +02:00
2023-05-08 19:01:06 +02:00
uint16_t cur_speed ; ///< current speed
2024-03-16 23:59:32 +01:00
uint8_t subspeed ; ///< fractional speed
uint8_t acceleration ; ///< used by train & aircraft
2023-05-08 19:01:06 +02:00
uint32_t motion_counter ; ///< counter to occasionally play a vehicle sound.
2024-03-16 23:59:32 +01:00
uint8_t progress ; ///< The percentage (if divided by 256) this vehicle already crossed the tile unit.
2007-06-21 18:17:47 +02:00
2024-03-16 23:59:32 +01:00
uint8_t waiting_triggers ; ///< Triggers to be yet matched before rerandomizing the random bits.
2024-03-14 21:40:33 +01:00
uint16_t random_bits ; ///< Bits used for randomized variational spritegroups.
2004-08-09 19:04:08 +02:00
2011-01-31 21:27:33 +01:00
StationID last_station_visited ; ///< The last station we stopped at.
2013-05-19 16:22:04 +02:00
StationID last_loading_station ; ///< Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
2023-11-20 18:00:34 +01:00
TimerGameTick : : TickCounter last_loading_tick ; ///< Last TimerGameTick::counter tick that the vehicle has stopped at a station and could possibly leave with any cargo loaded.
2004-09-10 21:02:27 +02:00
2024-03-14 21:40:33 +01:00
VehicleCargoList cargo ; ///< The cargo this vehicle is carrying
2010-11-05 16:48:30 +01:00
CargoID cargo_type ; ///< type of cargo this vehicle is carrying
2024-03-16 23:59:32 +01:00
uint8_t cargo_subtype ; ///< Used for livery refits (NewGRF variations)
2023-05-08 19:01:06 +02:00
uint16_t cargo_cap ; ///< total capacity
uint16_t refit_cap ; ///< Capacity left over from before last refit.
uint16_t cargo_age_counter ; ///< Ticks till cargo is aged next.
int8_t trip_occupancy ; ///< NOSAVE: Occupancy of vehicle of the current trip (updated after leaving a station).
2007-06-22 13:58:59 +02:00
2024-03-16 23:59:32 +01:00
uint8_t day_counter ; ///< Increased by one for each day
uint8_t tick_counter ; ///< Increased by one for each tick
uint8_t running_ticks ; ///< Number of ticks this vehicle was not stopped this day
2024-03-14 21:40:33 +01:00
uint16_t load_unload_ticks ; ///< Ticks to wait before starting next cycle.
2004-08-09 19:04:08 +02:00
2024-03-16 23:59:32 +01:00
uint8_t vehstatus ; ///< Status
2024-03-14 21:40:33 +01:00
uint8_t subtype ; ///< subtype (Filled with values from #AircraftSubType/#DisasterSubType/#EffectVehicleType/#GroundVehicleSubtypeFlags)
2010-11-05 16:48:30 +01:00
Order current_order ; ///< The current order (+ status, like: loading)
2005-01-15 20:06:22 +01:00
2009-01-03 14:52:06 +01:00
union {
2022-02-12 19:28:34 +01:00
OrderList * orders ; ///< Pointer to the order list for this vehicle
Order * old_orders ; ///< Only used during conversion of old save games
} ;
2004-08-09 19:04:08 +02:00
2010-11-06 13:37:55 +01:00
NewGRFCache grf_cache ; ///< Cache of often used calculated NewGRF values
2010-11-06 13:53:31 +01:00
VehicleCache vcache ; ///< Cache of often used vehicle values.
2007-08-03 21:36:00 +02:00
2024-03-14 21:40:33 +01:00
GroupID group_id ; ///< Index of group Pool array
2021-01-03 15:02:53 +01:00
mutable MutableSpriteCache sprite_cache ; ///< Cache of sprites and values related to recalculating them, see #MutableSpriteCache
2021-01-02 23:39:30 +01:00
2022-10-31 20:47:25 +01:00
/**
* Calculates the weight value that this vehicle will have when fully loaded with its current cargo .
* @ return Weight value in tonnes .
*/
2023-05-08 19:01:06 +02:00
virtual uint16_t GetMaxWeight ( ) const
2022-10-31 20:47:25 +01:00
{
return 0 ;
}
2009-05-30 22:13:12 +02:00
Vehicle ( VehicleType type = VEH_INVALID ) ;
2007-08-03 21:36:00 +02:00
2007-08-05 19:43:04 +02:00
void PreDestructor ( ) ;
2007-08-03 21:36:00 +02:00
/** We want to 'destruct' the right class. */
virtual ~ Vehicle ( ) ;
2007-01-13 19:55:54 +01:00
void BeginLoading ( ) ;
2013-06-09 15:03:48 +02:00
void CancelReservation ( StationID next , Station * st ) ;
2007-01-13 19:55:54 +01:00
void LeaveStation ( ) ;
2007-04-29 23:24:08 +02:00
2010-12-14 22:31:00 +01:00
GroundVehicleCache * GetGroundVehicleCache ( ) ;
const GroundVehicleCache * GetGroundVehicleCache ( ) const ;
2023-05-08 19:01:06 +02:00
uint16_t & GetGroundVehicleFlags ( ) ;
const uint16_t & GetGroundVehicleFlags ( ) const ;
2011-04-16 18:41:02 +02:00
2011-05-18 14:19:58 +02:00
void DeleteUnreachedImplicitOrders ( ) ;
2011-01-15 19:14:29 +01:00
2007-05-07 18:21:34 +02:00
void HandleLoading ( bool mode = false ) ;
2007-04-30 00:33:51 +02:00
/**
* Marks the vehicles to be redrawn and updates cached variables
2007-09-09 12:13:17 +02:00
*
* This method marks the area of the vehicle on the screen as dirty .
* It can be use to repaint the vehicle .
*
* @ ingroup dirty
2007-04-30 00:33:51 +02:00
*/
virtual void MarkDirty ( ) { }
2007-05-01 18:35:14 +02:00
/**
* Updates the x and y offsets and the size of the sprite used
* for this vehicle .
*/
2018-05-22 19:43:34 +02:00
virtual void UpdateDeltaXY ( ) { }
2007-05-02 11:29:41 +02:00
2010-07-04 15:07:47 +02:00
/**
* Determines the effective direction - specific vehicle movement speed .
*
* This method belongs to the old vehicle movement method :
* A vehicle moves a step every 256 progress units .
* The vehicle speed is scaled by 3 / 4 when moving in X or Y direction due to the longer distance .
*
* However , this method is slightly wrong in corners , as the leftover progress is not scaled correctly
* when changing movement direction . # GetAdvanceSpeed ( ) and # GetAdvanceDistance ( ) are better wrt . this .
*
* @ param speed Direction - independent unscaled speed .
* @ return speed scaled by movement direction . 256 units are required for each movement step .
*/
2011-12-20 18:57:56 +01:00
inline uint GetOldAdvanceSpeed ( uint speed )
2010-07-04 15:07:47 +02:00
{
return ( this - > direction & 1 ) ? speed : speed * 3 / 4 ;
}
/**
* Determines the effective vehicle movement speed .
*
* Together with # GetAdvanceDistance ( ) this function is a replacement for # GetOldAdvanceSpeed ( ) .
*
* A vehicle progresses independent of it ' s movement direction .
* However different amounts of " progress " are needed for moving a step in a specific direction .
* That way the leftover progress does not need any adaption when changing movement direction .
*
* @ param speed Direction - independent unscaled speed .
* @ return speed , scaled to match # GetAdvanceDistance ( ) .
*/
2011-12-20 18:57:56 +01:00
static inline uint GetAdvanceSpeed ( uint speed )
2010-07-04 15:07:47 +02:00
{
return speed * 3 / 4 ;
}
/**
* Determines the vehicle " progress " needed for moving a step .
*
* Together with # GetAdvanceSpeed ( ) this function is a replacement for # GetOldAdvanceSpeed ( ) .
*
* @ return distance to drive for a movement step on the map .
*/
2011-12-20 18:57:56 +01:00
inline uint GetAdvanceDistance ( )
2010-07-04 15:07:47 +02:00
{
2021-11-19 01:07:22 +01:00
return ( this - > direction & 1 ) ? TILE_AXIAL_DISTANCE : TILE_CORNER_DISTANCE * 2 ;
2010-07-04 15:07:47 +02:00
}
2007-05-02 11:29:41 +02:00
/**
* Sets the expense type associated to this vehicle type
* @ param income whether this is income or ( running ) expenses of the vehicle
*/
2023-09-16 22:20:53 +02:00
virtual ExpensesType GetExpenseType ( [ [ maybe_unused ] ] bool income ) const { return EXPENSES_OTHER ; }
2007-05-02 11:29:41 +02:00
2007-05-07 17:58:05 +02:00
/**
* Play the sound associated with leaving the station
2022-11-10 21:36:18 +01:00
* @ param force Should we play the sound even if sound effects are muted ? ( horn hotkey )
2007-05-07 17:58:05 +02:00
*/
2023-09-16 22:20:53 +02:00
virtual void PlayLeaveStationSound ( [ [ maybe_unused ] ] bool force = false ) const { }
2007-06-01 14:03:10 +02:00
/**
* Whether this is the primary vehicle in the chain .
*/
virtual bool IsPrimaryVehicle ( ) const { return false ; }
2011-11-01 01:21:08 +01:00
const Engine * GetEngine ( ) const ;
2007-07-01 21:11:47 +02:00
/**
* Gets the sprite to show for the given direction
* @ param direction the direction the vehicle is facing
2018-10-28 03:17:36 +01:00
* @ param [ out ] result Vehicle sprite sequence .
2007-07-01 21:11:47 +02:00
*/
2023-09-16 22:20:53 +02:00
virtual void GetImage ( [ [ maybe_unused ] ] Direction direction , [ [ maybe_unused ] ] EngineImageType image_type , [ [ maybe_unused ] ] VehicleSpriteSeq * result ) const { result - > Clear ( ) ; }
2007-07-01 21:24:54 +02:00
2011-11-01 01:23:41 +01:00
const GRFFile * GetGRF ( ) const ;
2023-05-08 19:01:06 +02:00
uint32_t GetGRFID ( ) const ;
2011-11-01 01:23:41 +01:00
2009-05-31 14:03:14 +02:00
/**
* Invalidates cached NewGRF variables
* @ see InvalidateNewGRFCacheOfChain
*/
2011-12-20 18:57:56 +01:00
inline void InvalidateNewGRFCache ( )
2009-05-31 14:03:14 +02:00
{
2010-11-06 13:37:55 +01:00
this - > grf_cache . cache_valid = 0 ;
2009-05-31 14:03:14 +02:00
}
/**
* Invalidates cached NewGRF variables of all vehicles in the chain ( after the current vehicle )
* @ see InvalidateNewGRFCache
*/
2011-12-20 18:57:56 +01:00
inline void InvalidateNewGRFCacheOfChain ( )
2009-05-31 14:03:14 +02:00
{
2019-04-10 23:07:06 +02:00
for ( Vehicle * u = this ; u ! = nullptr ; u = u - > Next ( ) ) {
2009-05-31 14:03:14 +02:00
u - > InvalidateNewGRFCache ( ) ;
}
}
2010-12-14 22:26:03 +01:00
/**
* Check if the vehicle is a ground vehicle .
* @ return True iff the vehicle is a train or a road vehicle .
*/
2023-01-24 22:50:53 +01:00
debug_inline bool IsGroundVehicle ( ) const
2010-12-14 22:26:03 +01:00
{
return this - > type = = VEH_TRAIN | | this - > type = = VEH_ROAD ;
}
2007-08-26 22:43:22 +02:00
/**
2009-02-01 18:14:39 +01:00
* Gets the speed in km - ish / h that can be sent into SetDParam for string processing .
2007-08-26 22:43:22 +02:00
* @ return the vehicle ' s speed
*/
virtual int GetDisplaySpeed ( ) const { return 0 ; }
2007-08-28 08:46:33 +02:00
/**
2009-02-01 18:14:39 +01:00
* Gets the maximum speed in km - ish / h that can be sent into SetDParam for string processing .
2007-08-28 08:46:33 +02:00
* @ return the vehicle ' s maximum speed
*/
virtual int GetDisplayMaxSpeed ( ) const { return 0 ; }
2012-05-14 21:56:49 +02:00
/**
* Calculates the maximum speed of the vehicle under its current conditions .
* @ return Current maximum speed in native units .
*/
virtual int GetCurrentMaxSpeed ( ) const { return 0 ; }
2007-08-29 23:27:16 +02:00
/**
* Gets the running cost of a vehicle
* @ return the vehicle ' s running cost
*/
virtual Money GetRunningCost ( ) const { return 0 ; }
2007-08-29 23:49:08 +02:00
/**
* Check whether the vehicle is in the depot .
* @ return true if and only if the vehicle is in the depot .
*/
virtual bool IsInDepot ( ) const { return false ; }
2012-07-07 17:39:46 +02:00
/**
* Check whether the whole vehicle chain is in the depot .
* @ return true if and only if the whole chain is in the depot .
*/
virtual bool IsChainInDepot ( ) const { return this - > IsInDepot ( ) ; }
2007-08-29 23:49:08 +02:00
/**
* Check whether the vehicle is in the depot * and * stopped .
* @ return true if and only if the vehicle is in the depot and stopped .
*/
2012-07-07 17:39:46 +02:00
bool IsStoppedInDepot ( ) const
{
assert ( this = = this - > First ( ) ) ;
/* Free wagons have no VS_STOPPED state */
if ( this - > IsPrimaryVehicle ( ) & & ! ( this - > vehstatus & VS_STOPPED ) ) return false ;
return this - > IsChainInDepot ( ) ;
}
2007-08-29 23:49:08 +02:00
2007-07-01 21:24:54 +02:00
/**
* Calls the tick handler of the vehicle
2009-05-22 15:53:14 +02:00
* @ return is this vehicle still valid ?
2007-07-01 21:24:54 +02:00
*/
2009-05-22 15:53:14 +02:00
virtual bool Tick ( ) { return true ; } ;
2007-08-02 23:19:07 +02:00
2008-02-01 23:02:14 +01:00
/**
2024-01-22 15:04:34 +01:00
* Calls the new calendar day handler of the vehicle .
2008-02-01 23:02:14 +01:00
*/
2024-01-22 15:04:34 +01:00
virtual void OnNewCalendarDay ( ) { } ;
2008-02-01 23:02:14 +01:00
2024-01-22 15:04:34 +01:00
/**
* Calls the new economy day handler of the vehicle .
*/
virtual void OnNewEconomyDay ( ) { } ;
void ShiftDates ( TimerGameEconomy : : Date interval ) ;
2021-11-19 01:04:22 +01:00
2009-12-04 21:29:46 +01:00
/**
* Crash the ( whole ) vehicle chain .
* @ param flooded whether the cause of the crash is flooding or not .
* @ return the number of lost souls .
*/
virtual uint Crash ( bool flooded = false ) ;
2009-05-22 20:17:20 +02:00
/**
* Returns the Trackdir on which the vehicle is currently located .
* Works for trains and ships .
* Currently works only sortof for road vehicles , since they have a fuzzy
* concept of being " on " a trackdir . Dunno really what it returns for a road
* vehicle that is halfway a tile , never really understood that part . For road
* vehicles that are at the beginning or end of the tile , should just return
* the diagonal trackdir on which they are driving . I _think_ .
* For other vehicles types , or vehicles with no clear trackdir ( such as those
* in depots ) , returns 0xFF .
* @ return the trackdir of the vehicle
*/
virtual Trackdir GetVehicleTrackdir ( ) const { return INVALID_TRACKDIR ; }
2007-08-29 23:27:16 +02:00
/**
* Gets the running cost of a vehicle that can be sent into SetDParam for string processing .
* @ return the vehicle ' s running cost
*/
Money GetDisplayRunningCost ( ) const { return ( this - > GetRunningCost ( ) > > 8 ) ; }
2008-02-20 18:06:58 +01:00
/**
* Gets the profit vehicle had this year . It can be sent into SetDParam for string processing .
* @ return the vehicle ' s profit this year
*/
Money GetDisplayProfitThisYear ( ) const { return ( this - > profit_this_year > > 8 ) ; }
/**
* Gets the profit vehicle had last year . It can be sent into SetDParam for string processing .
* @ return the vehicle ' s profit last year
*/
Money GetDisplayProfitLastYear ( ) const { return ( this - > profit_last_year > > 8 ) ; }
2007-08-30 23:11:12 +02:00
void SetNext ( Vehicle * next ) ;
2007-08-30 15:03:56 +02:00
/**
* Get the next vehicle of this vehicle .
* @ note articulated parts are also counted as vehicles .
2019-04-10 23:07:06 +02:00
* @ return the next vehicle or nullptr when there isn ' t a next vehicle .
2007-08-30 15:03:56 +02:00
*/
inline Vehicle * Next ( ) const { return this - > next ; }
2007-08-30 23:11:12 +02:00
/**
* Get the previous vehicle of this vehicle .
* @ note articulated parts are also counted as vehicles .
2019-04-10 23:07:06 +02:00
* @ return the previous vehicle or nullptr when there isn ' t a previous vehicle .
2007-08-30 23:11:12 +02:00
*/
inline Vehicle * Previous ( ) const { return this - > previous ; }
/**
* Get the first vehicle of this vehicle chain .
* @ return the first vehicle of the chain .
*/
inline Vehicle * First ( ) const { return this - > first ; }
2008-02-02 03:45:09 +01:00
2009-07-20 21:58:33 +02:00
/**
* Get the last vehicle of this vehicle chain .
* @ return the last vehicle of the chain .
*/
inline Vehicle * Last ( )
{
Vehicle * v = this ;
2019-04-10 23:07:06 +02:00
while ( v - > Next ( ) ! = nullptr ) v = v - > Next ( ) ;
2009-07-20 21:58:33 +02:00
return v ;
}
/**
* Get the last vehicle of this vehicle chain .
* @ return the last vehicle of the chain .
*/
inline const Vehicle * Last ( ) const
{
const Vehicle * v = this ;
2019-04-10 23:07:06 +02:00
while ( v - > Next ( ) ! = nullptr ) v = v - > Next ( ) ;
2009-07-20 21:58:33 +02:00
return v ;
}
2008-08-17 21:56:17 +02:00
2011-10-04 23:35:29 +02:00
/**
2012-01-01 18:22:32 +01:00
* Get the vehicle at offset \ a n of this vehicle chain .
2011-10-04 23:35:29 +02:00
* @ param n Offset from the current vehicle .
2019-04-10 23:07:06 +02:00
* @ return The new vehicle or nullptr if the offset is out - of - bounds .
2011-10-04 23:35:29 +02:00
*/
inline Vehicle * Move ( int n )
{
Vehicle * v = this ;
if ( n < 0 ) {
2019-04-10 23:07:06 +02:00
for ( int i = 0 ; i ! = n & & v ! = nullptr ; i - - ) v = v - > Previous ( ) ;
2011-10-04 23:35:29 +02:00
} else {
2019-04-10 23:07:06 +02:00
for ( int i = 0 ; i ! = n & & v ! = nullptr ; i + + ) v = v - > Next ( ) ;
2011-10-04 23:35:29 +02:00
}
return v ;
}
2012-09-16 18:31:53 +02:00
/**
* Get the vehicle at offset \ a n of this vehicle chain .
* @ param n Offset from the current vehicle .
2019-04-10 23:07:06 +02:00
* @ return The new vehicle or nullptr if the offset is out - of - bounds .
2012-09-16 18:31:53 +02:00
*/
inline const Vehicle * Move ( int n ) const
{
const Vehicle * v = this ;
if ( n < 0 ) {
2019-04-10 23:07:06 +02:00
for ( int i = 0 ; i ! = n & & v ! = nullptr ; i - - ) v = v - > Previous ( ) ;
2012-09-16 18:31:53 +02:00
} else {
2019-04-10 23:07:06 +02:00
for ( int i = 0 ; i ! = n & & v ! = nullptr ; i + + ) v = v - > Next ( ) ;
2012-09-16 18:31:53 +02:00
}
return v ;
}
2009-01-03 14:52:06 +01:00
/**
* Get the first order of the vehicles order list .
* @ return first order of order list .
*/
2022-02-12 19:28:34 +01:00
inline Order * GetFirstOrder ( ) const { return ( this - > orders = = nullptr ) ? nullptr : this - > orders - > GetFirstOrder ( ) ; }
2009-01-03 14:52:06 +01:00
2008-08-17 21:56:17 +02:00
void AddToShared ( Vehicle * shared_chain ) ;
void RemoveFromShared ( ) ;
/**
2009-01-03 14:52:06 +01:00
* Get the next vehicle of the shared vehicle chain .
2019-04-10 23:07:06 +02:00
* @ return the next shared vehicle or nullptr when there isn ' t a next vehicle .
2008-08-17 21:56:17 +02:00
*/
inline Vehicle * NextShared ( ) const { return this - > next_shared ; }
2009-01-03 14:52:06 +01:00
/**
* Get the previous vehicle of the shared vehicle chain
2019-04-10 23:07:06 +02:00
* @ return the previous shared vehicle or nullptr when there isn ' t a previous vehicle .
2009-01-03 14:52:06 +01:00
*/
inline Vehicle * PreviousShared ( ) const { return this - > previous_shared ; }
2008-08-17 21:56:17 +02:00
/**
* Get the first vehicle of this vehicle chain .
* @ return the first vehicle of the chain .
*/
2022-02-12 19:28:34 +01:00
inline Vehicle * FirstShared ( ) const { return ( this - > orders = = nullptr ) ? this - > First ( ) : this - > orders - > GetFirstSharedVehicle ( ) ; }
2008-08-17 21:56:17 +02:00
2008-02-02 03:45:09 +01:00
/**
* Check if we share our orders with another vehicle .
* @ return true if there are other vehicles sharing the same order
*/
2022-02-12 19:28:34 +01:00
inline bool IsOrderListShared ( ) const { return this - > orders ! = nullptr & & this - > orders - > IsShared ( ) ; }
2008-02-23 23:01:55 +01:00
2009-01-03 14:52:06 +01:00
/**
2009-01-03 14:20:32 +01:00
* Get the number of orders this vehicle has .
* @ return the number of orders this vehicle has .
*/
2022-02-12 19:28:34 +01:00
inline VehicleOrderID GetNumOrders ( ) const { return ( this - > orders = = nullptr ) ? 0 : this - > orders - > GetNumOrders ( ) ; }
2009-01-03 14:20:32 +01:00
2010-12-26 14:25:34 +01:00
/**
* Get the number of manually added orders this vehicle has .
* @ return the number of manually added orders this vehicle has .
*/
2022-02-12 19:28:34 +01:00
inline VehicleOrderID GetNumManualOrders ( ) const { return ( this - > orders = = nullptr ) ? 0 : this - > orders - > GetNumManualOrders ( ) ; }
2010-12-26 14:25:34 +01:00
2013-05-19 16:22:04 +02:00
/**
* Get the next station the vehicle will stop at .
* @ return ID of the next station the vehicle will stop at or INVALID_STATION .
*/
2013-10-20 15:47:58 +02:00
inline StationIDStack GetNextStoppingStation ( ) const
2013-05-19 16:22:04 +02:00
{
2022-02-12 19:28:34 +01:00
return ( this - > orders = = nullptr ) ? INVALID_STATION : this - > orders - > GetNextStoppingStation ( this ) ;
2013-05-19 16:22:04 +02:00
}
2013-07-06 19:01:31 +02:00
void ResetRefitCaps ( ) ;
2024-03-27 21:20:27 +01:00
void ReleaseUnitNumber ( ) ;
2008-08-16 16:02:20 +02:00
/**
* Copy certain configurations and statistics of a vehicle after successful autoreplace / renew
* The function shall copy everything that cannot be copied by a command ( like orders / group etc ) ,
* and that shall not be resetted for the new vehicle .
* @ param src The old vehicle
*/
2024-02-25 13:36:13 +01:00
inline void CopyVehicleConfigAndStatistics ( Vehicle * src )
2008-08-16 16:02:20 +02:00
{
2012-07-29 18:44:39 +02:00
this - > CopyConsistPropertiesFrom ( src ) ;
2024-03-27 21:20:27 +01:00
this - > ReleaseUnitNumber ( ) ;
2008-08-16 16:02:20 +02:00
this - > unitnumber = src - > unitnumber ;
this - > current_order = src - > current_order ;
this - > dest_tile = src - > dest_tile ;
this - > profit_this_year = src - > profit_this_year ;
this - > profit_last_year = src - > profit_last_year ;
2024-02-25 13:36:13 +01:00
src - > unitnumber = 0 ;
2008-08-16 16:02:20 +02:00
}
2010-08-28 16:14:37 +02:00
bool HandleBreakdown ( ) ;
2010-08-28 16:01:50 +02:00
2012-04-17 21:44:02 +02:00
bool NeedsAutorenewing ( const Company * c , bool use_renew_setting = true ) const ;
2008-04-05 12:55:50 +02:00
2008-04-08 17:48:32 +02:00
bool NeedsServicing ( ) const ;
bool NeedsAutomaticServicing ( ) const ;
2008-04-05 12:55:50 +02:00
/**
* Determine the location for the station where the vehicle goes to next .
* Things done for example are allocating slots in a road stop or exact
* location of the platform is determined for ships .
* @ param station the station to make the next location of the vehicle .
* @ return the location ( tile ) to aim for .
*/
2023-09-16 22:20:53 +02:00
virtual TileIndex GetOrderStationLocation ( [ [ maybe_unused ] ] StationID station ) { return INVALID_TILE ; }
2008-04-11 10:14:43 +02:00
2024-04-03 23:16:36 +02:00
virtual TileIndex GetCargoTile ( ) const { return this - > tile ; }
2008-04-11 10:14:43 +02:00
/**
* Find the closest depot for this vehicle and tell us the location ,
* DestinationID and whether we should reverse .
2023-01-03 22:33:09 +01:00
* @ return A structure with information about the closest depot , if found .
2008-04-11 10:14:43 +02:00
*/
2023-01-03 22:33:09 +01:00
virtual ClosestDepot FindClosestDepot ( ) { return { } ; }
2008-04-11 10:40:10 +02:00
2019-01-15 00:33:42 +01:00
virtual void SetDestTile ( TileIndex tile ) { this - > dest_tile = tile ; }
2009-02-09 22:20:05 +01:00
CommandCost SendToDepot ( DoCommandFlag flags , DepotCommand command ) ;
2009-05-09 15:37:18 +02:00
2010-11-18 15:09:39 +01:00
void UpdateVisualEffect ( bool allow_power_change = true ) ;
2010-11-18 15:15:27 +01:00
void ShowVisualEffect ( ) const ;
2014-09-20 17:31:26 +02:00
void UpdatePosition ( ) ;
void UpdateViewport ( bool dirty ) ;
2021-01-17 19:57:16 +01:00
void UpdateBoundingBoxCoordinates ( bool update_cache ) const ;
2014-09-20 17:31:26 +02:00
void UpdatePositionAndViewport ( ) ;
2021-01-17 19:57:16 +01:00
bool MarkAllViewportsDirty ( ) const ;
2014-09-20 17:31:26 +02:00
2023-05-08 19:01:06 +02:00
inline uint16_t GetServiceInterval ( ) const { return this - > service_interval ; }
2013-02-14 18:04:01 +01:00
2023-05-08 19:01:06 +02:00
inline void SetServiceInterval ( uint16_t interval ) { this - > service_interval = interval ; }
2013-02-14 18:06:49 +01:00
2013-02-14 18:24:55 +01:00
inline bool ServiceIntervalIsCustom ( ) const { return HasBit ( this - > vehicle_flags , VF_SERVINT_IS_CUSTOM ) ; }
2013-02-14 18:06:49 +01:00
2013-02-14 18:24:55 +01:00
inline bool ServiceIntervalIsPercent ( ) const { return HasBit ( this - > vehicle_flags , VF_SERVINT_IS_PERCENT ) ; }
2013-02-14 18:06:49 +01:00
2013-02-14 18:24:55 +01:00
inline void SetServiceIntervalIsCustom ( bool on ) { SB ( this - > vehicle_flags , VF_SERVINT_IS_CUSTOM , 1 , on ) ; }
inline void SetServiceIntervalIsPercent ( bool on ) { SB ( this - > vehicle_flags , VF_SERVINT_IS_PERCENT , 1 , on ) ; }
2013-02-14 18:06:49 +01:00
2024-03-09 14:28:05 +01:00
bool HasFullLoadOrder ( ) const ;
bool HasConditionalOrder ( ) const ;
2024-02-03 14:04:24 +01:00
bool HasUnbunchingOrder ( ) const ;
void LeaveUnbunchingDepot ( ) ;
bool IsWaitingForUnbunching ( ) const ;
2011-01-31 21:44:15 +01:00
private :
2009-05-09 15:37:18 +02:00
/**
2011-01-31 21:44:15 +01:00
* Advance cur_real_order_index to the next real order .
2011-05-18 14:19:58 +02:00
* cur_implicit_order_index is not touched .
2011-01-31 21:44:15 +01:00
*/
void SkipToNextRealOrderIndex ( )
{
if ( this - > GetNumManualOrders ( ) > 0 ) {
/* Advance to next real order */
do {
this - > cur_real_order_index + + ;
if ( this - > cur_real_order_index > = this - > GetNumOrders ( ) ) this - > cur_real_order_index = 0 ;
2011-05-18 14:19:58 +02:00
} while ( this - > GetOrder ( this - > cur_real_order_index ) - > IsType ( OT_IMPLICIT ) ) ;
2011-01-31 21:44:15 +01:00
} else {
this - > cur_real_order_index = 0 ;
}
}
public :
/**
2011-05-18 14:19:58 +02:00
* Increments cur_implicit_order_index , keeps care of the wrap - around and invalidates the GUI .
2011-01-31 21:44:15 +01:00
* cur_real_order_index is incremented as well , if needed .
2009-05-09 15:37:18 +02:00
* Note : current_order is not invalidated .
*/
2011-05-18 14:19:58 +02:00
void IncrementImplicitOrderIndex ( )
2009-05-09 16:23:19 +02:00
{
2011-05-18 14:19:58 +02:00
if ( this - > cur_implicit_order_index = = this - > cur_real_order_index ) {
2011-01-31 21:44:15 +01:00
/* Increment real order index as well */
this - > SkipToNextRealOrderIndex ( ) ;
}
assert ( this - > cur_real_order_index = = 0 | | this - > cur_real_order_index < this - > GetNumOrders ( ) ) ;
2011-05-18 14:19:58 +02:00
/* Advance to next implicit order */
2011-01-31 21:44:15 +01:00
do {
2011-05-18 14:19:58 +02:00
this - > cur_implicit_order_index + + ;
if ( this - > cur_implicit_order_index > = this - > GetNumOrders ( ) ) this - > cur_implicit_order_index = 0 ;
} while ( this - > cur_implicit_order_index ! = this - > cur_real_order_index & & ! this - > GetOrder ( this - > cur_implicit_order_index ) - > IsType ( OT_IMPLICIT ) ) ;
2011-01-31 21:44:15 +01:00
2009-05-09 15:37:18 +02:00
InvalidateVehicleOrder ( this , 0 ) ;
}
2009-05-23 14:27:42 +02:00
2011-01-31 21:44:15 +01:00
/**
* Advanced cur_real_order_index to the next real order , keeps care of the wrap - around and invalidates the GUI .
2011-05-18 14:19:58 +02:00
* 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
* but not any implicit orders .
2011-01-31 21:44:15 +01:00
* Note : current_order is not invalidated .
*/
void IncrementRealOrderIndex ( )
{
2011-05-18 14:19:58 +02:00
if ( this - > cur_implicit_order_index = = this - > cur_real_order_index ) {
/* Increment both real and implicit order */
this - > IncrementImplicitOrderIndex ( ) ;
2011-01-31 21:44:15 +01:00
} else {
/* Increment real order only */
this - > SkipToNextRealOrderIndex ( ) ;
InvalidateVehicleOrder ( this , 0 ) ;
}
}
/**
2011-05-18 14:19:58 +02:00
* Skip implicit orders until cur_real_order_index is a non - implicit order .
2011-01-31 21:44:15 +01:00
*/
void UpdateRealOrderIndex ( )
{
/* Make sure the index is valid */
if ( this - > cur_real_order_index > = this - > GetNumOrders ( ) ) this - > cur_real_order_index = 0 ;
if ( this - > GetNumManualOrders ( ) > 0 ) {
/* Advance to next real order */
2011-05-18 14:19:58 +02:00
while ( this - > GetOrder ( this - > cur_real_order_index ) - > IsType ( OT_IMPLICIT ) ) {
2011-01-31 21:44:15 +01:00
this - > cur_real_order_index + + ;
if ( this - > cur_real_order_index > = this - > GetNumOrders ( ) ) this - > cur_real_order_index = 0 ;
}
} else {
this - > cur_real_order_index = 0 ;
}
}
2009-05-23 14:27:42 +02:00
/**
2019-04-10 23:07:06 +02:00
* Returns order ' index ' of a vehicle or nullptr when it doesn ' t exists
2009-05-23 14:27:42 +02:00
* @ param index the order to fetch
* @ return the found ( or not ) order
*/
inline Order * GetOrder ( int index ) const
{
2022-02-12 19:28:34 +01:00
return ( this - > orders = = nullptr ) ? nullptr : this - > orders - > GetOrderAt ( index ) ;
2009-05-23 14:27:42 +02:00
}
/**
2019-04-10 23:07:06 +02:00
* Returns the last order of a vehicle , or nullptr if it doesn ' t exists
2009-05-23 14:27:42 +02:00
* @ return last order of a vehicle , if available
*/
inline Order * GetLastOrder ( ) const
{
2022-02-12 19:28:34 +01:00
return ( this - > orders = = nullptr ) ? nullptr : this - > orders - > GetLastOrder ( ) ;
2009-05-23 14:27:42 +02:00
}
2009-07-13 18:35:22 +02:00
bool IsEngineCountable ( ) const ;
2011-09-19 21:23:23 +02:00
bool HasEngineType ( ) const ;
2010-12-11 14:48:30 +01:00
bool HasDepotOrder ( ) const ;
2010-12-13 22:55:06 +01:00
void HandlePathfindingResult ( bool path_found ) ;
2011-01-29 18:26:23 +01:00
/**
* Check if the vehicle is a front engine .
* @ return Returns true if the vehicle is a front engine .
*/
2023-01-24 22:50:53 +01:00
debug_inline bool IsFrontEngine ( ) const
2011-01-29 18:26:23 +01:00
{
return this - > IsGroundVehicle ( ) & & HasBit ( this - > subtype , GVSF_FRONT ) ;
}
/**
* Check if the vehicle is an articulated part of an engine .
* @ return Returns true if the vehicle is an articulated part .
*/
2011-12-20 18:57:56 +01:00
inline bool IsArticulatedPart ( ) const
2011-01-29 18:26:23 +01:00
{
return this - > IsGroundVehicle ( ) & & HasBit ( this - > subtype , GVSF_ARTICULATED_PART ) ;
}
/**
* Check if an engine has an articulated part .
* @ return True if the engine has an articulated part .
*/
2011-12-20 18:57:56 +01:00
inline bool HasArticulatedPart ( ) const
2011-01-29 18:26:23 +01:00
{
2019-04-10 23:07:06 +02:00
return this - > Next ( ) ! = nullptr & & this - > Next ( ) - > IsArticulatedPart ( ) ;
2011-01-29 18:26:23 +01:00
}
2011-01-29 18:27:32 +01:00
/**
* Get the next part of an articulated engine .
* @ return Next part of the articulated engine .
* @ pre The vehicle is an articulated engine .
*/
2011-12-20 18:57:56 +01:00
inline Vehicle * GetNextArticulatedPart ( ) const
2011-01-29 18:27:32 +01:00
{
assert ( this - > HasArticulatedPart ( ) ) ;
return this - > Next ( ) ;
}
/**
* Get the first part of an articulated engine .
* @ return First part of the engine .
*/
2011-12-20 18:57:56 +01:00
inline Vehicle * GetFirstEnginePart ( )
2011-01-29 18:27:32 +01:00
{
Vehicle * v = this ;
while ( v - > IsArticulatedPart ( ) ) v = v - > Previous ( ) ;
return v ;
}
/**
* Get the first part of an articulated engine .
* @ return First part of the engine .
*/
2011-12-20 18:57:56 +01:00
inline const Vehicle * GetFirstEnginePart ( ) const
2011-01-29 18:27:32 +01:00
{
const Vehicle * v = this ;
while ( v - > IsArticulatedPart ( ) ) v = v - > Previous ( ) ;
return v ;
}
/**
* Get the last part of an articulated engine .
* @ return Last part of the engine .
*/
2011-12-20 18:57:56 +01:00
inline Vehicle * GetLastEnginePart ( )
2011-01-29 18:27:32 +01:00
{
Vehicle * v = this ;
while ( v - > HasArticulatedPart ( ) ) v = v - > GetNextArticulatedPart ( ) ;
return v ;
}
/**
* Get the next real ( non - articulated part ) vehicle in the consist .
* @ return Next vehicle in the consist .
*/
2011-12-20 18:57:56 +01:00
inline Vehicle * GetNextVehicle ( ) const
2011-01-29 18:27:32 +01:00
{
const Vehicle * v = this ;
while ( v - > HasArticulatedPart ( ) ) v = v - > GetNextArticulatedPart ( ) ;
/* v now contains the last articulated part in the engine */
return v - > Next ( ) ;
}
/**
* Get the previous real ( non - articulated part ) vehicle in the consist .
* @ return Previous vehicle in the consist .
*/
2011-12-20 18:57:56 +01:00
inline Vehicle * GetPrevVehicle ( ) const
2011-01-29 18:27:32 +01:00
{
Vehicle * v = this - > Previous ( ) ;
2019-04-10 23:07:06 +02:00
while ( v ! = nullptr & & v - > IsArticulatedPart ( ) ) v = v - > Previous ( ) ;
2011-01-29 18:27:32 +01:00
return v ;
}
2020-12-27 00:13:56 +01:00
/**
* Iterator to iterate orders
* Supports deletion of current order
*/
struct OrderIterator {
typedef Order value_type ;
2024-01-03 22:33:38 +01:00
typedef Order * pointer ;
typedef Order & reference ;
2020-12-27 00:13:56 +01:00
typedef size_t difference_type ;
typedef std : : forward_iterator_tag iterator_category ;
explicit OrderIterator ( OrderList * list ) : list ( list ) , prev ( nullptr )
{
this - > order = ( this - > list = = nullptr ) ? nullptr : this - > list - > GetFirstOrder ( ) ;
}
bool operator = = ( const OrderIterator & other ) const { return this - > order = = other . order ; }
bool operator ! = ( const OrderIterator & other ) const { return ! ( * this = = other ) ; }
Order * operator * ( ) const { return this - > order ; }
OrderIterator & operator + + ( )
{
this - > prev = ( this - > prev = = nullptr ) ? this - > list - > GetFirstOrder ( ) : this - > prev - > next ;
this - > order = ( this - > prev = = nullptr ) ? nullptr : this - > prev - > next ;
return * this ;
}
private :
OrderList * list ;
Order * order ;
Order * prev ;
} ;
/**
* Iterable ensemble of orders
*/
struct IterateWrapper {
OrderList * list ;
IterateWrapper ( OrderList * list = nullptr ) : list ( list ) { }
OrderIterator begin ( ) { return OrderIterator ( this - > list ) ; }
OrderIterator end ( ) { return OrderIterator ( nullptr ) ; }
bool empty ( ) { return this - > begin ( ) = = this - > end ( ) ; }
} ;
/**
* Returns an iterable ensemble of orders of a vehicle
* @ return an iterable ensemble of orders of a vehicle
*/
2022-02-12 19:28:34 +01:00
IterateWrapper Orders ( ) const { return IterateWrapper ( this - > orders ) ; }
2022-10-31 20:47:25 +01:00
2023-05-08 19:01:06 +02:00
uint32_t GetDisplayMaxWeight ( ) const ;
uint32_t GetDisplayMinPowerToWeight ( ) const ;
2007-04-29 23:24:08 +02:00
} ;
2009-05-27 00:10:13 +02:00
/**
* Class defining several overloaded accessors so we don ' t
* have to cast vehicle types that often
*/
template < class T , VehicleType Type >
struct SpecializedVehicle : public Vehicle {
static const VehicleType EXPECTED_TYPE = Type ; ///< Specialized type
2011-01-21 15:43:38 +01:00
typedef SpecializedVehicle < T , Type > SpecializedVehicleBase ; ///< Our type
2009-05-30 22:13:12 +02:00
/**
* Set vehicle type correctly
*/
2016-10-16 16:59:44 +02:00
inline SpecializedVehicle < T , Type > ( ) : Vehicle ( Type )
{
2021-01-03 14:32:58 +01:00
this - > sprite_cache . sprite_seq . count = 1 ;
2016-10-16 16:59:44 +02:00
}
2009-05-30 22:13:12 +02:00
2009-05-27 00:10:13 +02:00
/**
* Get the first vehicle in the chain
* @ return first vehicle in the chain
*/
2011-12-20 18:57:56 +01:00
inline T * First ( ) const { return ( T * ) this - > Vehicle : : First ( ) ; }
2009-05-27 00:10:13 +02:00
2009-07-20 21:58:33 +02:00
/**
* Get the last vehicle in the chain
* @ return last vehicle in the chain
*/
2011-12-20 18:57:56 +01:00
inline T * Last ( ) { return ( T * ) this - > Vehicle : : Last ( ) ; }
2009-07-20 21:58:33 +02:00
/**
* Get the last vehicle in the chain
* @ return last vehicle in the chain
*/
2011-12-20 18:57:56 +01:00
inline const T * Last ( ) const { return ( const T * ) this - > Vehicle : : Last ( ) ; }
2009-07-20 21:58:33 +02:00
2009-05-27 00:10:13 +02:00
/**
* Get next vehicle in the chain
* @ return next vehicle in the chain
*/
2011-12-20 18:57:56 +01:00
inline T * Next ( ) const { return ( T * ) this - > Vehicle : : Next ( ) ; }
2009-05-27 00:10:13 +02:00
/**
* Get previous vehicle in the chain
* @ return previous vehicle in the chain
*/
2011-12-20 18:57:56 +01:00
inline T * Previous ( ) const { return ( T * ) this - > Vehicle : : Previous ( ) ; }
2009-05-27 00:10:13 +02:00
2011-01-29 18:27:32 +01:00
/**
* Get the next part of an articulated engine .
* @ return Next part of the articulated engine .
* @ pre The vehicle is an articulated engine .
*/
2011-12-20 18:57:56 +01:00
inline T * GetNextArticulatedPart ( ) { return ( T * ) this - > Vehicle : : GetNextArticulatedPart ( ) ; }
2011-01-29 18:27:32 +01:00
/**
* Get the next part of an articulated engine .
* @ return Next part of the articulated engine .
* @ pre The vehicle is an articulated engine .
*/
2011-12-20 18:57:56 +01:00
inline T * GetNextArticulatedPart ( ) const { return ( T * ) this - > Vehicle : : GetNextArticulatedPart ( ) ; }
2011-01-29 18:27:32 +01:00
/**
* Get the first part of an articulated engine .
* @ return First part of the engine .
*/
2011-12-20 18:57:56 +01:00
inline T * GetFirstEnginePart ( ) { return ( T * ) this - > Vehicle : : GetFirstEnginePart ( ) ; }
2011-01-29 18:27:32 +01:00
/**
* Get the first part of an articulated engine .
* @ return First part of the engine .
*/
2011-12-20 18:57:56 +01:00
inline const T * GetFirstEnginePart ( ) const { return ( const T * ) this - > Vehicle : : GetFirstEnginePart ( ) ; }
2011-01-29 18:27:32 +01:00
/**
* Get the last part of an articulated engine .
* @ return Last part of the engine .
*/
2011-12-20 18:57:56 +01:00
inline T * GetLastEnginePart ( ) { return ( T * ) this - > Vehicle : : GetLastEnginePart ( ) ; }
2011-01-29 18:27:32 +01:00
/**
* Get the next real ( non - articulated part ) vehicle in the consist .
* @ return Next vehicle in the consist .
*/
2011-12-20 18:57:56 +01:00
inline T * GetNextVehicle ( ) const { return ( T * ) this - > Vehicle : : GetNextVehicle ( ) ; }
2011-01-29 18:27:32 +01:00
/**
* Get the previous real ( non - articulated part ) vehicle in the consist .
* @ return Previous vehicle in the consist .
*/
2011-12-20 18:57:56 +01:00
inline T * GetPrevVehicle ( ) const { return ( T * ) this - > Vehicle : : GetPrevVehicle ( ) ; }
2009-05-27 00:10:13 +02:00
/**
* Tests whether given index is a valid index for vehicle of this type
* @ param index tested index
* @ return is this index valid index of T ?
*/
2011-12-20 18:57:56 +01:00
static inline bool IsValidID ( size_t index )
2009-05-27 00:10:13 +02:00
{
return Vehicle : : IsValidID ( index ) & & Vehicle : : Get ( index ) - > type = = Type ;
}
/**
* Gets vehicle with given index
* @ return pointer to vehicle with given index casted to T *
*/
2011-12-20 18:57:56 +01:00
static inline T * Get ( size_t index )
2009-05-27 00:10:13 +02:00
{
return ( T * ) Vehicle : : Get ( index ) ;
}
/**
* Returns vehicle if the index is a valid index for this vehicle type
* @ return pointer to vehicle with given index if it ' s a vehicle of this type
*/
2011-12-20 18:57:56 +01:00
static inline T * GetIfValid ( size_t index )
2009-05-27 00:10:13 +02:00
{
2019-04-10 23:07:06 +02:00
return IsValidID ( index ) ? Get ( index ) : nullptr ;
2009-05-27 00:10:13 +02:00
}
2009-06-06 18:54:22 +02:00
/**
* Converts a Vehicle to SpecializedVehicle with type checking .
* @ param v Vehicle pointer
* @ return pointer to SpecializedVehicle
*/
2011-12-20 18:57:56 +01:00
static inline T * From ( Vehicle * v )
2009-06-06 18:54:22 +02:00
{
assert ( v - > type = = Type ) ;
return ( T * ) v ;
}
/**
* Converts a const Vehicle to const SpecializedVehicle with type checking .
* @ param v Vehicle pointer
* @ return pointer to SpecializedVehicle
*/
2011-12-20 18:57:56 +01:00
static inline const T * From ( const Vehicle * v )
2009-06-06 18:54:22 +02:00
{
assert ( v - > type = = Type ) ;
return ( const T * ) v ;
}
2010-05-04 01:36:17 +02:00
/**
* Update vehicle sprite - and position caches
2012-01-02 14:44:37 +01:00
* @ param force_update Force updating the vehicle on the viewport .
* @ param update_delta Also update the delta ?
2010-05-04 01:36:17 +02:00
*/
2012-01-02 14:44:37 +01:00
inline void UpdateViewport ( bool force_update , bool update_delta )
2010-05-04 01:36:17 +02:00
{
2021-01-02 23:39:30 +01:00
bool sprite_has_changed = false ;
2016-05-22 13:30:25 +02:00
/* Skip updating sprites on dedicated servers without screen */
if ( _network_dedicated ) return ;
2010-05-04 01:36:17 +02:00
/* Explicitly choose method to call to prevent vtable dereference -
* it gives ~ 3 % runtime improvements in games with many vehicles */
2018-05-22 19:43:34 +02:00
if ( update_delta ) ( ( T * ) this ) - > T : : UpdateDeltaXY ( ) ;
2021-01-02 23:39:30 +01:00
/*
* Only check for a new sprite sequence if the vehicle direction
* has changed since we last checked it , assuming that otherwise
* there won ' t be enough change in bounding box or offsets to need
* to resolve a new sprite .
*/
2021-01-03 14:32:58 +01:00
if ( this - > direction ! = this - > sprite_cache . last_direction | | this - > sprite_cache . is_viewport_candidate ) {
2021-01-02 23:39:30 +01:00
VehicleSpriteSeq seq ;
( ( T * ) this ) - > T : : GetImage ( this - > direction , EIT_ON_MAP , & seq ) ;
2021-01-03 14:32:58 +01:00
if ( this - > sprite_cache . sprite_seq ! = seq ) {
2021-01-02 23:39:30 +01:00
sprite_has_changed = true ;
2021-01-03 14:32:58 +01:00
this - > sprite_cache . sprite_seq = seq ;
2021-01-02 23:39:30 +01:00
}
2021-01-03 14:32:58 +01:00
this - > sprite_cache . last_direction = this - > direction ;
2021-01-17 19:57:16 +01:00
this - > sprite_cache . revalidate_before_draw = false ;
2021-01-02 23:39:30 +01:00
} else {
/*
2021-01-17 19:57:16 +01:00
* A change that could potentially invalidate the sprite has been
* made , signal that we should still resolve it before drawing on a
* viewport .
2021-01-02 23:39:30 +01:00
*/
2021-01-17 19:57:16 +01:00
this - > sprite_cache . revalidate_before_draw = true ;
2021-01-02 23:39:30 +01:00
}
if ( force_update | | sprite_has_changed ) {
2016-10-16 16:57:56 +02:00
this - > Vehicle : : UpdateViewport ( true ) ;
}
2010-05-04 01:36:17 +02:00
}
2009-05-27 00:10:13 +02:00
2019-12-17 03:37:43 +01:00
/**
* Returns an iterable ensemble of all valid vehicles of type T
* @ param from index of the first vehicle to consider
* @ return an iterable ensemble of all valid vehicles of type T
*/
static Pool : : IterateWrapper < T > Iterate ( size_t from = 0 ) { return Pool : : IterateWrapper < T > ( from ) ; }
} ;
2009-05-27 00:10:13 +02:00
2011-01-31 21:27:33 +01:00
/** Sentinel for an invalid coordinate. */
2023-05-08 19:01:06 +02:00
static const int32_t INVALID_COORD = 0x7fffffff ;
2009-01-04 16:32:25 +01:00
2007-12-27 14:35:39 +01:00
# endif /* VEHICLE_BASE_H */