2006-02-03 12:55:21 +00:00
/* $Id$ */
2009-08-21 21:21:05 +01: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/>.
*/
2008-05-06 16:11:33 +01:00
/** @file newgrf_engine.cpp NewGRF handling of engines. */
2007-03-21 03:06:21 +00:00
2006-02-03 12:55:21 +00:00
# include "stdafx.h"
# include "debug.h"
2006-04-28 21:04:57 +01:00
# include "train.h"
2009-05-22 21:22:20 +01:00
# include "roadveh.h"
2008-09-30 21:51:04 +01:00
# include "company_func.h"
2009-06-24 22:33:11 +01:00
# include "newgrf.h"
2009-11-05 19:46:17 +00:00
# include "newgrf_cargo.h"
2006-02-03 12:55:21 +00:00
# include "newgrf_engine.h"
2006-04-28 21:04:57 +01:00
# include "newgrf_spritegroup.h"
2007-12-26 13:50:40 +00:00
# include "date_func.h"
2007-12-27 13:35:39 +00:00
# include "vehicle_func.h"
2008-01-07 14:02:26 +00:00
# include "core/random_func.hpp"
2008-09-22 15:34:38 +01:00
# include "aircraft.h"
2008-12-26 13:50:46 +00:00
# include "core/smallmap_type.hpp"
2009-06-24 18:39:54 +01:00
# include "station_base.h"
2010-01-15 16:41:15 +00:00
# include "engine_base.h"
# include "company_base.h"
2006-05-14 16:11:12 +01:00
2007-03-07 12:11:48 +00:00
struct WagonOverride {
2008-01-05 15:39:22 +00:00
EngineID * train_id ;
uint trains ;
2006-10-17 15:52:55 +01:00
CargoID cargo ;
2006-04-30 19:19:37 +01:00
const SpriteGroup * group ;
2007-03-07 12:11:48 +00:00
} ;
2006-02-03 12:55:21 +00:00
2008-01-05 15:39:22 +00:00
void SetWagonOverrideSprites ( EngineID engine , CargoID cargo , const SpriteGroup * group , EngineID * train_id , uint trains )
2006-02-03 12:55:21 +00:00
{
2009-05-17 00:34:14 +01:00
Engine * e = Engine : : Get ( engine ) ;
2006-02-03 12:55:21 +00:00
WagonOverride * wo ;
2007-02-25 14:33:43 +00:00
assert ( cargo < NUM_CARGO + 2 ) ; // Include CT_DEFAULT and CT_PURCHASE pseudo cargos.
2006-12-18 10:46:06 +00:00
2008-04-29 22:31:29 +01:00
e - > overrides_count + + ;
e - > overrides = ReallocT ( e - > overrides , e - > overrides_count ) ;
2006-02-03 12:55:21 +00:00
2008-04-29 22:31:29 +01:00
wo = & e - > overrides [ e - > overrides_count - 1 ] ;
2006-02-03 12:55:21 +00:00
wo - > group = group ;
2006-10-17 15:52:55 +01:00
wo - > cargo = cargo ;
2006-02-03 12:55:21 +00:00
wo - > trains = trains ;
2008-01-05 15:39:22 +00:00
wo - > train_id = MallocT < EngineID > ( trains ) ;
memcpy ( wo - > train_id , train_id , trains * sizeof * train_id ) ;
2006-02-03 12:55:21 +00:00
}
2008-01-05 15:39:22 +00:00
const SpriteGroup * GetWagonOverrideSpriteSet ( EngineID engine , CargoID cargo , EngineID overriding_engine )
2006-02-03 12:55:21 +00:00
{
2009-05-17 00:34:14 +01:00
const Engine * e = Engine : : Get ( engine ) ;
2006-02-03 12:55:21 +00:00
2007-03-21 03:06:21 +00:00
/* XXX: This could turn out to be a timesink on profiles. We could
* always just dedicate 65535 bytes for an [ engine ] [ train ] trampoline
* for O ( 1 ) . Or O ( logMlogN ) and searching binary tree or smt . like
* that . - - pasky */
2006-02-03 12:55:21 +00:00
2008-04-29 22:31:29 +01:00
for ( uint i = 0 ; i < e - > overrides_count ; i + + ) {
const WagonOverride * wo = & e - > overrides [ i ] ;
2006-02-03 12:55:21 +00:00
2007-05-10 07:42:43 +01:00
if ( wo - > cargo ! = cargo & & wo - > cargo ! = CT_DEFAULT ) continue ;
2008-01-05 15:39:22 +00:00
for ( uint j = 0 ; j < wo - > trains ; j + + ) {
2007-05-10 07:42:43 +01:00
if ( wo - > train_id [ j ] = = overriding_engine ) return wo - > group ;
2006-02-03 12:55:21 +00:00
}
}
return NULL ;
}
/**
* Unload all wagon override sprite groups .
*/
2008-04-29 22:31:29 +01:00
void UnloadWagonOverrides ( Engine * e )
2006-02-03 12:55:21 +00:00
{
2008-04-29 22:31:29 +01:00
for ( uint i = 0 ; i < e - > overrides_count ; i + + ) {
WagonOverride * wo = & e - > overrides [ i ] ;
free ( wo - > train_id ) ;
2006-02-03 12:55:21 +00:00
}
2008-04-29 22:31:29 +01:00
free ( e - > overrides ) ;
e - > overrides_count = 0 ;
e - > overrides = NULL ;
2006-02-03 12:55:21 +00:00
}
2006-04-30 19:19:37 +01:00
void SetCustomEngineSprites ( EngineID engine , byte cargo , const SpriteGroup * group )
2006-02-03 12:55:21 +00:00
{
2009-05-17 00:34:14 +01:00
Engine * e = Engine : : Get ( engine ) ;
2008-04-29 22:31:29 +01:00
assert ( cargo < lengthof ( e - > group ) ) ;
2006-12-18 10:46:06 +00:00
2008-04-29 22:31:29 +01:00
if ( e - > group [ cargo ] ! = NULL ) {
2006-12-26 17:36:18 +00:00
grfmsg ( 6 , " SetCustomEngineSprites: engine %d cargo %d already has group -- replacing " , engine , cargo ) ;
2006-02-03 12:55:21 +00:00
}
2008-04-29 22:31:29 +01:00
e - > group [ cargo ] = group ;
2006-02-03 12:55:21 +00:00
}
2006-05-31 18:31:08 +01:00
/**
* Tie a GRFFile entry to an engine , to allow us to retrieve GRF parameters
* etc during a game .
* @ param engine Engine ID to tie the GRFFile to .
* @ param file Pointer of GRFFile to tie .
*/
void SetEngineGRF ( EngineID engine , const GRFFile * file )
2006-04-23 23:25:33 +01:00
{
2009-05-17 00:34:14 +01:00
Engine * e = Engine : : Get ( engine ) ;
2008-04-29 22:31:29 +01:00
e - > grffile = file ;
2006-04-23 23:25:33 +01:00
}
2006-05-31 18:31:08 +01:00
/**
* Retrieve the GRFFile tied to an engine
* @ param engine Engine ID to retrieve .
* @ return Pointer to GRFFile .
*/
const GRFFile * GetEngineGRF ( EngineID engine )
2006-04-23 23:25:33 +01:00
{
2009-05-17 00:34:14 +01:00
return Engine : : Get ( engine ) - > grffile ;
2006-04-23 23:25:33 +01:00
}
2006-05-31 18:31:08 +01:00
/**
* Retrieve the GRF ID of the GRFFile tied to an engine
* @ param engine Engine ID to retrieve .
* @ return 32 bit GRFID value .
*/
uint32 GetEngineGRFID ( EngineID engine )
{
2009-03-16 08:03:50 +00:00
const GRFFile * file = GetEngineGRF ( engine ) ;
return file = = NULL ? 0 : file - > grfid ;
2006-05-31 18:31:08 +01:00
}
2006-02-03 12:55:21 +00:00
static int MapOldSubType ( const Vehicle * v )
{
2009-06-21 11:11:04 +01:00
switch ( v - > type ) {
case VEH_TRAIN :
2009-07-02 00:57:20 +01:00
if ( Train : : From ( v ) - > IsEngine ( ) ) return 0 ;
2009-07-02 00:49:13 +01:00
if ( Train : : From ( v ) - > IsFreeWagon ( ) ) return 4 ;
2009-06-21 11:11:04 +01:00
return 2 ;
case VEH_ROAD :
case VEH_SHIP : return 0 ;
case VEH_AIRCRAFT :
case VEH_DISASTER : return v - > subtype ;
case VEH_EFFECT : return v - > subtype < < 1 ;
default : NOT_REACHED ( ) ;
}
2006-02-03 12:55:21 +00:00
}
2006-04-28 21:04:57 +01:00
2006-05-01 12:35:18 +01:00
/* TTDP style aircraft movement states for GRF Action 2 Var 0xE2 */
enum {
2006-06-22 22:03:19 +01:00
AMS_TTDP_HANGAR ,
AMS_TTDP_TO_HANGAR ,
2006-05-01 12:35:18 +01:00
AMS_TTDP_TO_PAD1 ,
AMS_TTDP_TO_PAD2 ,
AMS_TTDP_TO_PAD3 ,
AMS_TTDP_TO_ENTRY_2_AND_3 ,
AMS_TTDP_TO_ENTRY_2_AND_3_AND_H ,
AMS_TTDP_TO_JUNCTION ,
AMS_TTDP_LEAVE_RUNWAY ,
AMS_TTDP_TO_INWAY ,
AMS_TTDP_TO_RUNWAY ,
AMS_TTDP_TO_OUTWAY ,
AMS_TTDP_WAITING ,
AMS_TTDP_TAKEOFF ,
AMS_TTDP_TO_TAKEOFF ,
AMS_TTDP_CLIMBING ,
AMS_TTDP_FLIGHT_APPROACH ,
AMS_TTDP_UNUSED_0x11 ,
AMS_TTDP_FLIGHT_TO_TOWER ,
AMS_TTDP_UNUSED_0x13 ,
AMS_TTDP_FLIGHT_FINAL ,
AMS_TTDP_FLIGHT_DESCENT ,
AMS_TTDP_BRAKING ,
2006-05-30 22:23:01 +01:00
AMS_TTDP_HELI_TAKEOFF_AIRPORT ,
AMS_TTDP_HELI_TO_TAKEOFF_AIRPORT ,
AMS_TTDP_HELI_LAND_AIRPORT ,
2006-05-01 12:35:18 +01:00
AMS_TTDP_HELI_TAKEOFF_HELIPORT ,
AMS_TTDP_HELI_TO_TAKEOFF_HELIPORT ,
AMS_TTDP_HELI_LAND_HELIPORT ,
} ;
/**
* Map OTTD aircraft movement states to TTDPatch style movement states
* ( VarAction 2 Variable 0xE2 )
*/
2009-05-22 21:03:26 +01:00
static byte MapAircraftMovementState ( const Aircraft * v )
2006-05-01 12:35:18 +01:00
{
2008-09-22 15:34:38 +01:00
const Station * st = GetTargetAirportIfValid ( v ) ;
if ( st = = NULL ) return AMS_TTDP_FLIGHT_TO_TOWER ;
2007-06-15 09:05:24 +01:00
2010-03-18 21:02:20 +00:00
const AirportFTAClass * afc = st - > airport . GetFTA ( ) ;
2009-05-22 21:07:26 +01:00
uint16 amdflag = afc - > MovingData ( v - > pos ) - > flag ;
2006-05-01 12:35:18 +01:00
2009-05-22 21:07:26 +01:00
switch ( v - > state ) {
2006-05-01 12:35:18 +01:00
case HANGAR :
/* The international airport is a special case as helicopters can land in
* front of the hanger . Helicopters also change their air . state to
* AMED_HELI_LOWER some time before actually descending . */
/* This condition only occurs for helicopters, during descent,
* to a landing by the hanger of an international airport . */
2006-05-30 22:23:01 +01:00
if ( amdflag & AMED_HELI_LOWER ) return AMS_TTDP_HELI_LAND_AIRPORT ;
2006-05-01 12:35:18 +01:00
/* This condition only occurs for helicopters, before starting descent,
* to a landing by the hanger of an international airport . */
if ( amdflag & AMED_SLOWTURN ) return AMS_TTDP_FLIGHT_TO_TOWER ;
2007-03-21 03:06:21 +00:00
/* The final two conditions apply to helicopters or aircraft.
* Has reached hanger ? */
2006-06-22 22:03:19 +01:00
if ( amdflag & AMED_EXACTPOS ) return AMS_TTDP_HANGAR ;
2006-05-01 12:35:18 +01:00
2007-03-21 03:06:21 +00:00
/* Still moving towards hanger. */
2006-06-22 22:03:19 +01:00
return AMS_TTDP_TO_HANGAR ;
2006-05-01 12:35:18 +01:00
case TERM1 :
if ( amdflag & AMED_EXACTPOS ) return AMS_TTDP_TO_PAD1 ;
return AMS_TTDP_TO_JUNCTION ;
case TERM2 :
if ( amdflag & AMED_EXACTPOS ) return AMS_TTDP_TO_PAD2 ;
return AMS_TTDP_TO_ENTRY_2_AND_3_AND_H ;
case TERM3 :
case TERM4 :
case TERM5 :
case TERM6 :
2006-06-23 23:05:40 +01:00
case TERM7 :
case TERM8 :
2006-05-01 12:35:18 +01:00
/* TTDPatch only has 3 terminals, so treat these states the same */
if ( amdflag & AMED_EXACTPOS ) return AMS_TTDP_TO_PAD3 ;
return AMS_TTDP_TO_ENTRY_2_AND_3_AND_H ;
case HELIPAD1 :
2006-06-23 23:05:40 +01:00
case HELIPAD2 :
case HELIPAD3 :
case HELIPAD4 : // Will only occur for helicopters.
2006-05-30 22:23:01 +01:00
if ( amdflag & AMED_HELI_LOWER ) return AMS_TTDP_HELI_LAND_AIRPORT ; // Descending.
2006-05-01 12:35:18 +01:00
if ( amdflag & AMED_SLOWTURN ) return AMS_TTDP_FLIGHT_TO_TOWER ; // Still hasn't started descent.
return AMS_TTDP_TO_JUNCTION ; // On the ground.
case TAKEOFF : // Moving to takeoff position.
return AMS_TTDP_TO_OUTWAY ;
case STARTTAKEOFF : // Accelerating down runway.
return AMS_TTDP_TAKEOFF ;
case ENDTAKEOFF : // Ascent
return AMS_TTDP_CLIMBING ;
case HELITAKEOFF : // Helicopter is moving to take off position.
2007-02-15 07:43:06 +00:00
if ( afc - > delta_z = = 0 ) {
return amdflag & AMED_HELI_RAISE ?
AMS_TTDP_HELI_TAKEOFF_AIRPORT : AMS_TTDP_TO_JUNCTION ;
} else {
return AMS_TTDP_HELI_TAKEOFF_HELIPORT ;
2006-05-01 12:35:18 +01:00
}
case FLYING :
2007-05-10 10:21:22 +01:00
return amdflag & AMED_HOLD ? AMS_TTDP_FLIGHT_APPROACH : AMS_TTDP_FLIGHT_TO_TOWER ;
2006-05-01 12:35:18 +01:00
case LANDING : // Descent
return AMS_TTDP_FLIGHT_DESCENT ;
case ENDLANDING : // On the runway braking
if ( amdflag & AMED_BRAKE ) return AMS_TTDP_BRAKING ;
2007-03-21 03:06:21 +00:00
/* Landed - moving off runway */
2006-05-01 12:35:18 +01:00
return AMS_TTDP_TO_INWAY ;
case HELILANDING :
case HELIENDLANDING : // Helicoptor is decending.
if ( amdflag & AMED_HELI_LOWER ) {
2007-02-15 07:43:06 +00:00
return afc - > delta_z = = 0 ?
AMS_TTDP_HELI_LAND_AIRPORT : AMS_TTDP_HELI_LAND_HELIPORT ;
} else {
return AMS_TTDP_FLIGHT_TO_TOWER ;
2006-05-01 12:35:18 +01:00
}
default :
2006-06-22 22:03:19 +01:00
return AMS_TTDP_HANGAR ;
2006-05-01 12:35:18 +01:00
}
}
/* TTDP style aircraft movement action for GRF Action 2 Var 0xE6 */
enum {
2006-06-22 22:03:19 +01:00
AMA_TTDP_IN_HANGAR ,
2006-05-01 12:35:18 +01:00
AMA_TTDP_ON_PAD1 ,
AMA_TTDP_ON_PAD2 ,
AMA_TTDP_ON_PAD3 ,
2006-06-22 22:03:19 +01:00
AMA_TTDP_HANGAR_TO_PAD1 ,
AMA_TTDP_HANGAR_TO_PAD2 ,
AMA_TTDP_HANGAR_TO_PAD3 ,
2006-05-01 12:35:18 +01:00
AMA_TTDP_LANDING_TO_PAD1 ,
AMA_TTDP_LANDING_TO_PAD2 ,
AMA_TTDP_LANDING_TO_PAD3 ,
2006-06-22 22:03:19 +01:00
AMA_TTDP_PAD1_TO_HANGAR ,
AMA_TTDP_PAD2_TO_HANGAR ,
AMA_TTDP_PAD3_TO_HANGAR ,
2006-05-01 12:35:18 +01:00
AMA_TTDP_PAD1_TO_TAKEOFF ,
AMA_TTDP_PAD2_TO_TAKEOFF ,
AMA_TTDP_PAD3_TO_TAKEOFF ,
2006-06-22 22:03:19 +01:00
AMA_TTDP_HANGAR_TO_TAKOFF ,
AMA_TTDP_LANDING_TO_HANGAR ,
2006-05-01 12:35:18 +01:00
AMA_TTDP_IN_FLIGHT ,
} ;
/**
* Map OTTD aircraft movement states to TTDPatch style movement actions
* ( VarAction 2 Variable 0xE6 )
* This is not fully supported yet but it ' s enough for Planeset .
*/
2009-05-22 21:03:26 +01:00
static byte MapAircraftMovementAction ( const Aircraft * v )
2006-05-01 12:35:18 +01:00
{
2009-05-22 21:07:26 +01:00
switch ( v - > state ) {
2006-05-01 12:35:18 +01:00
case HANGAR :
2006-06-22 22:03:19 +01:00
return ( v - > cur_speed > 0 ) ? AMA_TTDP_LANDING_TO_HANGAR : AMA_TTDP_IN_HANGAR ;
2006-05-01 12:35:18 +01:00
case TERM1 :
case HELIPAD1 :
2008-04-06 00:36:54 +01:00
return ( v - > current_order . IsType ( OT_LOADING ) ) ? AMA_TTDP_ON_PAD1 : AMA_TTDP_LANDING_TO_PAD1 ;
2006-05-01 12:35:18 +01:00
case TERM2 :
case HELIPAD2 :
2008-04-06 00:36:54 +01:00
return ( v - > current_order . IsType ( OT_LOADING ) ) ? AMA_TTDP_ON_PAD2 : AMA_TTDP_LANDING_TO_PAD2 ;
2006-05-01 12:35:18 +01:00
case TERM3 :
case TERM4 :
case TERM5 :
case TERM6 :
2006-06-23 23:05:40 +01:00
case TERM7 :
case TERM8 :
case HELIPAD3 :
case HELIPAD4 :
2008-04-06 00:36:54 +01:00
return ( v - > current_order . IsType ( OT_LOADING ) ) ? AMA_TTDP_ON_PAD3 : AMA_TTDP_LANDING_TO_PAD3 ;
2006-05-01 12:35:18 +01:00
case TAKEOFF : // Moving to takeoff position
case STARTTAKEOFF : // Accelerating down runway
case ENDTAKEOFF : // Ascent
case HELITAKEOFF :
2007-03-21 03:06:21 +00:00
/* @todo Need to find which terminal (or hanger) we've come from. How? */
2006-05-01 12:35:18 +01:00
return AMA_TTDP_PAD1_TO_TAKEOFF ;
case FLYING :
return AMA_TTDP_IN_FLIGHT ;
case LANDING : // Descent
case ENDLANDING : // On the runway braking
case HELILANDING :
case HELIENDLANDING :
2007-03-21 03:06:21 +00:00
/* @todo Need to check terminal we're landing to. Is it known yet? */
2008-04-06 00:36:54 +01:00
return ( v - > current_order . IsType ( OT_GOTO_DEPOT ) ) ?
2006-06-22 22:03:19 +01:00
AMA_TTDP_LANDING_TO_HANGAR : AMA_TTDP_LANDING_TO_PAD1 ;
2006-05-01 12:35:18 +01:00
default :
2006-06-22 22:03:19 +01:00
return AMA_TTDP_IN_HANGAR ;
2006-05-01 12:35:18 +01:00
}
}
2006-04-28 21:04:57 +01:00
/* Vehicle Resolver Functions */
static inline const Vehicle * GRV ( const ResolverObject * object )
{
2008-03-27 21:36:16 +00:00
switch ( object - > scope ) {
default : NOT_REACHED ( ) ;
case VSG_SCOPE_SELF : return object - > u . vehicle . self ;
case VSG_SCOPE_PARENT : return object - > u . vehicle . parent ;
case VSG_SCOPE_RELATIVE : {
2010-05-10 18:27:34 +01:00
if ( object - > u . vehicle . self = = NULL ) return NULL ;
2008-03-28 02:10:25 +00:00
const Vehicle * v = NULL ;
2008-03-27 21:36:16 +00:00
switch ( GB ( object - > count , 6 , 2 ) ) {
default : NOT_REACHED ( ) ;
case 0x00 : // count back (away from the engine), starting at this vehicle
case 0x01 : // count forward (toward the engine), starting at this vehicle
v = object - > u . vehicle . self ;
break ;
case 0x02 : // count back, starting at the engine
v = object - > u . vehicle . parent ;
break ;
2008-03-28 02:10:25 +00:00
case 0x03 : { // count back, starting at the first vehicle in this chain of vehicles with the same ID, as for vehicle variable 41
const Vehicle * self = object - > u . vehicle . self ;
for ( const Vehicle * u = self - > First ( ) ; u ! = self ; u = u - > Next ( ) ) {
if ( u - > engine_type ! = self - > engine_type ) {
v = NULL ;
} else {
if ( v = = NULL ) v = u ;
}
}
if ( v = = NULL ) v = self ;
} break ;
2008-03-27 21:36:16 +00:00
}
uint32 count = GB ( object - > count , 0 , 4 ) ;
if ( count = = 0 ) count = GetRegister ( 0x100 ) ;
while ( v ! = NULL & & count - - ! = 0 ) v = ( GB ( object - > count , 6 , 2 ) = = 0x01 ) ? v - > Previous ( ) : v - > Next ( ) ;
return v ;
}
}
2006-04-28 21:04:57 +01:00
}
static uint32 VehicleGetRandomBits ( const ResolverObject * object )
{
return GRV ( object ) = = NULL ? 0 : GRV ( object ) - > random_bits ;
}
static uint32 VehicleGetTriggers ( const ResolverObject * object )
{
return GRV ( object ) = = NULL ? 0 : GRV ( object ) - > waiting_triggers ;
}
static void VehicleSetTriggers ( const ResolverObject * object , int triggers )
{
/* Evil cast to get around const-ness. This used to be achieved by an
* innocent looking function pointer cast . . . Currently I cannot see a
* way of avoiding this without removing consts deep within gui code .
*/
2009-05-24 22:09:00 +01:00
Vehicle * v = const_cast < Vehicle * > ( GRV ( object ) ) ;
2006-04-28 21:04:57 +01:00
/* This function must only be called when processing triggers -- any
* other time is an error . */
assert ( object - > trigger ! = 0 ) ;
if ( v ! = NULL ) v - > waiting_triggers = triggers ;
}
2007-04-20 22:21:47 +01:00
static uint8 LiveryHelper ( EngineID engine , const Vehicle * v )
{
const Livery * l ;
if ( v = = NULL ) {
2009-05-17 02:00:56 +01:00
if ( ! Company : : IsValidID ( _current_company ) ) return 0 ;
2008-09-30 21:39:50 +01:00
l = GetEngineLivery ( engine , _current_company , INVALID_ENGINE , NULL ) ;
2007-04-20 22:21:47 +01:00
} else if ( v - > type = = VEH_TRAIN ) {
2009-06-06 17:54:22 +01:00
l = GetEngineLivery ( v - > engine_type , v - > owner , Train : : From ( v ) - > tcache . first_engine , v ) ;
2009-02-18 20:40:24 +00:00
} else if ( v - > type = = VEH_ROAD ) {
2009-06-06 17:54:22 +01:00
l = GetEngineLivery ( v - > engine_type , v - > owner , RoadVehicle : : From ( v ) - > rcache . first_engine , v ) ;
2007-04-20 22:21:47 +01:00
} else {
l = GetEngineLivery ( v - > engine_type , v - > owner , INVALID_ENGINE , v ) ;
}
return l - > colour1 + l - > colour2 * 16 ;
}
2009-03-04 23:32:23 +00:00
/**
* Helper to get the position of a vehicle within a chain of vehicles .
* @ param v the vehicle to get the position of .
* @ param consecutive whether to look at the whole chain or the vehicles
* with the same ' engine type ' .
* @ return the position in the chain from front and tail and chain length .
*/
static uint32 PositionHelper ( const Vehicle * v , bool consecutive )
{
const Vehicle * u ;
byte chain_before = 0 ;
byte chain_after = 0 ;
for ( u = v - > First ( ) ; u ! = v ; u = u - > Next ( ) ) {
chain_before + + ;
if ( consecutive & & u - > engine_type ! = v - > engine_type ) chain_before = 0 ;
}
while ( u - > Next ( ) ! = NULL & & ( ! consecutive | | u - > Next ( ) - > engine_type = = v - > engine_type ) ) {
chain_after + + ;
u = u - > Next ( ) ;
}
return chain_before | chain_after < < 8 | ( chain_before + chain_after + consecutive ) < < 16 ;
}
2007-04-20 22:21:47 +01:00
2006-05-23 20:36:50 +01:00
static uint32 VehicleGetVariable ( const ResolverObject * object , byte variable , byte parameter , bool * available )
2006-04-28 21:04:57 +01:00
{
2009-03-04 23:32:23 +00:00
Vehicle * v = const_cast < Vehicle * > ( GRV ( object ) ) ;
2006-04-28 21:04:57 +01:00
if ( v = = NULL ) {
/* Vehicle does not exist, so we're in a purchase list */
switch ( variable ) {
2010-05-05 17:55:43 +01:00
case 0x43 : return _current_company | ( Company : : IsValidAiID ( _current_company ) ? 0x10000 : 0 ) | ( LiveryHelper ( object - > u . vehicle . self_type , NULL ) < < 24 ) ; // Owner information
2007-03-21 03:06:21 +00:00
case 0x46 : return 0 ; // Motion counter
2009-02-21 13:24:55 +00:00
case 0x47 : { // Vehicle cargo info
2009-05-17 00:34:14 +01:00
const Engine * e = Engine : : Get ( object - > u . vehicle . self_type ) ;
2009-02-21 13:24:55 +00:00
CargoID cargo_type = e - > GetDefaultCargoType ( ) ;
if ( cargo_type ! = CT_INVALID ) {
2009-07-16 20:00:13 +01:00
const CargoSpec * cs = CargoSpec : : Get ( cargo_type ) ;
2009-02-21 13:24:55 +00:00
return ( cs - > classes < < 16 ) | ( cs - > weight < < 8 ) | GetEngineGRF ( e - > index ) - > cargo_map [ cargo_type ] ;
} else {
return 0x000000FF ;
}
}
2009-05-17 00:34:14 +01:00
case 0x48 : return Engine : : Get ( object - > u . vehicle . self_type ) - > flags ; // Vehicle Type Info
2008-06-04 07:40:07 +01:00
case 0x49 : return _cur_year ; // 'Long' format build year
2007-11-19 18:38:10 +00:00
case 0xC4 : return Clamp ( _cur_year , ORIGINAL_BASE_YEAR , ORIGINAL_MAX_YEAR ) - ORIGINAL_BASE_YEAR ; // Build year
2007-03-21 03:06:21 +00:00
case 0xDA : return INVALID_VEHICLE ; // Next vehicle
2009-02-21 13:24:55 +00:00
case 0xF2 : return 0 ; // Cargo subtype
2006-04-28 21:04:57 +01:00
}
2006-05-23 20:36:50 +01:00
* available = false ;
2007-01-10 18:56:51 +00:00
return UINT_MAX ;
2006-04-28 21:04:57 +01:00
}
/* Calculated vehicle parameters */
switch ( variable ) {
2009-03-16 08:03:50 +00:00
case 0x25 : // Get engine GRF ID
return GetEngineGRFID ( v - > engine_type ) ;
2007-03-21 03:06:21 +00:00
case 0x40 : // Get length of consist
2009-05-23 10:10:56 +01:00
if ( ! HasBit ( v - > vcache . cache_valid , 0 ) ) {
v - > vcache . cached_var40 = PositionHelper ( v , false ) ;
SetBit ( v - > vcache . cache_valid , 0 ) ;
2009-03-04 23:32:23 +00:00
}
2009-05-23 10:10:56 +01:00
return v - > vcache . cached_var40 ;
2009-03-04 23:32:23 +00:00
2007-03-21 03:06:21 +00:00
case 0x41 : // Get length of same consecutive wagons
2009-05-23 10:10:56 +01:00
if ( ! HasBit ( v - > vcache . cache_valid , 1 ) ) {
v - > vcache . cached_var41 = PositionHelper ( v , true ) ;
SetBit ( v - > vcache . cache_valid , 1 ) ;
2009-03-04 23:32:23 +00:00
}
2009-05-23 10:10:56 +01:00
return v - > vcache . cached_var41 ;
2006-04-28 21:04:57 +01:00
2009-03-04 23:32:23 +00:00
case 0x42 : // Consist cargo information
2009-05-23 10:10:56 +01:00
if ( ! HasBit ( v - > vcache . cache_valid , 2 ) ) {
2009-03-04 23:32:23 +00:00
const Vehicle * u ;
byte cargo_classes = 0 ;
uint8 common_cargos [ NUM_CARGO ] ;
uint8 common_subtypes [ 256 ] ;
byte user_def_data = 0 ;
2009-05-31 12:27:10 +01:00
CargoID common_cargo_type = CT_INVALID ;
uint8 common_subtype = 0xFF ; // Return 0xFF if nothing is carried
2009-03-04 23:32:23 +00:00
/* Reset our arrays */
memset ( common_cargos , 0 , sizeof ( common_cargos ) ) ;
memset ( common_subtypes , 0 , sizeof ( common_subtypes ) ) ;
for ( u = v ; u ! = NULL ; u = u - > Next ( ) ) {
2009-06-06 17:54:22 +01:00
if ( v - > type = = VEH_TRAIN ) user_def_data | = Train : : From ( u ) - > tcache . user_def_data ;
2009-03-04 23:32:23 +00:00
/* Skip empty engines */
if ( u - > cargo_cap = = 0 ) continue ;
2009-07-16 20:00:13 +01:00
cargo_classes | = CargoSpec : : Get ( u - > cargo_type ) - > classes ;
2009-03-04 23:32:23 +00:00
common_cargos [ u - > cargo_type ] + + ;
2006-04-28 21:04:57 +01:00
}
2009-03-04 23:32:23 +00:00
/* Pick the most common cargo type */
2009-05-31 12:27:10 +01:00
uint common_cargo_best_amount = 0 ;
2009-03-04 23:32:23 +00:00
for ( CargoID cargo = 0 ; cargo < NUM_CARGO ; cargo + + ) {
2009-05-31 12:27:10 +01:00
if ( common_cargos [ cargo ] > common_cargo_best_amount ) {
common_cargo_best_amount = common_cargos [ cargo ] ;
2009-03-04 23:32:23 +00:00
common_cargo_type = cargo ;
}
2006-04-28 21:04:57 +01:00
}
2009-03-04 23:32:23 +00:00
/* Count subcargo types of common_cargo_type */
for ( u = v ; u ! = NULL ; u = u - > Next ( ) ) {
/* Skip empty engines and engines not carrying common_cargo_type */
if ( u - > cargo_cap = = 0 | | u - > cargo_type ! = common_cargo_type ) continue ;
2006-04-28 21:04:57 +01:00
2009-03-04 23:32:23 +00:00
common_subtypes [ u - > cargo_subtype ] + + ;
2006-05-14 16:11:12 +01:00
}
2009-02-06 18:06:05 +00:00
2009-03-04 23:32:23 +00:00
/* Pick the most common subcargo type*/
2009-05-31 12:27:10 +01:00
uint common_subtype_best_amount = 0 ;
2009-03-04 23:32:23 +00:00
for ( uint i = 0 ; i < lengthof ( common_subtypes ) ; i + + ) {
2009-05-31 12:27:10 +01:00
if ( common_subtypes [ i ] > common_subtype_best_amount ) {
common_subtype_best_amount = common_subtypes [ i ] ;
2009-03-04 23:32:23 +00:00
common_subtype = i ;
}
2007-06-08 07:27:58 +01:00
}
2009-07-16 20:00:13 +01:00
uint8 common_bitnum = ( common_cargo_type = = CT_INVALID ? 0xFF : CargoSpec : : Get ( common_cargo_type ) - > bitnum ) ;
2009-05-23 10:10:56 +01:00
v - > vcache . cached_var42 = cargo_classes | ( common_bitnum < < 8 ) | ( common_subtype < < 16 ) | ( user_def_data < < 24 ) ;
SetBit ( v - > vcache . cache_valid , 2 ) ;
2009-03-04 23:32:23 +00:00
}
2009-05-23 10:10:56 +01:00
return v - > vcache . cached_var42 ;
2006-05-14 16:11:12 +01:00
2008-09-30 21:39:50 +01:00
case 0x43 : // Company information
2009-05-23 10:10:56 +01:00
if ( ! HasBit ( v - > vcache . cache_valid , 3 ) ) {
2009-06-23 13:11:35 +01:00
v - > vcache . cached_var43 = v - > owner | ( Company : : IsHumanID ( v - > owner ) ? 0 : 0x10000 ) | ( LiveryHelper ( v - > engine_type , v ) < < 24 ) ;
2009-05-23 10:10:56 +01:00
SetBit ( v - > vcache . cache_valid , 3 ) ;
2009-03-04 23:32:23 +00:00
}
2009-05-23 10:10:56 +01:00
return v - > vcache . cached_var43 ;
2006-04-28 21:04:57 +01:00
2007-03-21 03:06:21 +00:00
case 0x44 : // Aircraft information
2007-03-08 16:27:54 +00:00
if ( v - > type ! = VEH_AIRCRAFT ) return UINT_MAX ;
2006-05-01 13:00:14 +01:00
{
2007-08-30 14:03:56 +01:00
const Vehicle * w = v - > Next ( ) ;
2007-03-21 03:06:21 +00:00
uint16 altitude = v - > z_pos - w - > z_pos ; // Aircraft height - shadow height
2008-09-22 15:34:38 +01:00
byte airporttype = ATP_TTDP_LARGE ;
2009-06-06 17:54:22 +01:00
const Station * st = GetTargetAirportIfValid ( Aircraft : : From ( v ) ) ;
2008-09-22 15:34:38 +01:00
2010-03-01 20:17:21 +00:00
if ( st ! = NULL & & st - > airport . tile ! = INVALID_TILE ) {
2010-03-18 21:02:20 +00:00
airporttype = st - > airport . GetSpec ( ) - > ttd_airport_type ;
2006-05-01 13:00:14 +01:00
}
return ( altitude < < 8 ) | airporttype ;
}
2007-05-06 21:05:10 +01:00
case 0x45 : { // Curvature info
/* Format: xxxTxBxF
* F - previous wagon to current wagon , 0 if vehicle is first
* B - current wagon to next wagon , 0 if wagon is last
* T - previous wagon to next wagon , 0 in an S - bend
*/
2009-01-09 23:04:51 +00:00
if ( v - > type ! = VEH_TRAIN & & v - > type ! = VEH_ROAD ) return 0 ;
2007-05-06 21:05:10 +01:00
2007-08-30 22:11:12 +01:00
const Vehicle * u_p = v - > Previous ( ) ;
2007-08-30 14:03:56 +01:00
const Vehicle * u_n = v - > Next ( ) ;
2007-05-06 21:05:10 +01:00
DirDiff f = ( u_p = = NULL ) ? DIRDIFF_SAME : DirDifference ( u_p - > direction , v - > direction ) ;
DirDiff b = ( u_n = = NULL ) ? DIRDIFF_SAME : DirDifference ( v - > direction , u_n - > direction ) ;
DirDiff t = ChangeDirDiff ( f , b ) ;
return ( ( t > DIRDIFF_REVERSE ? t | 8 : t ) < < 16 ) |
( ( b > DIRDIFF_REVERSE ? b | 8 : b ) < < 8 ) |
( f > DIRDIFF_REVERSE ? f | 8 : f ) ;
}
2007-03-21 03:06:21 +00:00
case 0x46 : // Motion counter
2006-09-27 19:17:01 +01:00
return v - > motion_counter ;
2006-05-02 21:17:17 +01:00
2007-03-21 03:06:21 +00:00
case 0x47 : { // Vehicle cargo info
2006-05-15 07:49:36 +01:00
/* Format: ccccwwtt
* tt - the cargo type transported by the vehicle ,
* translated if a translation table has been installed .
* ww - cargo unit weight in 1 / 16 tons , same as cargo prop . 0F .
* cccc - the cargo class value of the cargo transported by the vehicle .
*/
2009-07-16 20:00:13 +01:00
const CargoSpec * cs = CargoSpec : : Get ( v - > cargo_type ) ;
2006-05-15 07:49:36 +01:00
2007-02-24 23:20:21 +00:00
return ( cs - > classes < < 16 ) | ( cs - > weight < < 8 ) | GetEngineGRF ( v - > engine_type ) - > cargo_map [ v - > cargo_type ] ;
2006-05-15 07:49:36 +01:00
}
2009-05-17 00:34:14 +01:00
case 0x48 : return Engine : : Get ( v - > engine_type ) - > flags ; // Vehicle Type Info
2008-06-04 01:17:48 +01:00
case 0x49 : return v - > build_year ;
2006-06-22 22:31:09 +01:00
2006-05-02 21:17:17 +01:00
/* Variables which use the parameter */
2007-03-21 03:06:21 +00:00
case 0x60 : // Count consist's engine ID occurance
2008-04-29 22:31:29 +01:00
//EngineID engine = GetNewEngineID(GetEngineGRF(v->engine_type), v->type, parameter);
2009-05-17 00:34:14 +01:00
if ( v - > type ! = VEH_TRAIN ) return Engine : : Get ( v - > engine_type ) - > internal_id = = parameter ;
2006-05-02 21:17:17 +01:00
{
uint count = 0 ;
2007-08-30 14:03:56 +01:00
for ( ; v ! = NULL ; v = v - > Next ( ) ) {
2009-05-17 00:34:14 +01:00
if ( Engine : : Get ( v - > engine_type ) - > internal_id = = parameter ) count + + ;
2006-05-02 21:17:17 +01:00
}
return count ;
}
2006-05-31 18:40:48 +01:00
2007-02-28 17:59:05 +00:00
case 0xFE :
case 0xFF : {
uint16 modflags = 0 ;
2008-03-03 20:41:47 +00:00
if ( v - > type = = VEH_TRAIN ) {
2009-06-06 17:54:22 +01:00
const Train * t = Train : : From ( v ) ;
2009-07-02 00:57:20 +01:00
const Train * u = t - > IsWagon ( ) & & HasBit ( t - > vehicle_flags , VRF_POWEREDWAGON ) ? t - > First ( ) : t ;
2008-03-03 20:41:47 +00:00
RailType railtype = GetRailType ( v - > tile ) ;
2009-07-02 00:57:20 +01:00
bool powered = t - > IsEngine ( ) | | ( t - > IsWagon ( ) & & HasBit ( t - > vehicle_flags , VRF_POWEREDWAGON ) ) ;
2009-05-22 23:33:05 +01:00
bool has_power = powered & & HasPowerOnRail ( u - > railtype , railtype ) ;
bool is_electric = powered & & u - > railtype = = RAILTYPE_ELECTRIC ;
2008-03-03 20:56:30 +00:00
2008-03-03 20:41:47 +00:00
if ( has_power ) SetBit ( modflags , 5 ) ;
if ( is_electric & & ! has_power ) SetBit ( modflags , 6 ) ;
2009-05-22 23:33:05 +01:00
if ( HasBit ( t - > flags , VRF_TOGGLE_REVERSE ) ) SetBit ( modflags , 8 ) ;
2008-03-03 20:41:47 +00:00
}
2007-11-20 13:35:54 +00:00
if ( HasBit ( v - > vehicle_flags , VF_BUILT_AS_PROTOTYPE ) ) SetBit ( modflags , 10 ) ;
2007-02-28 17:59:05 +00:00
return variable = = 0xFE ? modflags : GB ( modflags , 8 , 8 ) ;
}
2006-04-28 21:04:57 +01:00
}
/* General vehicle properties */
switch ( variable - 0x80 ) {
2009-06-21 14:30:21 +01:00
case 0x00 : return v - > type + 0x10 ;
2006-04-28 21:04:57 +01:00
case 0x01 : return MapOldSubType ( v ) ;
case 0x04 : return v - > index ;
2006-11-28 21:03:28 +00:00
case 0x05 : return GB ( v - > index , 8 , 8 ) ;
2009-06-21 11:11:04 +01:00
case 0x0A : return v - > current_order . MapOldOrder ( ) ;
case 0x0B : return v - > current_order . GetDestination ( ) ;
2009-01-03 13:20:32 +00:00
case 0x0C : return v - > GetNumOrders ( ) ;
2006-04-28 21:04:57 +01:00
case 0x0D : return v - > cur_order_index ;
2010-01-28 18:19:34 +00:00
case 0x10 :
case 0x11 : {
uint ticks ;
if ( v - > current_order . IsType ( OT_LOADING ) ) {
ticks = v - > load_unload_ticks ;
} else {
switch ( v - > type ) {
case VEH_TRAIN : ticks = Train : : From ( v ) - > wait_counter ; break ;
case VEH_AIRCRAFT : ticks = Aircraft : : From ( v ) - > turn_counter ; break ;
default : ticks = 0 ; break ;
}
}
return ( variable - 0x80 ) = = 0x10 ? ticks : GB ( ticks , 8 , 8 ) ;
}
2006-08-20 21:21:00 +01:00
case 0x12 : return max ( v - > date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR , 0 ) ;
2006-11-28 21:03:28 +00:00
case 0x13 : return GB ( max ( v - > date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR , 0 ) , 8 , 8 ) ;
2006-04-28 21:04:57 +01:00
case 0x14 : return v - > service_interval ;
2006-11-28 21:03:28 +00:00
case 0x15 : return GB ( v - > service_interval , 8 , 8 ) ;
2006-04-28 21:04:57 +01:00
case 0x16 : return v - > last_station_visited ;
case 0x17 : return v - > tick_counter ;
case 0x18 : return v - > max_speed ;
2006-11-28 21:03:28 +00:00
case 0x19 : return GB ( v - > max_speed , 8 , 8 ) ;
2006-04-28 21:04:57 +01:00
case 0x1A : return v - > x_pos ;
2006-11-28 21:03:28 +00:00
case 0x1B : return GB ( v - > x_pos , 8 , 8 ) ;
2006-04-28 21:04:57 +01:00
case 0x1C : return v - > y_pos ;
2006-11-28 21:03:28 +00:00
case 0x1D : return GB ( v - > y_pos , 8 , 8 ) ;
2006-04-28 21:04:57 +01:00
case 0x1E : return v - > z_pos ;
2009-09-30 19:54:33 +01:00
case 0x1F : return object - > u . vehicle . info_view ? DIR_W : v - > direction ;
2006-04-28 21:04:57 +01:00
case 0x28 : return v - > cur_image ;
2006-11-28 21:03:28 +00:00
case 0x29 : return GB ( v - > cur_image , 8 , 8 ) ;
2006-04-28 21:04:57 +01:00
case 0x32 : return v - > vehstatus ;
2006-11-29 11:48:47 +00:00
case 0x33 : return 0 ; // non-existent high byte of vehstatus
2006-04-28 21:04:57 +01:00
case 0x34 : return v - > cur_speed ;
2006-11-28 21:03:28 +00:00
case 0x35 : return GB ( v - > cur_speed , 8 , 8 ) ;
2006-04-28 21:04:57 +01:00
case 0x36 : return v - > subspeed ;
case 0x37 : return v - > acceleration ;
case 0x39 : return v - > cargo_type ;
case 0x3A : return v - > cargo_cap ;
2006-11-28 21:03:28 +00:00
case 0x3B : return GB ( v - > cargo_cap , 8 , 8 ) ;
2007-06-22 12:58:59 +01:00
case 0x3C : return v - > cargo . Count ( ) ;
case 0x3D : return GB ( v - > cargo . Count ( ) , 8 , 8 ) ;
case 0x3E : return v - > cargo . Source ( ) ;
case 0x3F : return v - > cargo . DaysInTransit ( ) ;
2006-04-28 21:04:57 +01:00
case 0x40 : return v - > age ;
2006-11-28 21:03:28 +00:00
case 0x41 : return GB ( v - > age , 8 , 8 ) ;
2006-04-28 21:04:57 +01:00
case 0x42 : return v - > max_age ;
2006-11-28 21:03:28 +00:00
case 0x43 : return GB ( v - > max_age , 8 , 8 ) ;
2007-11-19 18:38:10 +00:00
case 0x44 : return Clamp ( v - > build_year , ORIGINAL_BASE_YEAR , ORIGINAL_MAX_YEAR ) - ORIGINAL_BASE_YEAR ;
2006-04-28 21:04:57 +01:00
case 0x45 : return v - > unitnumber ;
2009-05-17 00:34:14 +01:00
case 0x46 : return Engine : : Get ( v - > engine_type ) - > internal_id ;
case 0x47 : return GB ( Engine : : Get ( v - > engine_type ) - > internal_id , 8 , 8 ) ;
2008-04-27 11:19:41 +01:00
case 0x48 :
if ( v - > type ! = VEH_TRAIN | | v - > spritenum ! = 0xFD ) return v - > spritenum ;
2009-06-06 17:54:22 +01:00
return HasBit ( Train : : From ( v ) - > flags , VRF_REVERSE_DIRECTION ) ? 0xFE : 0xFD ;
2008-04-27 11:19:41 +01:00
2006-04-28 21:04:57 +01:00
case 0x49 : return v - > day_counter ;
case 0x4A : return v - > breakdowns_since_last_service ;
case 0x4B : return v - > breakdown_ctr ;
case 0x4C : return v - > breakdown_delay ;
case 0x4D : return v - > breakdown_chance ;
case 0x4E : return v - > reliability ;
2006-11-28 21:03:28 +00:00
case 0x4F : return GB ( v - > reliability , 8 , 8 ) ;
2006-04-28 21:04:57 +01:00
case 0x50 : return v - > reliability_spd_dec ;
2006-11-28 21:03:28 +00:00
case 0x51 : return GB ( v - > reliability_spd_dec , 8 , 8 ) ;
2008-02-20 17:06:58 +00:00
case 0x52 : return ClampToI32 ( v - > GetDisplayProfitThisYear ( ) ) ;
case 0x53 : return GB ( ClampToI32 ( v - > GetDisplayProfitThisYear ( ) ) , 8 , 24 ) ;
case 0x54 : return GB ( ClampToI32 ( v - > GetDisplayProfitThisYear ( ) ) , 16 , 16 ) ;
case 0x55 : return GB ( ClampToI32 ( v - > GetDisplayProfitThisYear ( ) ) , 24 , 8 ) ;
case 0x56 : return ClampToI32 ( v - > GetDisplayProfitLastYear ( ) ) ;
case 0x57 : return GB ( ClampToI32 ( v - > GetDisplayProfitLastYear ( ) ) , 8 , 24 ) ;
case 0x58 : return GB ( ClampToI32 ( v - > GetDisplayProfitLastYear ( ) ) , 16 , 16 ) ;
case 0x59 : return GB ( ClampToI32 ( v - > GetDisplayProfitLastYear ( ) ) , 24 , 8 ) ;
2007-08-30 14:03:56 +01:00
case 0x5A : return v - > Next ( ) = = NULL ? INVALID_VEHICLE : v - > Next ( ) - > index ;
2007-06-21 15:32:27 +01:00
case 0x5C : return ClampToI32 ( v - > value ) ;
case 0x5D : return GB ( ClampToI32 ( v - > value ) , 8 , 24 ) ;
case 0x5E : return GB ( ClampToI32 ( v - > value ) , 16 , 16 ) ;
case 0x5F : return GB ( ClampToI32 ( v - > value ) , 24 , 8 ) ;
2006-05-19 11:04:03 +01:00
case 0x72 : return v - > cargo_subtype ;
2006-04-28 21:04:57 +01:00
case 0x7A : return v - > random_bits ;
case 0x7B : return v - > waiting_triggers ;
}
/* Vehicle specific properties */
2006-02-12 10:35:51 +00:00
switch ( v - > type ) {
2009-05-22 23:22:46 +01:00
case VEH_TRAIN : {
2009-06-06 17:54:22 +01:00
Train * t = Train : : From ( v ) ;
2006-04-28 21:04:57 +01:00
switch ( variable - 0x80 ) {
2009-05-22 23:33:05 +01:00
case 0x62 : return t - > track ;
case 0x66 : return t - > railtype ;
2009-05-22 23:55:41 +01:00
case 0x73 : return t - > tcache . cached_veh_length ;
2010-03-06 12:42:53 +00:00
case 0x74 : return t - > acc_cache . cached_power ;
case 0x75 : return GB ( t - > acc_cache . cached_power , 8 , 24 ) ;
case 0x76 : return GB ( t - > acc_cache . cached_power , 16 , 16 ) ;
case 0x77 : return GB ( t - > acc_cache . cached_power , 24 , 8 ) ;
2009-05-22 23:22:46 +01:00
case 0x7C : return t - > First ( ) - > index ;
case 0x7D : return GB ( t - > First ( ) - > index , 8 , 8 ) ;
2006-06-20 14:15:56 +01:00
case 0x7F : return 0 ; // Used for vehicle reversing hack in TTDP
2006-02-12 10:35:51 +00:00
}
2009-05-22 23:22:46 +01:00
} break ;
2006-02-12 10:35:51 +00:00
2009-05-22 21:22:20 +01:00
case VEH_ROAD : {
2009-06-06 17:54:22 +01:00
RoadVehicle * rv = RoadVehicle : : From ( v ) ;
2006-04-28 21:04:57 +01:00
switch ( variable - 0x80 ) {
2009-05-22 21:22:20 +01:00
case 0x62 : return rv - > state ;
case 0x64 : return rv - > blocked_ctr ;
case 0x65 : return GB ( rv - > blocked_ctr , 8 , 8 ) ;
case 0x66 : return rv - > overtaking ;
case 0x67 : return rv - > overtaking_ctr ;
case 0x68 : return rv - > crashed_ctr ;
case 0x69 : return GB ( rv - > crashed_ctr , 8 , 8 ) ;
2006-02-12 10:35:51 +00:00
}
2009-05-22 21:22:20 +01:00
} break ;
2006-02-12 10:35:51 +00:00
2009-05-22 21:03:26 +01:00
case VEH_AIRCRAFT : {
2009-06-06 17:54:22 +01:00
Aircraft * a = Aircraft : : From ( v ) ;
2006-04-28 21:04:57 +01:00
switch ( variable - 0x80 ) {
2009-05-22 21:03:26 +01:00
case 0x62 : return MapAircraftMovementState ( a ) ; // Current movement state
2009-05-22 21:07:26 +01:00
case 0x63 : return a - > targetairport ; // Airport to which the action refers
2009-05-22 21:03:26 +01:00
case 0x66 : return MapAircraftMovementAction ( a ) ; // Current movement action
2006-02-12 10:35:51 +00:00
}
2009-05-22 21:03:26 +01:00
} break ;
2007-05-15 12:28:22 +01:00
default : break ;
2006-02-12 10:35:51 +00:00
}
2009-05-10 18:27:25 +01:00
DEBUG ( grf , 1 , " Unhandled vehicle property 0x%X, type 0x%X " , variable , ( uint ) v - > type ) ;
2006-02-12 10:35:51 +00:00
2006-05-23 20:36:50 +01:00
* available = false ;
2007-01-10 18:56:51 +00:00
return UINT_MAX ;
2006-02-12 10:35:51 +00:00
}
2006-02-03 12:55:21 +00:00
2009-05-23 13:13:42 +01:00
static const SpriteGroup * VehicleResolveReal ( const ResolverObject * object , const RealSpriteGroup * group )
2006-02-03 12:55:21 +00:00
{
2006-05-02 19:56:07 +01:00
const Vehicle * v = object - > u . vehicle . self ;
2006-02-03 12:55:21 +00:00
2008-02-18 19:20:37 +00:00
if ( v = = NULL ) {
2009-05-23 13:13:42 +01:00
if ( group - > num_loading > 0 ) return group - > loading [ 0 ] ;
if ( group - > num_loaded > 0 ) return group - > loaded [ 0 ] ;
2008-02-18 19:20:37 +00:00
return NULL ;
}
2006-02-03 12:55:21 +00:00
2008-04-06 00:36:54 +01:00
bool in_motion = ! v - > First ( ) - > current_order . IsType ( OT_LOADING ) ;
2006-02-03 12:55:21 +00:00
2009-05-23 13:13:42 +01:00
uint totalsets = in_motion ? group - > num_loaded : group - > num_loading ;
2006-02-03 12:55:21 +00:00
2008-12-15 22:22:23 +00:00
uint set = ( v - > cargo . Count ( ) * totalsets ) / max ( ( uint16 ) 1 , v - > cargo_cap ) ;
set = min ( set , totalsets - 1 ) ;
2006-02-03 12:55:21 +00:00
2009-05-23 13:13:42 +01:00
return in_motion ? group - > loaded [ set ] : group - > loading [ set ] ;
2006-04-28 21:04:57 +01:00
}
2006-02-03 12:55:21 +00:00
2006-06-22 22:25:51 +01:00
static inline void NewVehicleResolver ( ResolverObject * res , EngineID engine_type , const Vehicle * v )
2006-04-28 21:04:57 +01:00
{
res - > GetRandomBits = & VehicleGetRandomBits ;
res - > GetTriggers = & VehicleGetTriggers ;
res - > SetTriggers = & VehicleSetTriggers ;
res - > GetVariable = & VehicleGetVariable ;
res - > ResolveReal = & VehicleResolveReal ;
2006-05-02 19:56:07 +01:00
res - > u . vehicle . self = v ;
2007-09-09 12:23:49 +01:00
res - > u . vehicle . parent = ( v ! = NULL ) ? v - > First ( ) : v ;
2006-04-28 21:04:57 +01:00
2006-06-22 22:25:51 +01:00
res - > u . vehicle . self_type = engine_type ;
2009-09-30 19:54:33 +01:00
res - > u . vehicle . info_view = false ;
2006-06-22 22:15:27 +01:00
2007-07-25 20:06:29 +01:00
res - > callback = CBID_NO_CALLBACK ;
2006-04-28 21:04:57 +01:00
res - > callback_param1 = 0 ;
res - > callback_param2 = 0 ;
res - > last_value = 0 ;
res - > trigger = 0 ;
res - > reseed = 0 ;
2008-03-27 21:36:16 +00:00
res - > count = 0 ;
2008-07-30 19:23:12 +01:00
2009-05-17 00:34:14 +01:00
const Engine * e = Engine : : Get ( engine_type ) ;
2008-07-30 19:23:12 +01:00
res - > grffile = ( e ! = NULL ? e - > grffile : NULL ) ;
2006-02-03 12:55:21 +00:00
}
2006-04-28 21:04:57 +01:00
2006-10-21 15:53:57 +01:00
/** Retrieve the SpriteGroup for the specified vehicle.
* If the vehicle is not specified , the purchase list group for the engine is
* chosen . For trains , an additional engine override lookup is performed .
2007-11-11 18:32:01 +00:00
* @ param engine Engine type of the vehicle .
* @ param v The vehicle itself .
* @ param use_cache Use cached override
* @ returns The selected SpriteGroup for the vehicle .
2006-10-21 15:53:57 +01:00
*/
2007-11-11 18:32:01 +00:00
static const SpriteGroup * GetVehicleSpriteGroup ( EngineID engine , const Vehicle * v , bool use_cache = true )
2006-02-03 12:55:21 +00:00
{
const SpriteGroup * group ;
2006-10-12 16:05:25 +01:00
CargoID cargo ;
2006-02-03 12:55:21 +00:00
2006-10-21 15:53:57 +01:00
if ( v = = NULL ) {
2007-02-24 23:36:40 +00:00
cargo = CT_PURCHASE ;
2006-10-21 15:53:57 +01:00
} else {
2007-02-24 23:36:40 +00:00
cargo = v - > cargo_type ;
2006-04-28 21:04:57 +01:00
2007-03-08 16:27:54 +00:00
if ( v - > type = = VEH_TRAIN ) {
2007-11-11 18:32:01 +00:00
/* We always use cached value, except for callbacks because the override spriteset
* to use may be different than the one cached . It happens for callback 0x15 ( refit engine ) ,
* as v - > cargo_type is temporary changed to the new type */
2009-06-06 17:54:22 +01:00
group = use_cache ? Train : : From ( v ) - > tcache . cached_override : GetWagonOverrideSpriteSet ( v - > engine_type , v - > cargo_type , Train : : From ( v ) - > tcache . first_engine ) ;
2006-10-21 15:53:57 +01:00
if ( group ! = NULL ) return group ;
2009-02-18 20:35:02 +00:00
} else if ( v - > type = = VEH_ROAD ) {
2009-06-06 17:54:22 +01:00
group = GetWagonOverrideSpriteSet ( v - > engine_type , v - > cargo_type , RoadVehicle : : From ( v ) - > rcache . first_engine ) ;
2009-02-18 20:35:02 +00:00
if ( group ! = NULL ) return group ;
2006-10-21 15:53:57 +01:00
}
}
2006-02-03 12:55:21 +00:00
2009-05-17 00:34:14 +01:00
const Engine * e = Engine : : Get ( engine ) ;
2008-04-29 22:31:29 +01:00
2009-02-07 16:17:03 +00:00
assert ( cargo < lengthof ( e - > group ) ) ;
2008-04-29 22:31:29 +01:00
group = e - > group [ cargo ] ;
2006-10-21 15:53:57 +01:00
if ( group ! = NULL ) return group ;
2006-02-03 12:55:21 +00:00
2006-10-21 15:53:57 +01:00
/* Fall back to the default set if the selected cargo type is not defined */
2008-04-29 22:31:29 +01:00
return e - > group [ CT_DEFAULT ] ;
2006-10-21 15:53:57 +01:00
}
2006-02-03 12:55:21 +00:00
2006-10-21 15:53:57 +01:00
SpriteID GetCustomEngineSprite ( EngineID engine , const Vehicle * v , Direction direction )
{
const SpriteGroup * group ;
ResolverObject object ;
NewVehicleResolver ( & object , engine , v ) ;
2009-05-23 16:25:52 +01:00
group = SpriteGroup : : Resolve ( GetVehicleSpriteGroup ( engine , v ) , & object ) ;
2009-05-23 13:13:42 +01:00
if ( group = = NULL | | group - > GetNumResults ( ) = = 0 ) return 0 ;
2006-04-26 21:44:28 +01:00
2009-05-23 13:13:42 +01:00
return group - > GetResult ( ) + ( direction % group - > GetNumResults ( ) ) ;
2006-02-03 12:55:21 +00:00
}
2006-04-28 21:04:57 +01:00
2009-05-22 21:03:26 +01:00
SpriteID GetRotorOverrideSprite ( EngineID engine , const Aircraft * v , bool info_view )
2006-04-30 19:41:16 +01:00
{
2009-05-17 00:34:14 +01:00
const Engine * e = Engine : : Get ( engine ) ;
2006-04-30 19:41:16 +01:00
/* Only valid for helicopters */
2008-06-01 16:08:14 +01:00
assert ( e - > type = = VEH_AIRCRAFT ) ;
2008-04-29 22:31:29 +01:00
assert ( ! ( e - > u . air . subtype & AIR_CTOL ) ) ;
2006-04-30 19:41:16 +01:00
2008-06-01 16:08:14 +01:00
ResolverObject object ;
2006-06-22 22:25:51 +01:00
NewVehicleResolver ( & object , engine , v ) ;
2006-04-30 19:41:16 +01:00
2009-09-30 19:54:33 +01:00
object . u . vehicle . info_view = info_view ;
2006-06-22 22:15:27 +01:00
2008-06-01 16:08:14 +01:00
const SpriteGroup * group = GetWagonOverrideSpriteSet ( engine , CT_DEFAULT , engine ) ;
2009-05-23 16:25:52 +01:00
group = SpriteGroup : : Resolve ( group , & object ) ;
2006-04-30 19:41:16 +01:00
2009-05-23 13:13:42 +01:00
if ( group = = NULL | | group - > GetNumResults ( ) = = 0 ) return 0 ;
2006-04-30 19:41:16 +01:00
2009-05-23 13:13:42 +01:00
if ( v = = NULL ) return group - > GetResult ( ) ;
2006-04-30 19:41:16 +01:00
2009-05-23 13:13:42 +01:00
return group - > GetResult ( ) + ( info_view ? 0 : ( v - > Next ( ) - > Next ( ) - > state % group - > GetNumResults ( ) ) ) ;
2006-04-30 19:41:16 +01:00
}
2006-02-03 12:55:21 +00:00
/**
* Check if a wagon is currently using a wagon override
* @ param v The wagon to check
* @ return true if it is using an override , false otherwise
*/
2009-01-10 00:31:47 +00:00
bool UsesWagonOverride ( const Vehicle * v )
2006-02-03 12:55:21 +00:00
{
2007-03-08 16:27:54 +00:00
assert ( v - > type = = VEH_TRAIN ) ;
2009-06-06 17:54:22 +01:00
return Train : : From ( v ) - > tcache . cached_override ! = NULL ;
2006-02-03 12:55:21 +00:00
}
/**
2006-03-31 11:14:25 +01:00
* Evaluate a newgrf callback for vehicles
* @ param callback The callback to evalute
* @ param param1 First parameter of the callback
* @ param param2 Second parameter of the callback
* @ param engine Engine type of the vehicle to evaluate the callback for
2007-04-17 21:23:13 +01:00
* @ param v The vehicle to evaluate the callback for , or NULL if it doesnt exist yet
2006-02-03 12:55:21 +00:00
* @ return The value the callback returned , or CALLBACK_FAILED if it failed
*/
2007-07-25 20:06:29 +01:00
uint16 GetVehicleCallback ( CallbackID callback , uint32 param1 , uint32 param2 , EngineID engine , const Vehicle * v )
2006-02-03 12:55:21 +00:00
{
const SpriteGroup * group ;
2006-04-28 21:04:57 +01:00
ResolverObject object ;
2006-06-22 22:25:51 +01:00
NewVehicleResolver ( & object , engine , v ) ;
2006-04-28 21:04:57 +01:00
object . callback = callback ;
object . callback_param1 = param1 ;
object . callback_param2 = param2 ;
2006-02-03 12:55:21 +00:00
2009-05-23 16:25:52 +01:00
group = SpriteGroup : : Resolve ( GetVehicleSpriteGroup ( engine , v , false ) , & object ) ;
2009-05-23 13:13:42 +01:00
if ( group = = NULL ) return CALLBACK_FAILED ;
2006-02-03 12:55:21 +00:00
2009-05-23 13:13:42 +01:00
return group - > GetCallbackResult ( ) ;
2006-02-03 12:55:21 +00:00
}
2006-05-02 22:42:11 +01:00
/**
* Evaluate a newgrf callback for vehicles with a different vehicle for parent scope .
* @ param callback The callback to evalute
* @ param param1 First parameter of the callback
* @ param param2 Second parameter of the callback
* @ param engine Engine type of the vehicle to evaluate the callback for
* @ param v The vehicle to evaluate the callback for , or NULL if it doesnt exist yet
* @ param parent The vehicle to use for parent scope
* @ return The value the callback returned , or CALLBACK_FAILED if it failed
*/
2007-07-25 20:06:29 +01:00
uint16 GetVehicleCallbackParent ( CallbackID callback , uint32 param1 , uint32 param2 , EngineID engine , const Vehicle * v , const Vehicle * parent )
2006-05-02 22:42:11 +01:00
{
const SpriteGroup * group ;
ResolverObject object ;
2006-06-22 22:25:51 +01:00
NewVehicleResolver ( & object , engine , v ) ;
2006-05-02 22:42:11 +01:00
object . callback = callback ;
object . callback_param1 = param1 ;
object . callback_param2 = param2 ;
object . u . vehicle . parent = parent ;
2009-05-23 16:25:52 +01:00
group = SpriteGroup : : Resolve ( GetVehicleSpriteGroup ( engine , v , false ) , & object ) ;
2009-05-23 13:13:42 +01:00
if ( group = = NULL ) return CALLBACK_FAILED ;
2006-05-02 22:42:11 +01:00
2009-05-23 13:13:42 +01:00
return group - > GetCallbackResult ( ) ;
2006-05-02 22:42:11 +01:00
}
2006-02-03 12:55:21 +00:00
2007-04-18 19:37:40 +01:00
2007-04-20 22:42:06 +01:00
/* Callback 36 handlers */
2009-09-22 20:28:57 +01:00
uint GetVehicleProperty ( const Vehicle * v , PropertyID property , uint orig_value )
2007-04-18 19:37:40 +01:00
{
uint16 callback = GetVehicleCallback ( CBID_VEHICLE_MODIFY_PROPERTY , property , 0 , v - > engine_type , v ) ;
if ( callback ! = CALLBACK_FAILED ) return callback ;
return orig_value ;
}
2009-09-22 20:28:57 +01:00
uint GetEngineProperty ( EngineID engine , PropertyID property , uint orig_value )
2007-04-20 22:42:06 +01:00
{
uint16 callback = GetVehicleCallback ( CBID_VEHICLE_MODIFY_PROPERTY , property , 0 , engine , NULL ) ;
if ( callback ! = CALLBACK_FAILED ) return callback ;
return orig_value ;
}
2006-04-28 00:28:56 +01:00
static void DoTriggerVehicle ( Vehicle * v , VehicleTrigger trigger , byte base_random_bits , bool first )
2006-02-03 12:55:21 +00:00
{
const SpriteGroup * group ;
2006-04-28 21:04:57 +01:00
ResolverObject object ;
2006-02-03 12:55:21 +00:00
byte new_random_bits ;
2006-04-28 21:04:57 +01:00
/* We can't trigger a non-existent vehicle... */
assert ( v ! = NULL ) ;
2006-02-03 12:55:21 +00:00
2006-06-22 22:25:51 +01:00
NewVehicleResolver ( & object , v - > engine_type , v ) ;
2007-07-05 07:35:09 +01:00
object . callback = CBID_RANDOM_TRIGGER ;
2006-04-28 21:04:57 +01:00
object . trigger = trigger ;
2009-05-23 16:25:52 +01:00
group = SpriteGroup : : Resolve ( GetVehicleSpriteGroup ( v - > engine_type , v ) , & object ) ;
2007-11-11 17:58:05 +00:00
if ( group = = NULL ) return ;
2006-02-03 12:55:21 +00:00
new_random_bits = Random ( ) ;
2006-04-28 21:04:57 +01:00
v - > random_bits & = ~ object . reseed ;
v - > random_bits | = ( first ? new_random_bits : base_random_bits ) & object . reseed ;
2006-02-03 12:55:21 +00:00
switch ( trigger ) {
case VEHICLE_TRIGGER_NEW_CARGO :
/* All vehicles in chain get ANY_NEW_CARGO trigger now.
2009-03-15 00:32:18 +00:00
* So we call it for the first one and they will recurse .
* Indexing part of vehicle random bits needs to be
2006-02-03 12:55:21 +00:00
* same for all triggered vehicles in the chain ( to get
* all the random - cargo wagons carry the same cargo ,
* i . e . ) , so we give them all the NEW_CARGO triggered
* vehicle ' s portion of random bits . */
assert ( first ) ;
2007-09-09 16:32:46 +01:00
DoTriggerVehicle ( v - > First ( ) , VEHICLE_TRIGGER_ANY_NEW_CARGO , new_random_bits , false ) ;
2006-02-03 12:55:21 +00:00
break ;
2006-04-28 00:28:56 +01:00
2006-02-03 12:55:21 +00:00
case VEHICLE_TRIGGER_DEPOT :
/* We now trigger the next vehicle in chain recursively.
* The random bits portions may be different for each
* vehicle in chain . */
2007-08-30 14:03:56 +01:00
if ( v - > Next ( ) ! = NULL ) DoTriggerVehicle ( v - > Next ( ) , trigger , 0 , true ) ;
2006-02-03 12:55:21 +00:00
break ;
2006-04-28 00:28:56 +01:00
2006-02-03 12:55:21 +00:00
case VEHICLE_TRIGGER_EMPTY :
/* We now trigger the next vehicle in chain
* recursively . The random bits portions must be same
* for each vehicle in chain , so we give them all
* first chained vehicle ' s portion of random bits . */
2007-08-30 14:03:56 +01:00
if ( v - > Next ( ) ! = NULL ) DoTriggerVehicle ( v - > Next ( ) , trigger , first ? new_random_bits : base_random_bits , false ) ;
2006-02-03 12:55:21 +00:00
break ;
2006-04-28 00:28:56 +01:00
2006-02-03 12:55:21 +00:00
case VEHICLE_TRIGGER_ANY_NEW_CARGO :
/* Now pass the trigger recursively to the next vehicle
* in chain . */
assert ( ! first ) ;
2007-08-30 14:03:56 +01:00
if ( v - > Next ( ) ! = NULL ) DoTriggerVehicle ( v - > Next ( ) , VEHICLE_TRIGGER_ANY_NEW_CARGO , base_random_bits , false ) ;
2006-02-03 12:55:21 +00:00
break ;
2007-10-28 16:00:51 +00:00
case VEHICLE_TRIGGER_CALLBACK_32 :
/* Do not do any recursion */
break ;
2006-02-03 12:55:21 +00:00
}
}
2006-04-28 00:28:56 +01:00
void TriggerVehicle ( Vehicle * v , VehicleTrigger trigger )
2006-02-03 12:55:21 +00:00
{
if ( trigger = = VEHICLE_TRIGGER_DEPOT ) {
2007-03-21 03:06:21 +00:00
/* store that the vehicle entered a depot this tick */
2006-04-28 00:28:56 +01:00
VehicleEnteredDepotThisTick ( v ) ;
2006-02-03 12:55:21 +00:00
}
2009-05-31 13:03:14 +01:00
v - > InvalidateNewGRFCacheOfChain ( ) ;
2006-04-28 00:28:56 +01:00
DoTriggerVehicle ( v , trigger , 0 , true ) ;
2009-05-31 13:03:14 +01:00
v - > InvalidateNewGRFCacheOfChain ( ) ;
2006-02-03 12:55:21 +00:00
}
2007-03-21 03:06:21 +00:00
/* Functions for changing the order of vehicle purchase lists
* This is currently only implemented for rail vehicles . */
2006-02-04 21:48:46 +00:00
2006-10-11 19:35:40 +01:00
/**
* Get the list position of an engine .
* Used when sorting a list of engines .
* @ param engine ID of the engine .
* @ return The list position of the engine .
*/
2008-04-29 22:31:29 +01:00
uint ListPositionOfEngine ( EngineID engine )
2006-10-11 19:35:40 +01:00
{
2009-05-17 00:34:14 +01:00
const Engine * e = Engine : : Get ( engine ) ;
2008-04-29 22:31:29 +01:00
if ( e - > grffile = = NULL ) return e - > list_position ;
/* Crude sorting to group by GRF ID */
return ( e - > grffile - > grfid * 256 ) + e - > list_position ;
2006-02-04 21:48:46 +00:00
}
2008-04-29 22:31:29 +01:00
struct ListOrderChange {
EngineID engine ;
EngineID target ;
} ;
2008-12-13 15:59:25 +00:00
static SmallVector < ListOrderChange , 16 > _list_order_changes ;
2008-04-29 22:31:29 +01:00
2008-07-20 22:23:28 +01:00
void AlterVehicleListOrder ( EngineID engine , EngineID target )
2006-02-04 21:48:46 +00:00
{
2008-04-29 22:31:29 +01:00
/* Add the list order change to a queue */
2008-12-13 15:59:25 +00:00
ListOrderChange * loc = _list_order_changes . Append ( ) ;
loc - > engine = engine ;
loc - > target = target ;
2008-04-29 22:31:29 +01:00
}
2008-07-20 22:23:28 +01:00
void CommitVehicleListOrderChanges ( )
2008-04-29 22:31:29 +01:00
{
/* List position to Engine map */
2008-12-26 13:50:46 +00:00
typedef SmallMap < uint16 , Engine * , 16 > ListPositionMap ;
2008-04-29 22:31:29 +01:00
ListPositionMap lptr_map ;
2008-12-13 15:59:25 +00:00
const ListOrderChange * end = _list_order_changes . End ( ) ;
for ( const ListOrderChange * it = _list_order_changes . Begin ( ) ; it ! = end ; + + it ) {
2008-04-29 22:31:29 +01:00
EngineID engine = it - > engine ;
EngineID target = it - > target ;
if ( engine = = target ) continue ;
2009-05-17 00:34:14 +01:00
Engine * source_e = Engine : : Get ( engine ) ;
2008-04-29 22:31:29 +01:00
Engine * target_e = NULL ;
/* Populate map with current list positions */
Engine * e ;
2008-07-20 22:23:28 +01:00
FOR_ALL_ENGINES_OF_TYPE ( e , source_e - > type ) {
2008-05-29 16:13:28 +01:00
if ( ! _settings_game . vehicle . dynamic_engines | | e - > grffile = = source_e - > grffile ) {
2008-04-29 22:31:29 +01:00
if ( e - > internal_id = = target ) target_e = e ;
lptr_map [ e - > list_position ] = e ;
}
}
2006-02-04 21:48:46 +00:00
2008-12-30 21:04:09 +00:00
/* std::map sorted by default, SmallMap does not */
lptr_map . SortByKey ( ) ;
2008-04-29 22:31:29 +01:00
/* Get the target position, if it exists */
if ( target_e ! = NULL ) {
uint16 target_position = target_e - > list_position ;
2006-02-04 21:48:46 +00:00
2008-04-29 22:31:29 +01:00
bool moving = false ;
2008-12-26 13:50:46 +00:00
const ListPositionMap : : Pair * end = lptr_map . End ( ) ;
for ( ListPositionMap : : Pair * it = lptr_map . Begin ( ) ; it ! = end ; + + it ) {
2008-04-29 22:31:29 +01:00
if ( it - > first = = target_position ) moving = true ;
if ( moving ) it - > second - > list_position + + ;
}
2006-02-04 21:48:46 +00:00
2008-04-29 22:31:29 +01:00
source_e - > list_position = target_position ;
2006-02-04 21:48:46 +00:00
}
2006-10-11 19:35:40 +01:00
2008-12-26 13:50:46 +00:00
lptr_map . Clear ( ) ;
2006-10-11 19:35:40 +01:00
}
2008-04-29 22:31:29 +01:00
/* Clear out the queue */
2008-12-13 15:59:25 +00:00
_list_order_changes . Reset ( ) ;
2006-02-04 21:48:46 +00:00
}
2010-04-24 14:35:18 +01:00
/**
* Resolve an engine ' s spec and such so we can get a variable .
* @ param ro The resolver object to fill .
* @ param index The vehicle to get the data from .
*/
void GetVehicleResolver ( ResolverObject * ro , uint index )
{
Vehicle * v = Vehicle : : Get ( index ) ;
NewVehicleResolver ( ro , v - > engine_type , v ) ;
}