1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
8 /** @file newgrf_engine.cpp NewGRF handling of engines. */
9 
10 #include "stdafx.h"
11 #include "debug.h"
12 #include "train.h"
13 #include "roadveh.h"
14 #include "company_func.h"
15 #include "newgrf_cargo.h"
16 #include "newgrf_spritegroup.h"
17 #include "date_func.h"
18 #include "vehicle_func.h"
19 #include "core/random_func.hpp"
20 #include "aircraft.h"
21 #include "station_base.h"
22 #include "company_base.h"
23 #include "newgrf_railtype.h"
24 #include "newgrf_roadtype.h"
25 #include "ship.h"
26 
27 #include "safeguards.h"
28 
SetWagonOverrideSprites(EngineID engine,CargoID cargo,const SpriteGroup * group,EngineID * train_id,uint trains)29 void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const SpriteGroup *group, EngineID *train_id, uint trains)
30 {
31 	Engine *e = Engine::Get(engine);
32 
33 	assert(cargo < NUM_CARGO + 2); // Include CT_DEFAULT and CT_PURCHASE pseudo cargoes.
34 
35 	WagonOverride *wo = &e->overrides.emplace_back();
36 	wo->group = group;
37 	wo->cargo = cargo;
38 	wo->engines.assign(train_id, train_id + trains);
39 }
40 
GetWagonOverrideSpriteSet(EngineID engine,CargoID cargo,EngineID overriding_engine)41 const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, EngineID overriding_engine)
42 {
43 	const Engine *e = Engine::Get(engine);
44 
45 	for (const WagonOverride &wo : e->overrides) {
46 		if (wo.cargo != cargo && wo.cargo != CT_DEFAULT) continue;
47 		if (std::find(wo.engines.begin(), wo.engines.end(), overriding_engine) != wo.engines.end()) return wo.group;
48 	}
49 	return nullptr;
50 }
51 
SetCustomEngineSprites(EngineID engine,byte cargo,const SpriteGroup * group)52 void SetCustomEngineSprites(EngineID engine, byte cargo, const SpriteGroup *group)
53 {
54 	Engine *e = Engine::Get(engine);
55 	assert(cargo < lengthof(e->grf_prop.spritegroup));
56 
57 	if (e->grf_prop.spritegroup[cargo] != nullptr) {
58 		grfmsg(6, "SetCustomEngineSprites: engine %d cargo %d already has group -- replacing", engine, cargo);
59 	}
60 	e->grf_prop.spritegroup[cargo] = group;
61 }
62 
63 
64 /**
65  * Tie a GRFFile entry to an engine, to allow us to retrieve GRF parameters
66  * etc during a game.
67  * @param engine Engine ID to tie the GRFFile to.
68  * @param file   Pointer of GRFFile to tie.
69  */
SetEngineGRF(EngineID engine,const GRFFile * file)70 void SetEngineGRF(EngineID engine, const GRFFile *file)
71 {
72 	Engine *e = Engine::Get(engine);
73 	e->grf_prop.grffile = file;
74 }
75 
76 
MapOldSubType(const Vehicle * v)77 static int MapOldSubType(const Vehicle *v)
78 {
79 	switch (v->type) {
80 		case VEH_TRAIN:
81 			if (Train::From(v)->IsEngine()) return 0;
82 			if (Train::From(v)->IsFreeWagon()) return 4;
83 			return 2;
84 		case VEH_ROAD:
85 		case VEH_SHIP:     return 0;
86 		case VEH_AIRCRAFT:
87 		case VEH_DISASTER: return v->subtype;
88 		case VEH_EFFECT:   return v->subtype << 1;
89 		default: NOT_REACHED();
90 	}
91 }
92 
93 
94 /* TTDP style aircraft movement states for GRF Action 2 Var 0xE2 */
95 enum TTDPAircraftMovementStates {
96 	AMS_TTDP_HANGAR,
97 	AMS_TTDP_TO_HANGAR,
98 	AMS_TTDP_TO_PAD1,
99 	AMS_TTDP_TO_PAD2,
100 	AMS_TTDP_TO_PAD3,
101 	AMS_TTDP_TO_ENTRY_2_AND_3,
102 	AMS_TTDP_TO_ENTRY_2_AND_3_AND_H,
103 	AMS_TTDP_TO_JUNCTION,
104 	AMS_TTDP_LEAVE_RUNWAY,
105 	AMS_TTDP_TO_INWAY,
106 	AMS_TTDP_TO_RUNWAY,
107 	AMS_TTDP_TO_OUTWAY,
108 	AMS_TTDP_WAITING,
109 	AMS_TTDP_TAKEOFF,
110 	AMS_TTDP_TO_TAKEOFF,
111 	AMS_TTDP_CLIMBING,
112 	AMS_TTDP_FLIGHT_APPROACH,
113 	AMS_TTDP_UNUSED_0x11,
114 	AMS_TTDP_FLIGHT_TO_TOWER,
115 	AMS_TTDP_UNUSED_0x13,
116 	AMS_TTDP_FLIGHT_FINAL,
117 	AMS_TTDP_FLIGHT_DESCENT,
118 	AMS_TTDP_BRAKING,
119 	AMS_TTDP_HELI_TAKEOFF_AIRPORT,
120 	AMS_TTDP_HELI_TO_TAKEOFF_AIRPORT,
121 	AMS_TTDP_HELI_LAND_AIRPORT,
122 	AMS_TTDP_HELI_TAKEOFF_HELIPORT,
123 	AMS_TTDP_HELI_TO_TAKEOFF_HELIPORT,
124 	AMS_TTDP_HELI_LAND_HELIPORT,
125 };
126 
127 
128 /**
129  * Map OTTD aircraft movement states to TTDPatch style movement states
130  * (VarAction 2 Variable 0xE2)
131  */
MapAircraftMovementState(const Aircraft * v)132 static byte MapAircraftMovementState(const Aircraft *v)
133 {
134 	const Station *st = GetTargetAirportIfValid(v);
135 	if (st == nullptr) return AMS_TTDP_FLIGHT_TO_TOWER;
136 
137 	const AirportFTAClass *afc = st->airport.GetFTA();
138 	uint16 amdflag = afc->MovingData(v->pos)->flag;
139 
140 	switch (v->state) {
141 		case HANGAR:
142 			/* The international airport is a special case as helicopters can land in
143 			 * front of the hangar. Helicopters also change their air.state to
144 			 * AMED_HELI_LOWER some time before actually descending. */
145 
146 			/* This condition only occurs for helicopters, during descent,
147 			 * to a landing by the hangar of an international airport. */
148 			if (amdflag & AMED_HELI_LOWER) return AMS_TTDP_HELI_LAND_AIRPORT;
149 
150 			/* This condition only occurs for helicopters, before starting descent,
151 			 * to a landing by the hangar of an international airport. */
152 			if (amdflag & AMED_SLOWTURN) return AMS_TTDP_FLIGHT_TO_TOWER;
153 
154 			/* The final two conditions apply to helicopters or aircraft.
155 			 * Has reached hangar? */
156 			if (amdflag & AMED_EXACTPOS) return AMS_TTDP_HANGAR;
157 
158 			/* Still moving towards hangar. */
159 			return AMS_TTDP_TO_HANGAR;
160 
161 		case TERM1:
162 			if (amdflag & AMED_EXACTPOS) return AMS_TTDP_TO_PAD1;
163 			return AMS_TTDP_TO_JUNCTION;
164 
165 		case TERM2:
166 			if (amdflag & AMED_EXACTPOS) return AMS_TTDP_TO_PAD2;
167 			return AMS_TTDP_TO_ENTRY_2_AND_3_AND_H;
168 
169 		case TERM3:
170 		case TERM4:
171 		case TERM5:
172 		case TERM6:
173 		case TERM7:
174 		case TERM8:
175 			/* TTDPatch only has 3 terminals, so treat these states the same */
176 			if (amdflag & AMED_EXACTPOS) return AMS_TTDP_TO_PAD3;
177 			return AMS_TTDP_TO_ENTRY_2_AND_3_AND_H;
178 
179 		case HELIPAD1:
180 		case HELIPAD2:
181 		case HELIPAD3:
182 			/* Will only occur for helicopters.*/
183 			if (amdflag & AMED_HELI_LOWER) return AMS_TTDP_HELI_LAND_AIRPORT; // Descending.
184 			if (amdflag & AMED_SLOWTURN)   return AMS_TTDP_FLIGHT_TO_TOWER;   // Still hasn't started descent.
185 			return AMS_TTDP_TO_JUNCTION; // On the ground.
186 
187 		case TAKEOFF: // Moving to takeoff position.
188 			return AMS_TTDP_TO_OUTWAY;
189 
190 		case STARTTAKEOFF: // Accelerating down runway.
191 			return AMS_TTDP_TAKEOFF;
192 
193 		case ENDTAKEOFF: // Ascent
194 			return AMS_TTDP_CLIMBING;
195 
196 		case HELITAKEOFF: // Helicopter is moving to take off position.
197 			if (afc->delta_z == 0) {
198 				return amdflag & AMED_HELI_RAISE ?
199 					AMS_TTDP_HELI_TAKEOFF_AIRPORT : AMS_TTDP_TO_JUNCTION;
200 			} else {
201 				return AMS_TTDP_HELI_TAKEOFF_HELIPORT;
202 			}
203 
204 		case FLYING:
205 			return amdflag & AMED_HOLD ? AMS_TTDP_FLIGHT_APPROACH : AMS_TTDP_FLIGHT_TO_TOWER;
206 
207 		case LANDING: // Descent
208 			return AMS_TTDP_FLIGHT_DESCENT;
209 
210 		case ENDLANDING: // On the runway braking
211 			if (amdflag & AMED_BRAKE) return AMS_TTDP_BRAKING;
212 			/* Landed - moving off runway */
213 			return AMS_TTDP_TO_INWAY;
214 
215 		case HELILANDING:
216 		case HELIENDLANDING: // Helicoptor is descending.
217 			if (amdflag & AMED_HELI_LOWER) {
218 				return afc->delta_z == 0 ?
219 					AMS_TTDP_HELI_LAND_AIRPORT : AMS_TTDP_HELI_LAND_HELIPORT;
220 			} else {
221 				return AMS_TTDP_FLIGHT_TO_TOWER;
222 			}
223 
224 		default:
225 			return AMS_TTDP_HANGAR;
226 	}
227 }
228 
229 
230 /* TTDP style aircraft movement action for GRF Action 2 Var 0xE6 */
231 enum TTDPAircraftMovementActions {
232 	AMA_TTDP_IN_HANGAR,
233 	AMA_TTDP_ON_PAD1,
234 	AMA_TTDP_ON_PAD2,
235 	AMA_TTDP_ON_PAD3,
236 	AMA_TTDP_HANGAR_TO_PAD1,
237 	AMA_TTDP_HANGAR_TO_PAD2,
238 	AMA_TTDP_HANGAR_TO_PAD3,
239 	AMA_TTDP_LANDING_TO_PAD1,
240 	AMA_TTDP_LANDING_TO_PAD2,
241 	AMA_TTDP_LANDING_TO_PAD3,
242 	AMA_TTDP_PAD1_TO_HANGAR,
243 	AMA_TTDP_PAD2_TO_HANGAR,
244 	AMA_TTDP_PAD3_TO_HANGAR,
245 	AMA_TTDP_PAD1_TO_TAKEOFF,
246 	AMA_TTDP_PAD2_TO_TAKEOFF,
247 	AMA_TTDP_PAD3_TO_TAKEOFF,
248 	AMA_TTDP_HANGAR_TO_TAKOFF,
249 	AMA_TTDP_LANDING_TO_HANGAR,
250 	AMA_TTDP_IN_FLIGHT,
251 };
252 
253 
254 /**
255  * Map OTTD aircraft movement states to TTDPatch style movement actions
256  * (VarAction 2 Variable 0xE6)
257  * This is not fully supported yet but it's enough for Planeset.
258  */
MapAircraftMovementAction(const Aircraft * v)259 static byte MapAircraftMovementAction(const Aircraft *v)
260 {
261 	switch (v->state) {
262 		case HANGAR:
263 			return (v->cur_speed > 0) ? AMA_TTDP_LANDING_TO_HANGAR : AMA_TTDP_IN_HANGAR;
264 
265 		case TERM1:
266 		case HELIPAD1:
267 			return (v->current_order.IsType(OT_LOADING)) ? AMA_TTDP_ON_PAD1 : AMA_TTDP_LANDING_TO_PAD1;
268 
269 		case TERM2:
270 		case HELIPAD2:
271 			return (v->current_order.IsType(OT_LOADING)) ? AMA_TTDP_ON_PAD2 : AMA_TTDP_LANDING_TO_PAD2;
272 
273 		case TERM3:
274 		case TERM4:
275 		case TERM5:
276 		case TERM6:
277 		case TERM7:
278 		case TERM8:
279 		case HELIPAD3:
280 			return (v->current_order.IsType(OT_LOADING)) ? AMA_TTDP_ON_PAD3 : AMA_TTDP_LANDING_TO_PAD3;
281 
282 		case TAKEOFF:      // Moving to takeoff position
283 		case STARTTAKEOFF: // Accelerating down runway
284 		case ENDTAKEOFF:   // Ascent
285 		case HELITAKEOFF:
286 			/* @todo Need to find which terminal (or hangar) we've come from. How? */
287 			return AMA_TTDP_PAD1_TO_TAKEOFF;
288 
289 		case FLYING:
290 			return AMA_TTDP_IN_FLIGHT;
291 
292 		case LANDING:    // Descent
293 		case ENDLANDING: // On the runway braking
294 		case HELILANDING:
295 		case HELIENDLANDING:
296 			/* @todo Need to check terminal we're landing to. Is it known yet? */
297 			return (v->current_order.IsType(OT_GOTO_DEPOT)) ?
298 				AMA_TTDP_LANDING_TO_HANGAR : AMA_TTDP_LANDING_TO_PAD1;
299 
300 		default:
301 			return AMA_TTDP_IN_HANGAR;
302 	}
303 }
304 
305 
GetRandomBits() const306 /* virtual */ uint32 VehicleScopeResolver::GetRandomBits() const
307 {
308 	return this->v == nullptr ? 0 : this->v->random_bits;
309 }
310 
GetTriggers() const311 /* virtual */ uint32 VehicleScopeResolver::GetTriggers() const
312 {
313 	return this->v == nullptr ? 0 : this->v->waiting_triggers;
314 }
315 
316 
GetScope(VarSpriteGroupScope scope,byte relative)317 /* virtual */ ScopeResolver *VehicleResolverObject::GetScope(VarSpriteGroupScope scope, byte relative)
318 {
319 	switch (scope) {
320 		case VSG_SCOPE_SELF:   return &this->self_scope;
321 		case VSG_SCOPE_PARENT: return &this->parent_scope;
322 		case VSG_SCOPE_RELATIVE: {
323 			int32 count = GB(relative, 0, 4);
324 			if (this->self_scope.v != nullptr && (relative != this->cached_relative_count || count == 0)) {
325 				/* Note: This caching only works as long as the VSG_SCOPE_RELATIVE cannot be used in
326 				 *       VarAct2 with procedure calls. */
327 				if (count == 0) count = GetRegister(0x100);
328 
329 				const Vehicle *v = nullptr;
330 				switch (GB(relative, 6, 2)) {
331 					default: NOT_REACHED();
332 					case 0x00: // count back (away from the engine), starting at this vehicle
333 						v = this->self_scope.v;
334 						break;
335 					case 0x01: // count forward (toward the engine), starting at this vehicle
336 						v = this->self_scope.v;
337 						count = -count;
338 						break;
339 					case 0x02: // count back, starting at the engine
340 						v = this->parent_scope.v;
341 						break;
342 					case 0x03: { // count back, starting at the first vehicle in this chain of vehicles with the same ID, as for vehicle variable 41
343 						const Vehicle *self = this->self_scope.v;
344 						for (const Vehicle *u = self->First(); u != self; u = u->Next()) {
345 							if (u->engine_type != self->engine_type) {
346 								v = nullptr;
347 							} else {
348 								if (v == nullptr) v = u;
349 							}
350 						}
351 						if (v == nullptr) v = self;
352 						break;
353 					}
354 				}
355 				this->relative_scope.SetVehicle(v->Move(count));
356 			}
357 			return &this->relative_scope;
358 		}
359 		default: return ResolverObject::GetScope(scope, relative);
360 	}
361 }
362 
363 /**
364  * Determines the livery of an engine.
365  *
366  * This always uses dual company colours independent of GUI settings. So it is desync-safe.
367  *
368  * @param engine Engine type
369  * @param v Vehicle, nullptr in purchase list.
370  * @return Livery to use
371  */
LiveryHelper(EngineID engine,const Vehicle * v)372 static const Livery *LiveryHelper(EngineID engine, const Vehicle *v)
373 {
374 	const Livery *l;
375 
376 	if (v == nullptr) {
377 		if (!Company::IsValidID(_current_company)) return nullptr;
378 		l = GetEngineLivery(engine, _current_company, INVALID_ENGINE, nullptr, LIT_ALL);
379 	} else if (v->IsGroundVehicle()) {
380 		l = GetEngineLivery(v->engine_type, v->owner, v->GetGroundVehicleCache()->first_engine, v, LIT_ALL);
381 	} else {
382 		l = GetEngineLivery(v->engine_type, v->owner, INVALID_ENGINE, v, LIT_ALL);
383 	}
384 
385 	return l;
386 }
387 
388 /**
389  * Helper to get the position of a vehicle within a chain of vehicles.
390  * @param v the vehicle to get the position of.
391  * @param consecutive whether to look at the whole chain or the vehicles
392  *                    with the same 'engine type'.
393  * @return the position in the chain from front and tail and chain length.
394  */
PositionHelper(const Vehicle * v,bool consecutive)395 static uint32 PositionHelper(const Vehicle *v, bool consecutive)
396 {
397 	const Vehicle *u;
398 	byte chain_before = 0;
399 	byte chain_after  = 0;
400 
401 	for (u = v->First(); u != v; u = u->Next()) {
402 		chain_before++;
403 		if (consecutive && u->engine_type != v->engine_type) chain_before = 0;
404 	}
405 
406 	while (u->Next() != nullptr && (!consecutive || u->Next()->engine_type == v->engine_type)) {
407 		chain_after++;
408 		u = u->Next();
409 	}
410 
411 	return chain_before | chain_after << 8 | (chain_before + chain_after + consecutive) << 16;
412 }
413 
VehicleGetVariable(Vehicle * v,const VehicleScopeResolver * object,byte variable,uint32 parameter,bool * available)414 static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, byte variable, uint32 parameter, bool *available)
415 {
416 	/* Calculated vehicle parameters */
417 	switch (variable) {
418 		case 0x25: // Get engine GRF ID
419 			return v->GetGRFID();
420 
421 		case 0x40: // Get length of consist
422 			if (!HasBit(v->grf_cache.cache_valid, NCVV_POSITION_CONSIST_LENGTH)) {
423 				v->grf_cache.position_consist_length = PositionHelper(v, false);
424 				SetBit(v->grf_cache.cache_valid, NCVV_POSITION_CONSIST_LENGTH);
425 			}
426 			return v->grf_cache.position_consist_length;
427 
428 		case 0x41: // Get length of same consecutive wagons
429 			if (!HasBit(v->grf_cache.cache_valid, NCVV_POSITION_SAME_ID_LENGTH)) {
430 				v->grf_cache.position_same_id_length = PositionHelper(v, true);
431 				SetBit(v->grf_cache.cache_valid, NCVV_POSITION_SAME_ID_LENGTH);
432 			}
433 			return v->grf_cache.position_same_id_length;
434 
435 		case 0x42: { // Consist cargo information
436 			if (!HasBit(v->grf_cache.cache_valid, NCVV_CONSIST_CARGO_INFORMATION)) {
437 				const Vehicle *u;
438 				byte cargo_classes = 0;
439 				uint8 common_cargoes[NUM_CARGO];
440 				uint8 common_subtypes[256];
441 				byte user_def_data = 0;
442 				CargoID common_cargo_type = CT_INVALID;
443 				uint8 common_subtype = 0xFF; // Return 0xFF if nothing is carried
444 
445 				/* Reset our arrays */
446 				memset(common_cargoes, 0, sizeof(common_cargoes));
447 				memset(common_subtypes, 0, sizeof(common_subtypes));
448 
449 				for (u = v; u != nullptr; u = u->Next()) {
450 					if (v->type == VEH_TRAIN) user_def_data |= Train::From(u)->tcache.user_def_data;
451 
452 					/* Skip empty engines */
453 					if (!u->GetEngine()->CanCarryCargo()) continue;
454 
455 					cargo_classes |= CargoSpec::Get(u->cargo_type)->classes;
456 					common_cargoes[u->cargo_type]++;
457 				}
458 
459 				/* Pick the most common cargo type */
460 				uint common_cargo_best_amount = 0;
461 				for (CargoID cargo = 0; cargo < NUM_CARGO; cargo++) {
462 					if (common_cargoes[cargo] > common_cargo_best_amount) {
463 						common_cargo_best_amount = common_cargoes[cargo];
464 						common_cargo_type = cargo;
465 					}
466 				}
467 
468 				/* Count subcargo types of common_cargo_type */
469 				for (u = v; u != nullptr; u = u->Next()) {
470 					/* Skip empty engines and engines not carrying common_cargo_type */
471 					if (u->cargo_type != common_cargo_type || !u->GetEngine()->CanCarryCargo()) continue;
472 
473 					common_subtypes[u->cargo_subtype]++;
474 				}
475 
476 				/* Pick the most common subcargo type*/
477 				uint common_subtype_best_amount = 0;
478 				for (uint i = 0; i < lengthof(common_subtypes); i++) {
479 					if (common_subtypes[i] > common_subtype_best_amount) {
480 						common_subtype_best_amount = common_subtypes[i];
481 						common_subtype = i;
482 					}
483 				}
484 
485 				/* Note: We have to store the untranslated cargotype in the cache as the cache can be read by different NewGRFs,
486 				 *       which will need different translations */
487 				v->grf_cache.consist_cargo_information = cargo_classes | (common_cargo_type << 8) | (common_subtype << 16) | (user_def_data << 24);
488 				SetBit(v->grf_cache.cache_valid, NCVV_CONSIST_CARGO_INFORMATION);
489 			}
490 
491 			/* The cargo translation is specific to the accessing GRF, and thus cannot be cached. */
492 			CargoID common_cargo_type = (v->grf_cache.consist_cargo_information >> 8) & 0xFF;
493 
494 			/* Note:
495 			 *  - Unlike everywhere else the cargo translation table is only used since grf version 8, not 7.
496 			 *  - For translating the cargo type we need to use the GRF which is resolving the variable, which
497 			 *    is object->ro.grffile.
498 			 *    In case of CBID_TRAIN_ALLOW_WAGON_ATTACH this is not the same as v->GetGRF().
499 			 *  - The grffile == nullptr case only happens if this function is called for default vehicles.
500 			 *    And this is only done by CheckCaches().
501 			 */
502 			const GRFFile *grffile = object->ro.grffile;
503 			uint8 common_bitnum = (common_cargo_type == CT_INVALID) ? 0xFF :
504 				(grffile == nullptr || grffile->grf_version < 8) ? CargoSpec::Get(common_cargo_type)->bitnum : grffile->cargo_map[common_cargo_type];
505 
506 			return (v->grf_cache.consist_cargo_information & 0xFFFF00FF) | common_bitnum << 8;
507 		}
508 
509 		case 0x43: // Company information
510 			if (!HasBit(v->grf_cache.cache_valid, NCVV_COMPANY_INFORMATION)) {
511 				v->grf_cache.company_information = GetCompanyInfo(v->owner, LiveryHelper(v->engine_type, v));
512 				SetBit(v->grf_cache.cache_valid, NCVV_COMPANY_INFORMATION);
513 			}
514 			return v->grf_cache.company_information;
515 
516 		case 0x44: // Aircraft information
517 			if (v->type != VEH_AIRCRAFT || !Aircraft::From(v)->IsNormalAircraft()) return UINT_MAX;
518 
519 			{
520 				const Vehicle *w = v->Next();
521 				uint16 altitude = ClampToU16(v->z_pos - w->z_pos); // Aircraft height - shadow height
522 				byte airporttype = ATP_TTDP_LARGE;
523 
524 				const Station *st = GetTargetAirportIfValid(Aircraft::From(v));
525 
526 				if (st != nullptr && st->airport.tile != INVALID_TILE) {
527 					airporttype = st->airport.GetSpec()->ttd_airport_type;
528 				}
529 
530 				return (Clamp(altitude, 0, 0xFF) << 8) | airporttype;
531 			}
532 
533 		case 0x45: { // Curvature info
534 			/* Format: xxxTxBxF
535 			 * F - previous wagon to current wagon, 0 if vehicle is first
536 			 * B - current wagon to next wagon, 0 if wagon is last
537 			 * T - previous wagon to next wagon, 0 in an S-bend
538 			 */
539 			if (!v->IsGroundVehicle()) return 0;
540 
541 			const Vehicle *u_p = v->Previous();
542 			const Vehicle *u_n = v->Next();
543 			DirDiff f = (u_p == nullptr) ?  DIRDIFF_SAME : DirDifference(u_p->direction, v->direction);
544 			DirDiff b = (u_n == nullptr) ?  DIRDIFF_SAME : DirDifference(v->direction, u_n->direction);
545 			DirDiff t = ChangeDirDiff(f, b);
546 
547 			return ((t > DIRDIFF_REVERSE ? t | 8 : t) << 16) |
548 			       ((b > DIRDIFF_REVERSE ? b | 8 : b) <<  8) |
549 			       ( f > DIRDIFF_REVERSE ? f | 8 : f);
550 		}
551 
552 		case 0x46: // Motion counter
553 			return v->motion_counter;
554 
555 		case 0x47: { // Vehicle cargo info
556 			/* Format: ccccwwtt
557 			 * tt - the cargo type transported by the vehicle,
558 			 *     translated if a translation table has been installed.
559 			 * ww - cargo unit weight in 1/16 tons, same as cargo prop. 0F.
560 			 * cccc - the cargo class value of the cargo transported by the vehicle.
561 			 */
562 			const CargoSpec *cs = CargoSpec::Get(v->cargo_type);
563 
564 			/* Note:
565 			 * For translating the cargo type we need to use the GRF which is resolving the variable, which
566 			 * is object->ro.grffile.
567 			 * In case of CBID_TRAIN_ALLOW_WAGON_ATTACH this is not the same as v->GetGRF().
568 			 */
569 			return (cs->classes << 16) | (cs->weight << 8) | object->ro.grffile->cargo_map[v->cargo_type];
570 		}
571 
572 		case 0x48: return v->GetEngine()->flags; // Vehicle Type Info
573 		case 0x49: return v->build_year;
574 
575 		case 0x4A:
576 			switch (v->type) {
577 				case VEH_TRAIN: {
578 					RailType rt = GetTileRailType(v->tile);
579 					const RailtypeInfo *rti = GetRailTypeInfo(rt);
580 					return ((rti->flags & RTFB_CATENARY) ? 0x200 : 0) |
581 						(HasPowerOnRail(Train::From(v)->railtype, rt) ? 0x100 : 0) |
582 						GetReverseRailTypeTranslation(rt, object->ro.grffile);
583 				}
584 
585 				case VEH_ROAD: {
586 					RoadType rt = GetRoadType(v->tile, GetRoadTramType(RoadVehicle::From(v)->roadtype));
587 					const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
588 					return ((rti->flags & ROTFB_CATENARY) ? 0x200 : 0) |
589 						0x100 |
590 						GetReverseRoadTypeTranslation(rt, object->ro.grffile);
591 				}
592 
593 				default:
594 					return 0;
595 			}
596 
597 		case 0x4B: // Long date of last service
598 			return v->date_of_last_service;
599 
600 		case 0x4C: // Current maximum speed in NewGRF units
601 			if (!v->IsPrimaryVehicle()) return 0;
602 			return v->GetCurrentMaxSpeed();
603 
604 		case 0x4D: // Position within articulated vehicle
605 			if (!HasBit(v->grf_cache.cache_valid, NCVV_POSITION_IN_VEHICLE)) {
606 				byte artic_before = 0;
607 				for (const Vehicle *u = v; u->IsArticulatedPart(); u = u->Previous()) artic_before++;
608 				byte artic_after = 0;
609 				for (const Vehicle *u = v; u->HasArticulatedPart(); u = u->Next()) artic_after++;
610 				v->grf_cache.position_in_vehicle = artic_before | artic_after << 8;
611 				SetBit(v->grf_cache.cache_valid, NCVV_POSITION_IN_VEHICLE);
612 			}
613 			return v->grf_cache.position_in_vehicle;
614 
615 		/* Variables which use the parameter */
616 		case 0x60: // Count consist's engine ID occurrence
617 			if (v->type != VEH_TRAIN) return v->GetEngine()->grf_prop.local_id == parameter ? 1 : 0;
618 
619 			{
620 				uint count = 0;
621 				for (; v != nullptr; v = v->Next()) {
622 					if (v->GetEngine()->grf_prop.local_id == parameter) count++;
623 				}
624 				return count;
625 			}
626 
627 		case 0x61: // Get variable of n-th vehicle in chain [signed number relative to vehicle]
628 			if (!v->IsGroundVehicle() || parameter == 0x61) {
629 				/* Not available */
630 				break;
631 			}
632 
633 			/* Only allow callbacks that don't change properties to avoid circular dependencies. */
634 			if (object->ro.callback == CBID_NO_CALLBACK || object->ro.callback == CBID_RANDOM_TRIGGER || object->ro.callback == CBID_TRAIN_ALLOW_WAGON_ATTACH ||
635 					object->ro.callback == CBID_VEHICLE_START_STOP_CHECK || object->ro.callback == CBID_VEHICLE_32DAY_CALLBACK || object->ro.callback == CBID_VEHICLE_COLOUR_MAPPING ||
636 					object->ro.callback == CBID_VEHICLE_SPAWN_VISUAL_EFFECT) {
637 				Vehicle *u = v->Move((int32)GetRegister(0x10F));
638 				if (u == nullptr) return 0; // available, but zero
639 
640 				if (parameter == 0x5F) {
641 					/* This seems to be the only variable that makes sense to access via var 61, but is not handled by VehicleGetVariable */
642 					return (u->random_bits << 8) | u->waiting_triggers;
643 				} else {
644 					return VehicleGetVariable(u, object, parameter, GetRegister(0x10E), available);
645 				}
646 			}
647 			/* Not available */
648 			break;
649 
650 		case 0x62: { // Curvature/position difference for n-th vehicle in chain [signed number relative to vehicle]
651 			/* Format: zzyyxxFD
652 			 * zz - Signed difference of z position between the selected and this vehicle.
653 			 * yy - Signed difference of y position between the selected and this vehicle.
654 			 * xx - Signed difference of x position between the selected and this vehicle.
655 			 * F  - Flags, bit 7 corresponds to VS_HIDDEN.
656 			 * D  - Dir difference, like in 0x45.
657 			 */
658 			if (!v->IsGroundVehicle()) return 0;
659 
660 			const Vehicle *u = v->Move((int8)parameter);
661 			if (u == nullptr) return 0;
662 
663 			/* Get direction difference. */
664 			bool prev = (int8)parameter < 0;
665 			uint32 ret = prev ? DirDifference(u->direction, v->direction) : DirDifference(v->direction, u->direction);
666 			if (ret > DIRDIFF_REVERSE) ret |= 0x08;
667 
668 			if (u->vehstatus & VS_HIDDEN) ret |= 0x80;
669 
670 			/* Get position difference. */
671 			ret |= ((prev ? u->x_pos - v->x_pos : v->x_pos - u->x_pos) & 0xFF) << 8;
672 			ret |= ((prev ? u->y_pos - v->y_pos : v->y_pos - u->y_pos) & 0xFF) << 16;
673 			ret |= ((prev ? u->z_pos - v->z_pos : v->z_pos - u->z_pos) & 0xFF) << 24;
674 
675 			return ret;
676 		}
677 
678 		case 0x63:
679 			/* Tile compatibility wrt. arbitrary track-type
680 			 * Format:
681 			 *  bit 0: Type 'parameter' is known.
682 			 *  bit 1: Engines with type 'parameter' are compatible with this tile.
683 			 *  bit 2: Engines with type 'parameter' are powered on this tile.
684 			 *  bit 3: This tile has type 'parameter' or it is considered equivalent (alternate labels).
685 			 */
686 			switch (v->type) {
687 				case VEH_TRAIN: {
688 					RailType param_type = GetRailTypeTranslation(parameter, object->ro.grffile);
689 					if (param_type == INVALID_RAILTYPE) return 0x00;
690 					RailType tile_type = GetTileRailType(v->tile);
691 					if (tile_type == param_type) return 0x0F;
692 					return (HasPowerOnRail(param_type, tile_type) ? 0x04 : 0x00) |
693 							(IsCompatibleRail(param_type, tile_type) ? 0x02 : 0x00) |
694 							0x01;
695 				}
696 				case VEH_ROAD: {
697 					RoadTramType rtt = GetRoadTramType(RoadVehicle::From(v)->roadtype);
698 					RoadType param_type = GetRoadTypeTranslation(rtt, parameter, object->ro.grffile);
699 					if (param_type == INVALID_ROADTYPE) return 0x00;
700 					RoadType tile_type = GetRoadType(v->tile, rtt);
701 					if (tile_type == param_type) return 0x0F;
702 					return (HasPowerOnRoad(param_type, tile_type) ? 0x06 : 0x00) |
703 							0x01;
704 				}
705 				default: return 0x00;
706 			}
707 
708 		case 0xFE:
709 		case 0xFF: {
710 			uint16 modflags = 0;
711 
712 			if (v->type == VEH_TRAIN) {
713 				const Train *t = Train::From(v);
714 				bool is_powered_wagon = HasBit(t->flags, VRF_POWEREDWAGON);
715 				const Train *u = is_powered_wagon ? t->First() : t; // for powered wagons the engine defines the type of engine (i.e. railtype)
716 				RailType railtype = GetRailType(v->tile);
717 				bool powered = t->IsEngine() || is_powered_wagon;
718 				bool has_power = HasPowerOnRail(u->railtype, railtype);
719 
720 				if (powered && has_power) SetBit(modflags, 5);
721 				if (powered && !has_power) SetBit(modflags, 6);
722 				if (HasBit(t->flags, VRF_TOGGLE_REVERSE)) SetBit(modflags, 8);
723 			}
724 			if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING)) SetBit(modflags, 1);
725 			if (HasBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE)) SetBit(modflags, 10);
726 
727 			return variable == 0xFE ? modflags : GB(modflags, 8, 8);
728 		}
729 	}
730 
731 	/*
732 	 * General vehicle properties
733 	 *
734 	 * Some parts of the TTD Vehicle structure are omitted for various reasons
735 	 * (see http://marcin.ttdpatch.net/sv1codec/TTD-locations.html#_VehicleArray)
736 	 */
737 	switch (variable - 0x80) {
738 		case 0x00: return v->type + 0x10;
739 		case 0x01: return MapOldSubType(v);
740 		case 0x02: break; // not implemented
741 		case 0x03: break; // not implemented
742 		case 0x04: return v->index;
743 		case 0x05: return GB(v->index, 8, 8);
744 		case 0x06: break; // not implemented
745 		case 0x07: break; // not implemented
746 		case 0x08: break; // not implemented
747 		case 0x09: break; // not implemented
748 		case 0x0A: return v->current_order.MapOldOrder();
749 		case 0x0B: return v->current_order.GetDestination();
750 		case 0x0C: return v->GetNumOrders();
751 		case 0x0D: return v->cur_real_order_index;
752 		case 0x0E: break; // not implemented
753 		case 0x0F: break; // not implemented
754 		case 0x10:
755 		case 0x11: {
756 			uint ticks;
757 			if (v->current_order.IsType(OT_LOADING)) {
758 				ticks = v->load_unload_ticks;
759 			} else {
760 				switch (v->type) {
761 					case VEH_TRAIN:    ticks = Train::From(v)->wait_counter; break;
762 					case VEH_AIRCRAFT: ticks = Aircraft::From(v)->turn_counter; break;
763 					default:           ticks = 0; break;
764 				}
765 			}
766 			return (variable - 0x80) == 0x10 ? ticks : GB(ticks, 8, 8);
767 		}
768 		case 0x12: return Clamp(v->date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF);
769 		case 0x13: return GB(Clamp(v->date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF), 8, 8);
770 		case 0x14: return v->GetServiceInterval();
771 		case 0x15: return GB(v->GetServiceInterval(), 8, 8);
772 		case 0x16: return v->last_station_visited;
773 		case 0x17: return v->tick_counter;
774 		case 0x18:
775 		case 0x19: {
776 			uint max_speed;
777 			switch (v->type) {
778 				case VEH_AIRCRAFT:
779 					max_speed = Aircraft::From(v)->GetSpeedOldUnits(); // Convert to old units.
780 					break;
781 
782 				default:
783 					max_speed = v->vcache.cached_max_speed;
784 					break;
785 			}
786 			return (variable - 0x80) == 0x18 ? max_speed : GB(max_speed, 8, 8);
787 		}
788 		case 0x1A: return v->x_pos;
789 		case 0x1B: return GB(v->x_pos, 8, 8);
790 		case 0x1C: return v->y_pos;
791 		case 0x1D: return GB(v->y_pos, 8, 8);
792 		case 0x1E: return v->z_pos;
793 		case 0x1F: return object->info_view ? DIR_W : v->direction;
794 		case 0x20: break; // not implemented
795 		case 0x21: break; // not implemented
796 		case 0x22: break; // not implemented
797 		case 0x23: break; // not implemented
798 		case 0x24: break; // not implemented
799 		case 0x25: break; // not implemented
800 		case 0x26: break; // not implemented
801 		case 0x27: break; // not implemented
802 		case 0x28: return 0; // cur_image is a potential desyncer due to Action1 in static NewGRFs.
803 		case 0x29: return 0; // cur_image is a potential desyncer due to Action1 in static NewGRFs.
804 		case 0x2A: break; // not implemented
805 		case 0x2B: break; // not implemented
806 		case 0x2C: break; // not implemented
807 		case 0x2D: break; // not implemented
808 		case 0x2E: break; // not implemented
809 		case 0x2F: break; // not implemented
810 		case 0x30: break; // not implemented
811 		case 0x31: break; // not implemented
812 		case 0x32: return v->vehstatus;
813 		case 0x33: return 0; // non-existent high byte of vehstatus
814 		case 0x34: return v->type == VEH_AIRCRAFT ? (v->cur_speed * 10) / 128 : v->cur_speed;
815 		case 0x35: return GB(v->type == VEH_AIRCRAFT ? (v->cur_speed * 10) / 128 : v->cur_speed, 8, 8);
816 		case 0x36: return v->subspeed;
817 		case 0x37: return v->acceleration;
818 		case 0x38: break; // not implemented
819 		case 0x39: return v->cargo_type;
820 		case 0x3A: return v->cargo_cap;
821 		case 0x3B: return GB(v->cargo_cap, 8, 8);
822 		case 0x3C: return ClampToU16(v->cargo.StoredCount());
823 		case 0x3D: return GB(ClampToU16(v->cargo.StoredCount()), 8, 8);
824 		case 0x3E: return v->cargo.Source();
825 		case 0x3F: return ClampU(v->cargo.DaysInTransit(), 0, 0xFF);
826 		case 0x40: return ClampToU16(v->age);
827 		case 0x41: return GB(ClampToU16(v->age), 8, 8);
828 		case 0x42: return ClampToU16(v->max_age);
829 		case 0x43: return GB(ClampToU16(v->max_age), 8, 8);
830 		case 0x44: return Clamp(v->build_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
831 		case 0x45: return v->unitnumber;
832 		case 0x46: return v->GetEngine()->grf_prop.local_id;
833 		case 0x47: return GB(v->GetEngine()->grf_prop.local_id, 8, 8);
834 		case 0x48:
835 			if (v->type != VEH_TRAIN || v->spritenum != 0xFD) return v->spritenum;
836 			return HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION) ? 0xFE : 0xFD;
837 
838 		case 0x49: return v->day_counter;
839 		case 0x4A: return v->breakdowns_since_last_service;
840 		case 0x4B: return v->breakdown_ctr;
841 		case 0x4C: return v->breakdown_delay;
842 		case 0x4D: return v->breakdown_chance;
843 		case 0x4E: return v->reliability;
844 		case 0x4F: return GB(v->reliability, 8, 8);
845 		case 0x50: return v->reliability_spd_dec;
846 		case 0x51: return GB(v->reliability_spd_dec, 8, 8);
847 		case 0x52: return ClampToI32(v->GetDisplayProfitThisYear());
848 		case 0x53: return GB(ClampToI32(v->GetDisplayProfitThisYear()),  8, 24);
849 		case 0x54: return GB(ClampToI32(v->GetDisplayProfitThisYear()), 16, 16);
850 		case 0x55: return GB(ClampToI32(v->GetDisplayProfitThisYear()), 24,  8);
851 		case 0x56: return ClampToI32(v->GetDisplayProfitLastYear());
852 		case 0x57: return GB(ClampToI32(v->GetDisplayProfitLastYear()),  8, 24);
853 		case 0x58: return GB(ClampToI32(v->GetDisplayProfitLastYear()), 16, 16);
854 		case 0x59: return GB(ClampToI32(v->GetDisplayProfitLastYear()), 24,  8);
855 		case 0x5A: return v->Next() == nullptr ? INVALID_VEHICLE : v->Next()->index;
856 		case 0x5B: break; // not implemented
857 		case 0x5C: return ClampToI32(v->value);
858 		case 0x5D: return GB(ClampToI32(v->value),  8, 24);
859 		case 0x5E: return GB(ClampToI32(v->value), 16, 16);
860 		case 0x5F: return GB(ClampToI32(v->value), 24,  8);
861 		case 0x60: break; // not implemented
862 		case 0x61: break; // not implemented
863 		case 0x62: break; // vehicle specific, see below
864 		case 0x63: break; // not implemented
865 		case 0x64: break; // vehicle specific, see below
866 		case 0x65: break; // vehicle specific, see below
867 		case 0x66: break; // vehicle specific, see below
868 		case 0x67: break; // vehicle specific, see below
869 		case 0x68: break; // vehicle specific, see below
870 		case 0x69: break; // vehicle specific, see below
871 		case 0x6A: break; // not implemented
872 		case 0x6B: break; // not implemented
873 		case 0x6C: break; // not implemented
874 		case 0x6D: break; // not implemented
875 		case 0x6E: break; // not implemented
876 		case 0x6F: break; // not implemented
877 		case 0x70: break; // not implemented
878 		case 0x71: break; // not implemented
879 		case 0x72: return v->cargo_subtype;
880 		case 0x73: break; // vehicle specific, see below
881 		case 0x74: break; // vehicle specific, see below
882 		case 0x75: break; // vehicle specific, see below
883 		case 0x76: break; // vehicle specific, see below
884 		case 0x77: break; // vehicle specific, see below
885 		case 0x78: break; // not implemented
886 		case 0x79: break; // not implemented
887 		case 0x7A: return v->random_bits;
888 		case 0x7B: return v->waiting_triggers;
889 		case 0x7C: break; // vehicle specific, see below
890 		case 0x7D: break; // vehicle specific, see below
891 		case 0x7E: break; // not implemented
892 		case 0x7F: break; // vehicle specific, see below
893 	}
894 
895 	/* Vehicle specific properties */
896 	switch (v->type) {
897 		case VEH_TRAIN: {
898 			Train *t = Train::From(v);
899 			switch (variable - 0x80) {
900 				case 0x62: return t->track;
901 				case 0x66: return t->railtype;
902 				case 0x73: return 0x80 + VEHICLE_LENGTH - t->gcache.cached_veh_length;
903 				case 0x74: return t->gcache.cached_power;
904 				case 0x75: return GB(t->gcache.cached_power,  8, 24);
905 				case 0x76: return GB(t->gcache.cached_power, 16, 16);
906 				case 0x77: return GB(t->gcache.cached_power, 24,  8);
907 				case 0x7C: return t->First()->index;
908 				case 0x7D: return GB(t->First()->index, 8, 8);
909 				case 0x7F: return 0; // Used for vehicle reversing hack in TTDP
910 			}
911 			break;
912 		}
913 
914 		case VEH_ROAD: {
915 			RoadVehicle *rv = RoadVehicle::From(v);
916 			switch (variable - 0x80) {
917 				case 0x62: return rv->state;
918 				case 0x64: return rv->blocked_ctr;
919 				case 0x65: return GB(rv->blocked_ctr, 8, 8);
920 				case 0x66: return rv->overtaking;
921 				case 0x67: return rv->overtaking_ctr;
922 				case 0x68: return rv->crashed_ctr;
923 				case 0x69: return GB(rv->crashed_ctr, 8, 8);
924 			}
925 			break;
926 		}
927 
928 		case VEH_SHIP: {
929 			Ship *s = Ship::From(v);
930 			switch (variable - 0x80) {
931 				case 0x62: return s->state;
932 			}
933 			break;
934 		}
935 
936 		case VEH_AIRCRAFT: {
937 			Aircraft *a = Aircraft::From(v);
938 			switch (variable - 0x80) {
939 				case 0x62: return MapAircraftMovementState(a);  // Current movement state
940 				case 0x63: return a->targetairport;             // Airport to which the action refers
941 				case 0x66: return MapAircraftMovementAction(a); // Current movement action
942 			}
943 			break;
944 		}
945 
946 		default: break;
947 	}
948 
949 	Debug(grf, 1, "Unhandled vehicle variable 0x{:X}, type 0x{:X}", variable, (uint)v->type);
950 
951 	*available = false;
952 	return UINT_MAX;
953 }
954 
GetVariable(byte variable,uint32 parameter,bool * available) const955 /* virtual */ uint32 VehicleScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
956 {
957 	if (this->v == nullptr) {
958 		/* Vehicle does not exist, so we're in a purchase list */
959 		switch (variable) {
960 			case 0x43: return GetCompanyInfo(_current_company, LiveryHelper(this->self_type, nullptr)); // Owner information
961 			case 0x46: return 0;               // Motion counter
962 			case 0x47: { // Vehicle cargo info
963 				const Engine *e = Engine::Get(this->self_type);
964 				CargoID cargo_type = e->GetDefaultCargoType();
965 				if (cargo_type != CT_INVALID) {
966 					const CargoSpec *cs = CargoSpec::Get(cargo_type);
967 					return (cs->classes << 16) | (cs->weight << 8) | this->ro.grffile->cargo_map[cargo_type];
968 				} else {
969 					return 0x000000FF;
970 				}
971 			}
972 			case 0x48: return Engine::Get(this->self_type)->flags; // Vehicle Type Info
973 			case 0x49: return _cur_year; // 'Long' format build year
974 			case 0x4B: return _date; // Long date of last service
975 			case 0x92: return Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF); // Date of last service
976 			case 0x93: return GB(Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF), 8, 8);
977 			case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
978 			case 0xDA: return INVALID_VEHICLE; // Next vehicle
979 			case 0xF2: return 0; // Cargo subtype
980 		}
981 
982 		*available = false;
983 		return UINT_MAX;
984 	}
985 
986 	return VehicleGetVariable(const_cast<Vehicle*>(this->v), this, variable, parameter, available);
987 }
988 
989 
ResolveReal(const RealSpriteGroup * group) const990 /* virtual */ const SpriteGroup *VehicleResolverObject::ResolveReal(const RealSpriteGroup *group) const
991 {
992 	const Vehicle *v = this->self_scope.v;
993 
994 	if (v == nullptr) {
995 		if (!group->loading.empty()) return group->loading[0];
996 		if (!group->loaded.empty())  return group->loaded[0];
997 		return nullptr;
998 	}
999 
1000 	bool in_motion = !v->First()->current_order.IsType(OT_LOADING);
1001 
1002 	uint totalsets = in_motion ? (uint)group->loaded.size() : (uint)group->loading.size();
1003 
1004 	if (totalsets == 0) return nullptr;
1005 
1006 	uint set = (v->cargo.StoredCount() * totalsets) / std::max<uint16>(1u, v->cargo_cap);
1007 	set = std::min(set, totalsets - 1);
1008 
1009 	return in_motion ? group->loaded[set] : group->loading[set];
1010 }
1011 
GetFeature() const1012 GrfSpecFeature VehicleResolverObject::GetFeature() const
1013 {
1014 	switch (Engine::Get(this->self_scope.self_type)->type) {
1015 		case VEH_TRAIN: return GSF_TRAINS;
1016 		case VEH_ROAD: return GSF_ROADVEHICLES;
1017 		case VEH_SHIP: return GSF_SHIPS;
1018 		case VEH_AIRCRAFT: return GSF_AIRCRAFT;
1019 		default: return GSF_INVALID;
1020 	}
1021 }
1022 
GetDebugID() const1023 uint32 VehicleResolverObject::GetDebugID() const
1024 {
1025 	return Engine::Get(this->self_scope.self_type)->grf_prop.local_id;
1026 }
1027 
1028 /**
1029  * Get the grf file associated with an engine type.
1030  * @param engine_type Engine to query.
1031  * @return grf file associated with the engine.
1032  */
GetEngineGrfFile(EngineID engine_type)1033 static const GRFFile *GetEngineGrfFile(EngineID engine_type)
1034 {
1035 	const Engine *e = Engine::Get(engine_type);
1036 	return (e != nullptr) ? e->GetGRF() : nullptr;
1037 }
1038 
1039 /**
1040  * Resolver of a vehicle (chain).
1041  * @param engine_type Engine type
1042  * @param v %Vehicle being resolved.
1043  * @param wagon_override Application of wagon overrides.
1044  * @param info_view Indicates if the item is being drawn in an info window.
1045  * @param callback Callback ID.
1046  * @param callback_param1 First parameter (var 10) of the callback.
1047  * @param callback_param2 Second parameter (var 18) of the callback.
1048  */
VehicleResolverObject(EngineID engine_type,const Vehicle * v,WagonOverride wagon_override,bool info_view,CallbackID callback,uint32 callback_param1,uint32 callback_param2)1049 VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, WagonOverride wagon_override, bool info_view,
1050 		CallbackID callback, uint32 callback_param1, uint32 callback_param2)
1051 	: ResolverObject(GetEngineGrfFile(engine_type), callback, callback_param1, callback_param2),
1052 	self_scope(*this, engine_type, v, info_view),
1053 	parent_scope(*this, engine_type, ((v != nullptr) ? v->First() : v), info_view),
1054 	relative_scope(*this, engine_type, v, info_view),
1055 	cached_relative_count(0)
1056 {
1057 	if (wagon_override == WO_SELF) {
1058 		this->root_spritegroup = GetWagonOverrideSpriteSet(engine_type, CT_DEFAULT, engine_type);
1059 	} else {
1060 		if (wagon_override != WO_NONE && v != nullptr && v->IsGroundVehicle()) {
1061 			assert(v->engine_type == engine_type); // overrides make little sense with fake scopes
1062 
1063 			/* For trains we always use cached value, except for callbacks because the override spriteset
1064 			 * to use may be different than the one cached. It happens for callback 0x15 (refit engine),
1065 			 * as v->cargo_type is temporary changed to the new type */
1066 			if (wagon_override == WO_CACHED && v->type == VEH_TRAIN) {
1067 				this->root_spritegroup = Train::From(v)->tcache.cached_override;
1068 			} else {
1069 				this->root_spritegroup = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->GetGroundVehicleCache()->first_engine);
1070 			}
1071 		}
1072 
1073 		if (this->root_spritegroup == nullptr) {
1074 			const Engine *e = Engine::Get(engine_type);
1075 			CargoID cargo = v != nullptr ? v->cargo_type : CT_PURCHASE;
1076 			assert(cargo < lengthof(e->grf_prop.spritegroup));
1077 			this->root_spritegroup = e->grf_prop.spritegroup[cargo] != nullptr ? e->grf_prop.spritegroup[cargo] : e->grf_prop.spritegroup[CT_DEFAULT];
1078 		}
1079 	}
1080 }
1081 
1082 
1083 
GetCustomEngineSprite(EngineID engine,const Vehicle * v,Direction direction,EngineImageType image_type,VehicleSpriteSeq * result)1084 void GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type, VehicleSpriteSeq *result)
1085 {
1086 	VehicleResolverObject object(engine, v, VehicleResolverObject::WO_CACHED, false, CBID_NO_CALLBACK);
1087 	result->Clear();
1088 
1089 	bool sprite_stack = HasBit(EngInfo(engine)->misc_flags, EF_SPRITE_STACK);
1090 	uint max_stack = sprite_stack ? lengthof(result->seq) : 1;
1091 	for (uint stack = 0; stack < max_stack; ++stack) {
1092 		object.ResetState();
1093 		object.callback_param1 = image_type | (stack << 8);
1094 		const SpriteGroup *group = object.Resolve();
1095 		uint32 reg100 = sprite_stack ? GetRegister(0x100) : 0;
1096 		if (group != nullptr && group->GetNumResults() != 0) {
1097 			result->seq[result->count].sprite = group->GetResult() + (direction % group->GetNumResults());
1098 			result->seq[result->count].pal    = GB(reg100, 0, 16); // zero means default recolouring
1099 			result->count++;
1100 		}
1101 		if (!HasBit(reg100, 31)) break;
1102 	}
1103 }
1104 
1105 
GetRotorOverrideSprite(EngineID engine,const struct Aircraft * v,bool info_view,EngineImageType image_type,VehicleSpriteSeq * result)1106 void GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, bool info_view, EngineImageType image_type, VehicleSpriteSeq *result)
1107 {
1108 	const Engine *e = Engine::Get(engine);
1109 
1110 	/* Only valid for helicopters */
1111 	assert(e->type == VEH_AIRCRAFT);
1112 	assert(!(e->u.air.subtype & AIR_CTOL));
1113 
1114 	VehicleResolverObject object(engine, v, VehicleResolverObject::WO_SELF, info_view, CBID_NO_CALLBACK);
1115 	result->Clear();
1116 	uint rotor_pos = v == nullptr || info_view ? 0 : v->Next()->Next()->state;
1117 
1118 	bool sprite_stack = HasBit(e->info.misc_flags, EF_SPRITE_STACK);
1119 	uint max_stack = sprite_stack ? lengthof(result->seq) : 1;
1120 	for (uint stack = 0; stack < max_stack; ++stack) {
1121 		object.ResetState();
1122 		object.callback_param1 = image_type | (stack << 8);
1123 		const SpriteGroup *group = object.Resolve();
1124 		uint32 reg100 = sprite_stack ? GetRegister(0x100) : 0;
1125 		if (group != nullptr && group->GetNumResults() != 0) {
1126 			result->seq[result->count].sprite = group->GetResult() + (rotor_pos % group->GetNumResults());
1127 			result->seq[result->count].pal    = GB(reg100, 0, 16); // zero means default recolouring
1128 			result->count++;
1129 		}
1130 		if (!HasBit(reg100, 31)) break;
1131 	}
1132 }
1133 
1134 
1135 /**
1136  * Check if a wagon is currently using a wagon override
1137  * @param v The wagon to check
1138  * @return true if it is using an override, false otherwise
1139  */
UsesWagonOverride(const Vehicle * v)1140 bool UsesWagonOverride(const Vehicle *v)
1141 {
1142 	assert(v->type == VEH_TRAIN);
1143 	return Train::From(v)->tcache.cached_override != nullptr;
1144 }
1145 
1146 /**
1147  * Evaluate a newgrf callback for vehicles
1148  * @param callback The callback to evaluate
1149  * @param param1   First parameter of the callback
1150  * @param param2   Second parameter of the callback
1151  * @param engine   Engine type of the vehicle to evaluate the callback for
1152  * @param v        The vehicle to evaluate the callback for, or nullptr if it doesn't exist yet
1153  * @return The value the callback returned, or CALLBACK_FAILED if it failed
1154  */
GetVehicleCallback(CallbackID callback,uint32 param1,uint32 param2,EngineID engine,const Vehicle * v)1155 uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
1156 {
1157 	VehicleResolverObject object(engine, v, VehicleResolverObject::WO_UNCACHED, false, callback, param1, param2);
1158 	return object.ResolveCallback();
1159 }
1160 
1161 /**
1162  * Evaluate a newgrf callback for vehicles with a different vehicle for parent scope.
1163  * @param callback The callback to evaluate
1164  * @param param1   First parameter of the callback
1165  * @param param2   Second parameter of the callback
1166  * @param engine   Engine type of the vehicle to evaluate the callback for
1167  * @param v        The vehicle to evaluate the callback for, or nullptr if it doesn't exist yet
1168  * @param parent   The vehicle to use for parent scope
1169  * @return The value the callback returned, or CALLBACK_FAILED if it failed
1170  */
GetVehicleCallbackParent(CallbackID callback,uint32 param1,uint32 param2,EngineID engine,const Vehicle * v,const Vehicle * parent)1171 uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent)
1172 {
1173 	VehicleResolverObject object(engine, v, VehicleResolverObject::WO_NONE, false, callback, param1, param2);
1174 	object.parent_scope.SetVehicle(parent);
1175 	return object.ResolveCallback();
1176 }
1177 
1178 
1179 /* Callback 36 handlers */
GetVehicleProperty(const Vehicle * v,PropertyID property,int orig_value,bool is_signed)1180 int GetVehicleProperty(const Vehicle *v, PropertyID property, int orig_value, bool is_signed)
1181 {
1182 	return GetEngineProperty(v->engine_type, property, orig_value, v, is_signed);
1183 }
1184 
1185 
GetEngineProperty(EngineID engine,PropertyID property,int orig_value,const Vehicle * v,bool is_signed)1186 int GetEngineProperty(EngineID engine, PropertyID property, int orig_value, const Vehicle *v, bool is_signed)
1187 {
1188 	uint16 callback = GetVehicleCallback(CBID_VEHICLE_MODIFY_PROPERTY, property, 0, engine, v);
1189 	if (callback != CALLBACK_FAILED) {
1190 		if (is_signed) {
1191 			/* Sign extend 15 bit integer */
1192 			return static_cast<int16>(callback << 1) / 2;
1193 		} else {
1194 			return callback;
1195 		}
1196 	}
1197 
1198 	return orig_value;
1199 }
1200 
1201 
DoTriggerVehicle(Vehicle * v,VehicleTrigger trigger,byte base_random_bits,bool first)1202 static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_random_bits, bool first)
1203 {
1204 	/* We can't trigger a non-existent vehicle... */
1205 	assert(v != nullptr);
1206 
1207 	VehicleResolverObject object(v->engine_type, v, VehicleResolverObject::WO_CACHED, false, CBID_RANDOM_TRIGGER);
1208 	object.waiting_triggers = v->waiting_triggers | trigger;
1209 	v->waiting_triggers = object.waiting_triggers; // store now for var 5F
1210 
1211 	const SpriteGroup *group = object.Resolve();
1212 	if (group == nullptr) return;
1213 
1214 	/* Store remaining triggers. */
1215 	v->waiting_triggers = object.GetRemainingTriggers();
1216 
1217 	/* Rerandomise bits. Scopes other than SELF are invalid for rerandomisation. For bug-to-bug-compatibility with TTDP we ignore the scope. */
1218 	byte new_random_bits = Random();
1219 	uint32 reseed = object.GetReseedSum();
1220 	v->random_bits &= ~reseed;
1221 	v->random_bits |= (first ? new_random_bits : base_random_bits) & reseed;
1222 
1223 	switch (trigger) {
1224 		case VEHICLE_TRIGGER_NEW_CARGO:
1225 			/* All vehicles in chain get ANY_NEW_CARGO trigger now.
1226 			 * So we call it for the first one and they will recurse.
1227 			 * Indexing part of vehicle random bits needs to be
1228 			 * same for all triggered vehicles in the chain (to get
1229 			 * all the random-cargo wagons carry the same cargo,
1230 			 * i.e.), so we give them all the NEW_CARGO triggered
1231 			 * vehicle's portion of random bits. */
1232 			assert(first);
1233 			DoTriggerVehicle(v->First(), VEHICLE_TRIGGER_ANY_NEW_CARGO, new_random_bits, false);
1234 			break;
1235 
1236 		case VEHICLE_TRIGGER_DEPOT:
1237 			/* We now trigger the next vehicle in chain recursively.
1238 			 * The random bits portions may be different for each
1239 			 * vehicle in chain. */
1240 			if (v->Next() != nullptr) DoTriggerVehicle(v->Next(), trigger, 0, true);
1241 			break;
1242 
1243 		case VEHICLE_TRIGGER_EMPTY:
1244 			/* We now trigger the next vehicle in chain
1245 			 * recursively.  The random bits portions must be same
1246 			 * for each vehicle in chain, so we give them all
1247 			 * first chained vehicle's portion of random bits. */
1248 			if (v->Next() != nullptr) DoTriggerVehicle(v->Next(), trigger, first ? new_random_bits : base_random_bits, false);
1249 			break;
1250 
1251 		case VEHICLE_TRIGGER_ANY_NEW_CARGO:
1252 			/* Now pass the trigger recursively to the next vehicle
1253 			 * in chain. */
1254 			assert(!first);
1255 			if (v->Next() != nullptr) DoTriggerVehicle(v->Next(), VEHICLE_TRIGGER_ANY_NEW_CARGO, base_random_bits, false);
1256 			break;
1257 
1258 		case VEHICLE_TRIGGER_CALLBACK_32:
1259 			/* Do not do any recursion */
1260 			break;
1261 	}
1262 }
1263 
TriggerVehicle(Vehicle * v,VehicleTrigger trigger)1264 void TriggerVehicle(Vehicle *v, VehicleTrigger trigger)
1265 {
1266 	if (trigger == VEHICLE_TRIGGER_DEPOT) {
1267 		/* store that the vehicle entered a depot this tick */
1268 		VehicleEnteredDepotThisTick(v);
1269 	}
1270 
1271 	v->InvalidateNewGRFCacheOfChain();
1272 	DoTriggerVehicle(v, trigger, 0, true);
1273 	v->InvalidateNewGRFCacheOfChain();
1274 }
1275 
1276 /* Functions for changing the order of vehicle purchase lists */
1277 
1278 struct ListOrderChange {
1279 	EngineID engine;
1280 	uint target;      ///< local ID
1281 };
1282 
1283 static std::vector<ListOrderChange> _list_order_changes;
1284 
1285 /**
1286  * Record a vehicle ListOrderChange.
1287  * @param engine Engine to move
1288  * @param target Local engine ID to move \a engine in front of
1289  * @note All sorting is done later in CommitVehicleListOrderChanges
1290  */
AlterVehicleListOrder(EngineID engine,uint target)1291 void AlterVehicleListOrder(EngineID engine, uint target)
1292 {
1293 	/* Add the list order change to a queue */
1294 	_list_order_changes.push_back({engine, target});
1295 }
1296 
1297 /**
1298  * Comparator function to sort engines via scope-GRFID and local ID.
1299  * @param a left side
1300  * @param b right side
1301  * @return comparison result
1302  */
EnginePreSort(const EngineID & a,const EngineID & b)1303 static bool EnginePreSort(const EngineID &a, const EngineID &b)
1304 {
1305 	const EngineIDMapping &id_a = _engine_mngr.at(a);
1306 	const EngineIDMapping &id_b = _engine_mngr.at(b);
1307 
1308 	/* 1. Sort by engine type */
1309 	if (id_a.type != id_b.type) return (int)id_a.type < (int)id_b.type;
1310 
1311 	/* 2. Sort by scope-GRFID */
1312 	if (id_a.grfid != id_b.grfid) return id_a.grfid < id_b.grfid;
1313 
1314 	/* 3. Sort by local ID */
1315 	return (int)id_a.internal_id < (int)id_b.internal_id;
1316 }
1317 
1318 /**
1319  * Deternine default engine sorting and execute recorded ListOrderChanges from AlterVehicleListOrder.
1320  */
CommitVehicleListOrderChanges()1321 void CommitVehicleListOrderChanges()
1322 {
1323 	/* Pre-sort engines by scope-grfid and local index */
1324 	std::vector<EngineID> ordering;
1325 	for (const Engine *e : Engine::Iterate()) {
1326 		ordering.push_back(e->index);
1327 	}
1328 	std::sort(ordering.begin(), ordering.end(), EnginePreSort);
1329 
1330 	/* Apply Insertion-Sort operations */
1331 	for (const ListOrderChange &it : _list_order_changes) {
1332 		EngineID source = it.engine;
1333 		uint local_target = it.target;
1334 
1335 		const EngineIDMapping *id_source = _engine_mngr.data() + source;
1336 		if (id_source->internal_id == local_target) continue;
1337 
1338 		EngineID target = _engine_mngr.GetID(id_source->type, local_target, id_source->grfid);
1339 		if (target == INVALID_ENGINE) continue;
1340 
1341 		int source_index = find_index(ordering, source);
1342 		int target_index = find_index(ordering, target);
1343 
1344 		assert(source_index >= 0 && target_index >= 0);
1345 		assert(source_index != target_index);
1346 
1347 		EngineID *list = ordering.data();
1348 		if (source_index < target_index) {
1349 			--target_index;
1350 			for (int i = source_index; i < target_index; ++i) list[i] = list[i + 1];
1351 			list[target_index] = source;
1352 		} else {
1353 			for (int i = source_index; i > target_index; --i) list[i] = list[i - 1];
1354 			list[target_index] = source;
1355 		}
1356 	}
1357 
1358 	/* Store final sort-order */
1359 	uint index = 0;
1360 	for (const EngineID &eid : ordering) {
1361 		Engine::Get(eid)->list_position = index;
1362 		++index;
1363 	}
1364 
1365 	/* Clear out the queue */
1366 	_list_order_changes.clear();
1367 	_list_order_changes.shrink_to_fit();
1368 }
1369 
1370 /**
1371  * Fill the grf_cache of the given vehicle.
1372  * @param v The vehicle to fill the cache for.
1373  */
FillNewGRFVehicleCache(const Vehicle * v)1374 void FillNewGRFVehicleCache(const Vehicle *v)
1375 {
1376 	VehicleResolverObject ro(v->engine_type, v, VehicleResolverObject::WO_NONE);
1377 
1378 	/* These variables we have to check; these are the ones with a cache. */
1379 	static const int cache_entries[][2] = {
1380 		{ 0x40, NCVV_POSITION_CONSIST_LENGTH },
1381 		{ 0x41, NCVV_POSITION_SAME_ID_LENGTH },
1382 		{ 0x42, NCVV_CONSIST_CARGO_INFORMATION },
1383 		{ 0x43, NCVV_COMPANY_INFORMATION },
1384 		{ 0x4D, NCVV_POSITION_IN_VEHICLE },
1385 	};
1386 	static_assert(NCVV_END == lengthof(cache_entries));
1387 
1388 	/* Resolve all the variables, so their caches are set. */
1389 	for (size_t i = 0; i < lengthof(cache_entries); i++) {
1390 		/* Only resolve when the cache isn't valid. */
1391 		if (HasBit(v->grf_cache.cache_valid, cache_entries[i][1])) continue;
1392 		bool stub;
1393 		ro.GetScope(VSG_SCOPE_SELF)->GetVariable(cache_entries[i][0], 0, &stub);
1394 	}
1395 
1396 	/* Make sure really all bits are set. */
1397 	assert(v->grf_cache.cache_valid == (1 << NCVV_END) - 1);
1398 }
1399