File diff r20251:8c2b509af318 → r20252:76a6f1c78ce7
src/vehicle_base.h
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * 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/>.
 
 */
 

	
 
/** @file  vehicle_base.h Base class for all vehicles. */
 

	
 
#ifndef VEHICLE_BASE_H
 
#define VEHICLE_BASE_H
 

	
 
#include "core/smallmap_type.hpp"
 
#include "track_type.h"
 
#include "command_type.h"
 
#include "order_base.h"
 
#include "cargopacket.h"
 
#include "texteff.hpp"
 
#include "engine_type.h"
 
#include "order_func.h"
 
#include "transport_type.h"
 
#include "group_type.h"
 
#include "base_consist.h"
 

	
 
/** Vehicle status bits in #Vehicle::vehstatus. */
 
enum VehStatus {
 
	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.
 
};
 

	
 
/** Bit numbers in #Vehicle::vehicle_flags. */
 
enum VehicleFlags {
 
	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).
 
	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
 
	VF_STOP_LOADING,            ///< Don't load anymore during the next load cycle.
 
	VF_PATHFINDER_LOST,         ///< Vehicle's pathfinder is lost.
 
	VF_SERVINT_IS_CUSTOM,       ///< Service interval is custom.
 
	VF_SERVINT_IS_PERCENT,      ///< Service interval is percent.
 
};
 

	
 
/** 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.
 
	NCVV_END,                           ///< End of the bits.
 
};
 

	
 
/** Cached often queried (NewGRF) values */
 
struct NewGRFCache {
 
@@ -166,142 +167,148 @@ public:
 

	
 
	/* Related to age and service time */
 
	Year build_year;                    ///< Year the vehicle has been built.
 
	Date age;                           ///< Age in days
 
	Date max_age;                       ///< Maximum age
 
	Date date_of_last_service;          ///< Last date the vehicle had a service at a depot.
 
	uint16 reliability;                 ///< Reliability.
 
	uint16 reliability_spd_dec;         ///< Reliability decrease speed.
 
	byte breakdown_ctr;                 ///< Counter for managing breakdown events. @see Vehicle::HandleBreakdown
 
	byte breakdown_delay;               ///< Counter for managing breakdown length.
 
	byte breakdowns_since_last_service; ///< Counter for the amount of breakdowns.
 
	byte breakdown_chance;              ///< Current chance of breakdowns.
 

	
 
	int32 x_pos;                        ///< x coordinate.
 
	int32 y_pos;                        ///< y coordinate.
 
	int32 z_pos;                        ///< z coordinate.
 
	DirectionByte direction;            ///< facing
 

	
 
	OwnerByte owner;                    ///< Which company owns the vehicle?
 
	/**
 
	 * currently displayed sprite index
 
	 * 0xfd == custom sprite, 0xfe == custom second head sprite
 
	 * 0xff == reserved for another custom sprite
 
	 */
 
	byte spritenum;
 
	SpriteID cur_image;                 ///< sprite number for this vehicle
 
	byte x_extent;                      ///< x-extent of vehicle bounding box
 
	byte y_extent;                      ///< y-extent of vehicle bounding box
 
	byte z_extent;                      ///< z-extent of vehicle bounding box
 
	int8 x_bb_offs;                     ///< x offset of vehicle bounding box
 
	int8 y_bb_offs;                     ///< y offset of vehicle bounding box
 
	int8 x_offs;                        ///< x offset for vehicle sprite
 
	int8 y_offs;                        ///< y offset for vehicle sprite
 
	EngineID engine_type;               ///< The type of engine used for this vehicle.
 

	
 
	TextEffectID fill_percent_te_id;    ///< a text-effect id to a loading indicator object
 
	UnitID unitnumber;                  ///< unit number, for display purposes only
 

	
 
	uint16 cur_speed;                   ///< current speed
 
	byte subspeed;                      ///< fractional speed
 
	byte acceleration;                  ///< used by train & aircraft
 
	uint32 motion_counter;              ///< counter to occasionally play a vehicle sound.
 
	byte progress;                      ///< The percentage (if divided by 256) this vehicle already crossed the tile unit.
 

	
 
	byte random_bits;                   ///< Bits used for determining which randomized variational spritegroups to use when drawing.
 
	byte waiting_triggers;              ///< Triggers to be yet matched before rerandomizing the random bits.
 

	
 
	StationID last_station_visited;     ///< The last station we stopped at.
 
	StationID last_loading_station;     ///< Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
 

	
 
	CargoID cargo_type;                 ///< type of cargo this vehicle is carrying
 
	byte cargo_subtype;                 ///< Used for livery refits (NewGRF variations)
 
	uint16 cargo_cap;                   ///< total capacity
 
	uint16 refit_cap;                   ///< Capacity left over from before last refit.
 
	VehicleCargoList cargo;             ///< The cargo this vehicle is carrying
 
	uint16 cargo_age_counter;           ///< Ticks till cargo is aged next.
 

	
 
	byte day_counter;                   ///< Increased by one for each day
 
	byte tick_counter;                  ///< Increased by one for each tick
 
	byte running_ticks;                 ///< Number of ticks this vehicle was not stopped this day
 

	
 
	byte vehstatus;                     ///< Status
 
	Order current_order;                ///< The current order (+ status, like: loading)
 

	
 
	union {
 
		OrderList *list;            ///< Pointer to the order list for this vehicle
 
		Order     *old;             ///< Only used during conversion of old save games
 
	} orders;                           ///< The orders currently assigned to the vehicle.
 

	
 
	uint16 load_unload_ticks;           ///< Ticks to wait before starting next cycle.
 
	GroupID group_id;                   ///< Index of group Pool array
 
	byte subtype;                       ///< subtype (Filled with values from #EffectVehicles/#TrainSubTypes/#AircraftSubTypes)
 

	
 
	NewGRFCache grf_cache;              ///< Cache of often used calculated NewGRF values
 
	VehicleCache vcache;                ///< Cache of often used vehicle values.
 

	
 
	Vehicle(VehicleType type = VEH_INVALID);
 

	
 
	void PreDestructor();
 
	/** We want to 'destruct' the right class. */
 
	virtual ~Vehicle();
 

	
 
	void BeginLoading();
 
	void CancelReservation(Station *st);
 
	void LeaveStation();
 

	
 
	GroundVehicleCache *GetGroundVehicleCache();
 
	const GroundVehicleCache *GetGroundVehicleCache() const;
 

	
 
	uint16 &GetGroundVehicleFlags();
 
	const uint16 &GetGroundVehicleFlags() const;
 

	
 
	void DeleteUnreachedImplicitOrders();
 

	
 
	void HandleLoading(bool mode = false);
 

	
 
	void GetConsistFreeCapacities(SmallMap<CargoID, uint> &capacities) const;
 

	
 
	uint GetConsistTotalCapacity() const;
 

	
 
	/**
 
	 * Marks the vehicles to be redrawn and updates cached variables
 
	 *
 
	 * This method marks the area of the vehicle on the screen as dirty.
 
	 * It can be use to repaint the vehicle.
 
	 *
 
	 * @ingroup dirty
 
	 */
 
	virtual void MarkDirty() {}
 

	
 
	/**
 
	 * Updates the x and y offsets and the size of the sprite used
 
	 * for this vehicle.
 
	 * @param direction the direction the vehicle is facing
 
	 */
 
	virtual void UpdateDeltaXY(Direction direction) {}
 

	
 
	/**
 
	 * 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.
 
	 */
 
	inline uint GetOldAdvanceSpeed(uint speed)
 
	{
 
		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().
 
	 */
 
	static inline uint GetAdvanceSpeed(uint speed)
 
@@ -553,96 +560,107 @@ public:
 
	}
 

	
 
	/**
 
	 * Get the first order of the vehicles order list.
 
	 * @return first order of order list.
 
	 */
 
	inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
 

	
 
	void AddToShared(Vehicle *shared_chain);
 
	void RemoveFromShared();
 

	
 
	/**
 
	 * Get the next vehicle of the shared vehicle chain.
 
	 * @return the next shared vehicle or NULL when there isn't a next vehicle.
 
	 */
 
	inline Vehicle *NextShared() const { return this->next_shared; }
 

	
 
	/**
 
	 * Get the previous vehicle of the shared vehicle chain
 
	 * @return the previous shared vehicle or NULL when there isn't a previous vehicle.
 
	 */
 
	inline Vehicle *PreviousShared() const { return this->previous_shared; }
 

	
 
	/**
 
	 * Get the first vehicle of this vehicle chain.
 
	 * @return the first vehicle of the chain.
 
	 */
 
	inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? this->First() : this->orders.list->GetFirstSharedVehicle(); }
 

	
 
	/**
 
	 * Check if we share our orders with another vehicle.
 
	 * @return true if there are other vehicles sharing the same order
 
	 */
 
	inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
 

	
 
	/**
 
	 * Get the number of orders this vehicle has.
 
	 * @return the number of orders this vehicle has.
 
	 */
 
	inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
 

	
 
	/**
 
	 * Get the number of manually added orders this vehicle has.
 
	 * @return the number of manually added orders this vehicle has.
 
	 */
 
	inline VehicleOrderID GetNumManualOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumManualOrders(); }
 

	
 
	/**
 
	 * Get the next station the vehicle will stop at.
 
	 * @return ID of the next station the vehicle will stop at or INVALID_STATION.
 
	 */
 
	inline StationID GetNextStoppingStation() const
 
	{
 
		return (this->orders.list == NULL) ? INVALID_STATION : this->orders.list->GetNextStoppingStation(this);
 
	}
 

	
 
	void RefreshNextHopsStats();
 

	
 
	/**
 
	 * 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
 
	 */
 
	inline void CopyVehicleConfigAndStatistics(const Vehicle *src)
 
	{
 
		this->CopyConsistPropertiesFrom(src);
 

	
 
		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;
 
	}
 

	
 

	
 
	bool HandleBreakdown();
 

	
 
	bool NeedsAutorenewing(const Company *c, bool use_renew_setting = true) const;
 

	
 
	bool NeedsServicing() const;
 
	bool NeedsAutomaticServicing() const;
 

	
 
	/**
 
	 * 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.
 
	 */
 
	virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
 

	
 
	/**
 
	 * Find the closest depot for this vehicle and tell us the location,
 
	 * DestinationID and whether we should reverse.
 
	 * @param location    where do we go to?
 
	 * @param destination what hangar do we go to?
 
	 * @param reverse     should the vehicle be reversed?
 
	 * @return true if a depot could be found.
 
	 */
 
	virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
 

	
 
	CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
 

	
 
	void UpdateVisualEffect(bool allow_power_change = true);