Merge branch 'development' into master_joker
[openttd-joker.git] / src / newgrf_engine.cpp
bloba3cc75be13f7e0b49835c698c3a1a245dff542cd
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file newgrf_engine.cpp NewGRF handling of engines. */
12 #include "stdafx.h"
13 #include "debug.h"
14 #include "train.h"
15 #include "roadveh.h"
16 #include "company_func.h"
17 #include "newgrf_cargo.h"
18 #include "newgrf_spritegroup.h"
19 #include "date_func.h"
20 #include "vehicle_func.h"
21 #include "core/random_func.hpp"
22 #include "aircraft.h"
23 #include "station_base.h"
24 #include "company_base.h"
25 #include "newgrf_railtype.h"
26 #include "newgrf_roadtype.h"
27 #include "ship.h"
29 #include "safeguards.h"
31 struct WagonOverride {
32 EngineID *train_id;
33 uint trains;
34 CargoID cargo;
35 const SpriteGroup *group;
38 void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const SpriteGroup *group, EngineID *train_id, uint trains)
40 Engine *e = Engine::Get(engine);
41 WagonOverride *wo;
43 assert(cargo < NUM_CARGO + 2); // Include CT_DEFAULT and CT_PURCHASE pseudo cargoes.
45 e->overrides_count++;
46 e->overrides = ReallocT(e->overrides, e->overrides_count);
48 wo = &e->overrides[e->overrides_count - 1];
49 wo->group = group;
50 wo->cargo = cargo;
51 wo->trains = trains;
52 wo->train_id = MallocT<EngineID>(trains);
53 memcpy(wo->train_id, train_id, trains * sizeof *train_id);
56 const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, EngineID overriding_engine)
58 const Engine *e = Engine::Get(engine);
60 for (uint i = 0; i < e->overrides_count; i++) {
61 const WagonOverride *wo = &e->overrides[i];
63 if (wo->cargo != cargo && wo->cargo != CT_DEFAULT) continue;
65 for (uint j = 0; j < wo->trains; j++) {
66 if (wo->train_id[j] == overriding_engine) return wo->group;
69 return nullptr;
72 /**
73 * Unload all wagon override sprite groups.
75 void UnloadWagonOverrides(Engine *e)
77 for (uint i = 0; i < e->overrides_count; i++) {
78 WagonOverride *wo = &e->overrides[i];
79 free(wo->train_id);
81 free(e->overrides);
82 e->overrides_count = 0;
83 e->overrides = nullptr;
87 void SetCustomEngineSprites(EngineID engine, byte cargo, const SpriteGroup *group)
89 Engine *e = Engine::Get(engine);
90 assert(cargo < lengthof(e->grf_prop.spritegroup));
92 if (e->grf_prop.spritegroup[cargo] != nullptr) {
93 grfmsg(6, "SetCustomEngineSprites: engine %d cargo %d already has group -- replacing", engine, cargo);
95 e->grf_prop.spritegroup[cargo] = group;
99 /**
100 * Tie a GRFFile entry to an engine, to allow us to retrieve GRF parameters
101 * etc during a game.
102 * @param engine Engine ID to tie the GRFFile to.
103 * @param file Pointer of GRFFile to tie.
105 void SetEngineGRF(EngineID engine, const GRFFile *file)
107 Engine *e = Engine::Get(engine);
108 e->grf_prop.grffile = file;
112 static int MapOldSubType(const Vehicle *v)
114 switch (v->type) {
115 case VEH_TRAIN:
116 if (Train::From(v)->IsEngine()) return 0;
117 if (Train::From(v)->IsFreeWagon()) return 4;
118 return 2;
119 case VEH_ROAD:
120 case VEH_SHIP: return 0;
121 case VEH_AIRCRAFT:
122 case VEH_DISASTER: return v->subtype;
123 case VEH_EFFECT: return v->subtype << 1;
124 default: NOT_REACHED();
129 /* TTDP style aircraft movement states for GRF Action 2 Var 0xE2 */
130 enum TTDPAircraftMovementStates {
131 AMS_TTDP_HANGAR,
132 AMS_TTDP_TO_HANGAR,
133 AMS_TTDP_TO_PAD1,
134 AMS_TTDP_TO_PAD2,
135 AMS_TTDP_TO_PAD3,
136 AMS_TTDP_TO_ENTRY_2_AND_3,
137 AMS_TTDP_TO_ENTRY_2_AND_3_AND_H,
138 AMS_TTDP_TO_JUNCTION,
139 AMS_TTDP_LEAVE_RUNWAY,
140 AMS_TTDP_TO_INWAY,
141 AMS_TTDP_TO_RUNWAY,
142 AMS_TTDP_TO_OUTWAY,
143 AMS_TTDP_WAITING,
144 AMS_TTDP_TAKEOFF,
145 AMS_TTDP_TO_TAKEOFF,
146 AMS_TTDP_CLIMBING,
147 AMS_TTDP_FLIGHT_APPROACH,
148 AMS_TTDP_UNUSED_0x11,
149 AMS_TTDP_FLIGHT_TO_TOWER,
150 AMS_TTDP_UNUSED_0x13,
151 AMS_TTDP_FLIGHT_FINAL,
152 AMS_TTDP_FLIGHT_DESCENT,
153 AMS_TTDP_BRAKING,
154 AMS_TTDP_HELI_TAKEOFF_AIRPORT,
155 AMS_TTDP_HELI_TO_TAKEOFF_AIRPORT,
156 AMS_TTDP_HELI_LAND_AIRPORT,
157 AMS_TTDP_HELI_TAKEOFF_HELIPORT,
158 AMS_TTDP_HELI_TO_TAKEOFF_HELIPORT,
159 AMS_TTDP_HELI_LAND_HELIPORT,
164 * Map OTTD aircraft movement states to TTDPatch style movement states
165 * (VarAction 2 Variable 0xE2)
167 static byte MapAircraftMovementState(const Aircraft *v)
169 const Station *st = GetTargetAirportIfValid(v);
170 if (st == nullptr) return AMS_TTDP_FLIGHT_TO_TOWER;
172 const AirportFTAClass *afc = st->airport.GetFTA();
173 uint16 amdflag = afc->MovingData(v->pos)->flag;
175 switch (v->state) {
176 case HANGAR:
177 /* The international airport is a special case as helicopters can land in
178 * front of the hangar. Helicopters also change their air.state to
179 * AMED_HELI_LOWER some time before actually descending. */
181 /* This condition only occurs for helicopters, during descent,
182 * to a landing by the hangar of an international airport. */
183 if (amdflag & AMED_HELI_LOWER) return AMS_TTDP_HELI_LAND_AIRPORT;
185 /* This condition only occurs for helicopters, before starting descent,
186 * to a landing by the hangar of an international airport. */
187 if (amdflag & AMED_SLOWTURN) return AMS_TTDP_FLIGHT_TO_TOWER;
189 /* The final two conditions apply to helicopters or aircraft.
190 * Has reached hangar? */
191 if (amdflag & AMED_EXACTPOS) return AMS_TTDP_HANGAR;
193 /* Still moving towards hangar. */
194 return AMS_TTDP_TO_HANGAR;
196 case TERM1:
197 if (amdflag & AMED_EXACTPOS) return AMS_TTDP_TO_PAD1;
198 return AMS_TTDP_TO_JUNCTION;
200 case TERM2:
201 if (amdflag & AMED_EXACTPOS) return AMS_TTDP_TO_PAD2;
202 return AMS_TTDP_TO_ENTRY_2_AND_3_AND_H;
204 case TERM3:
205 case TERM4:
206 case TERM5:
207 case TERM6:
208 case TERM7:
209 case TERM8:
210 /* TTDPatch only has 3 terminals, so treat these states the same */
211 if (amdflag & AMED_EXACTPOS) return AMS_TTDP_TO_PAD3;
212 return AMS_TTDP_TO_ENTRY_2_AND_3_AND_H;
214 case HELIPAD1:
215 case HELIPAD2:
216 case HELIPAD3:
217 /* Will only occur for helicopters.*/
218 if (amdflag & AMED_HELI_LOWER) return AMS_TTDP_HELI_LAND_AIRPORT; // Descending.
219 if (amdflag & AMED_SLOWTURN) return AMS_TTDP_FLIGHT_TO_TOWER; // Still hasn't started descent.
220 return AMS_TTDP_TO_JUNCTION; // On the ground.
222 case TAKEOFF: // Moving to takeoff position.
223 return AMS_TTDP_TO_OUTWAY;
225 case STARTTAKEOFF: // Accelerating down runway.
226 return AMS_TTDP_TAKEOFF;
228 case ENDTAKEOFF: // Ascent
229 return AMS_TTDP_CLIMBING;
231 case HELITAKEOFF: // Helicopter is moving to take off position.
232 if (afc->delta_z == 0) {
233 return amdflag & AMED_HELI_RAISE ?
234 AMS_TTDP_HELI_TAKEOFF_AIRPORT : AMS_TTDP_TO_JUNCTION;
235 } else {
236 return AMS_TTDP_HELI_TAKEOFF_HELIPORT;
239 case FLYING:
240 return amdflag & AMED_HOLD ? AMS_TTDP_FLIGHT_APPROACH : AMS_TTDP_FLIGHT_TO_TOWER;
242 case LANDING: // Descent
243 return AMS_TTDP_FLIGHT_DESCENT;
245 case ENDLANDING: // On the runway braking
246 if (amdflag & AMED_BRAKE) return AMS_TTDP_BRAKING;
247 /* Landed - moving off runway */
248 return AMS_TTDP_TO_INWAY;
250 case HELILANDING:
251 case HELIENDLANDING: // Helicoptor is decending.
252 if (amdflag & AMED_HELI_LOWER) {
253 return afc->delta_z == 0 ?
254 AMS_TTDP_HELI_LAND_AIRPORT : AMS_TTDP_HELI_LAND_HELIPORT;
255 } else {
256 return AMS_TTDP_FLIGHT_TO_TOWER;
259 default:
260 return AMS_TTDP_HANGAR;
265 /* TTDP style aircraft movement action for GRF Action 2 Var 0xE6 */
266 enum TTDPAircraftMovementActions {
267 AMA_TTDP_IN_HANGAR,
268 AMA_TTDP_ON_PAD1,
269 AMA_TTDP_ON_PAD2,
270 AMA_TTDP_ON_PAD3,
271 AMA_TTDP_HANGAR_TO_PAD1,
272 AMA_TTDP_HANGAR_TO_PAD2,
273 AMA_TTDP_HANGAR_TO_PAD3,
274 AMA_TTDP_LANDING_TO_PAD1,
275 AMA_TTDP_LANDING_TO_PAD2,
276 AMA_TTDP_LANDING_TO_PAD3,
277 AMA_TTDP_PAD1_TO_HANGAR,
278 AMA_TTDP_PAD2_TO_HANGAR,
279 AMA_TTDP_PAD3_TO_HANGAR,
280 AMA_TTDP_PAD1_TO_TAKEOFF,
281 AMA_TTDP_PAD2_TO_TAKEOFF,
282 AMA_TTDP_PAD3_TO_TAKEOFF,
283 AMA_TTDP_HANGAR_TO_TAKOFF,
284 AMA_TTDP_LANDING_TO_HANGAR,
285 AMA_TTDP_IN_FLIGHT,
290 * Map OTTD aircraft movement states to TTDPatch style movement actions
291 * (VarAction 2 Variable 0xE6)
292 * This is not fully supported yet but it's enough for Planeset.
294 static byte MapAircraftMovementAction(const Aircraft *v)
296 switch (v->state) {
297 case HANGAR:
298 return (v->cur_speed > 0) ? AMA_TTDP_LANDING_TO_HANGAR : AMA_TTDP_IN_HANGAR;
300 case TERM1:
301 case HELIPAD1:
302 return (v->current_order.IsType(OT_LOADING)) ? AMA_TTDP_ON_PAD1 : AMA_TTDP_LANDING_TO_PAD1;
304 case TERM2:
305 case HELIPAD2:
306 return (v->current_order.IsType(OT_LOADING)) ? AMA_TTDP_ON_PAD2 : AMA_TTDP_LANDING_TO_PAD2;
308 case TERM3:
309 case TERM4:
310 case TERM5:
311 case TERM6:
312 case TERM7:
313 case TERM8:
314 case HELIPAD3:
315 return (v->current_order.IsType(OT_LOADING)) ? AMA_TTDP_ON_PAD3 : AMA_TTDP_LANDING_TO_PAD3;
317 case TAKEOFF: // Moving to takeoff position
318 case STARTTAKEOFF: // Accelerating down runway
319 case ENDTAKEOFF: // Ascent
320 case HELITAKEOFF:
321 /* @todo Need to find which terminal (or hangar) we've come from. How? */
322 return AMA_TTDP_PAD1_TO_TAKEOFF;
324 case FLYING:
325 return AMA_TTDP_IN_FLIGHT;
327 case LANDING: // Descent
328 case ENDLANDING: // On the runway braking
329 case HELILANDING:
330 case HELIENDLANDING:
331 /* @todo Need to check terminal we're landing to. Is it known yet? */
332 return (v->current_order.IsType(OT_GOTO_DEPOT)) ?
333 AMA_TTDP_LANDING_TO_HANGAR : AMA_TTDP_LANDING_TO_PAD1;
335 default:
336 return AMA_TTDP_IN_HANGAR;
341 /* virtual */ uint32 VehicleScopeResolver::GetRandomBits() const
343 return this->v == nullptr ? 0 : this->v->random_bits;
346 /* virtual */ uint32 VehicleScopeResolver::GetTriggers() const
348 return this->v == nullptr ? 0 : this->v->waiting_triggers;
352 /* virtual */ ScopeResolver *VehicleResolverObject::GetScope(VarSpriteGroupScope scope, byte relative)
354 switch (scope) {
355 case VSG_SCOPE_SELF: return &this->self_scope;
356 case VSG_SCOPE_PARENT: return &this->parent_scope;
357 case VSG_SCOPE_RELATIVE: {
358 int32 count = GB(relative, 0, 4);
359 if (this->self_scope.v != nullptr && (relative != this->cached_relative_count || count == 0)) {
360 /* Note: This caching only works as long as the VSG_SCOPE_RELATIVE cannot be used in
361 * VarAct2 with procedure calls. */
362 if (count == 0) count = GetRegister(0x100);
364 const Vehicle *v = nullptr;
365 switch (GB(relative, 6, 2)) {
366 default: NOT_REACHED();
367 case 0x00: // count back (away from the engine), starting at this vehicle
368 v = this->self_scope.v;
369 break;
370 case 0x01: // count forward (toward the engine), starting at this vehicle
371 v = this->self_scope.v;
372 count = -count;
373 break;
374 case 0x02: // count back, starting at the engine
375 v = this->parent_scope.v;
376 break;
377 case 0x03: { // count back, starting at the first vehicle in this chain of vehicles with the same ID, as for vehicle variable 41
378 const Vehicle *self = this->self_scope.v;
379 for (const Vehicle *u = self->First(); u != self; u = u->Next()) {
380 if (u->engine_type != self->engine_type) {
381 v = nullptr;
382 } else {
383 if (v == nullptr) v = u;
386 if (v == nullptr) v = self;
387 break;
390 this->relative_scope.SetVehicle(v->Move(count));
392 return &this->relative_scope;
394 default: return ResolverObject::GetScope(scope, relative);
399 * Determines the livery of an engine.
401 * This always uses dual company colours independent of GUI settings. So it is desync-safe.
403 * @param engine Engine type
404 * @param v Vehicle, nullptr in purchase list.
405 * @return Livery to use
407 static const Livery *LiveryHelper(EngineID engine, const Vehicle *v)
409 const Livery *l;
411 if (v == nullptr) {
412 if (!Company::IsValidID(_current_company)) return nullptr;
413 l = GetEngineLivery(engine, _current_company, INVALID_ENGINE, nullptr, LIT_ALL);
414 } else if (v->IsGroundVehicle()) {
415 l = GetEngineLivery(v->engine_type, v->owner, v->GetGroundVehicleCache()->first_engine, v, LIT_ALL);
416 } else {
417 l = GetEngineLivery(v->engine_type, v->owner, INVALID_ENGINE, v, LIT_ALL);
420 return l;
424 * Helper to get the position of a vehicle within a chain of vehicles.
425 * @param v the vehicle to get the position of.
426 * @param consecutive whether to look at the whole chain or the vehicles
427 * with the same 'engine type'.
428 * @return the position in the chain from front and tail and chain length.
430 static uint32 PositionHelper(const Vehicle *v, bool consecutive)
432 const Vehicle *u;
433 byte chain_before = 0;
434 byte chain_after = 0;
436 for (u = v->First(); u != v; u = u->Next()) {
437 chain_before++;
438 if (consecutive && u->engine_type != v->engine_type) chain_before = 0;
441 while (u->Next() != nullptr && (!consecutive || u->Next()->engine_type == v->engine_type)) {
442 chain_after++;
443 u = u->Next();
446 return chain_before | chain_after << 8 | (chain_before + chain_after + consecutive) << 16;
449 static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, byte variable, uint32 parameter, bool *available)
451 /* Calculated vehicle parameters */
452 switch (variable) {
453 case 0x25: // Get engine GRF ID
454 return v->GetGRFID();
456 case 0x40: // Get length of consist
457 if (!HasBit(v->grf_cache.cache_valid, NCVV_POSITION_CONSIST_LENGTH)) {
458 v->grf_cache.position_consist_length = PositionHelper(v, false);
459 SetBit(v->grf_cache.cache_valid, NCVV_POSITION_CONSIST_LENGTH);
461 return v->grf_cache.position_consist_length;
463 case 0x41: // Get length of same consecutive wagons
464 if (!HasBit(v->grf_cache.cache_valid, NCVV_POSITION_SAME_ID_LENGTH)) {
465 v->grf_cache.position_same_id_length = PositionHelper(v, true);
466 SetBit(v->grf_cache.cache_valid, NCVV_POSITION_SAME_ID_LENGTH);
468 return v->grf_cache.position_same_id_length;
470 case 0x42: { // Consist cargo information
471 if (!HasBit(v->grf_cache.cache_valid, NCVV_CONSIST_CARGO_INFORMATION)) {
472 const Vehicle *u;
473 byte cargo_classes = 0;
474 uint8 common_cargoes[NUM_CARGO];
475 uint8 common_subtypes[256];
476 byte user_def_data = 0;
477 CargoID common_cargo_type = CT_INVALID;
478 uint8 common_subtype = 0xFF; // Return 0xFF if nothing is carried
480 /* Reset our arrays */
481 memset(common_cargoes, 0, sizeof(common_cargoes));
482 memset(common_subtypes, 0, sizeof(common_subtypes));
484 for (u = v; u != nullptr; u = u->Next()) {
485 if (v->type == VEH_TRAIN) user_def_data |= Train::From(u)->tcache.user_def_data;
487 /* Skip empty engines */
488 if (!u->GetEngine()->CanCarryCargo()) continue;
490 cargo_classes |= CargoSpec::Get(u->cargo_type)->classes;
491 common_cargoes[u->cargo_type]++;
494 /* Pick the most common cargo type */
495 uint common_cargo_best_amount = 0;
496 for (CargoID cargo = 0; cargo < NUM_CARGO; cargo++) {
497 if (common_cargoes[cargo] > common_cargo_best_amount) {
498 common_cargo_best_amount = common_cargoes[cargo];
499 common_cargo_type = cargo;
503 /* Count subcargo types of common_cargo_type */
504 for (u = v; u != nullptr; u = u->Next()) {
505 /* Skip empty engines and engines not carrying common_cargo_type */
506 if (u->cargo_type != common_cargo_type || !u->GetEngine()->CanCarryCargo()) continue;
508 common_subtypes[u->cargo_subtype]++;
511 /* Pick the most common subcargo type*/
512 uint common_subtype_best_amount = 0;
513 for (uint i = 0; i < lengthof(common_subtypes); i++) {
514 if (common_subtypes[i] > common_subtype_best_amount) {
515 common_subtype_best_amount = common_subtypes[i];
516 common_subtype = i;
520 /* Note: We have to store the untranslated cargotype in the cache as the cache can be read by different NewGRFs,
521 * which will need different translations */
522 v->grf_cache.consist_cargo_information = cargo_classes | (common_cargo_type << 8) | (common_subtype << 16) | (user_def_data << 24);
523 SetBit(v->grf_cache.cache_valid, NCVV_CONSIST_CARGO_INFORMATION);
526 /* The cargo translation is specific to the accessing GRF, and thus cannot be cached. */
527 CargoID common_cargo_type = (v->grf_cache.consist_cargo_information >> 8) & 0xFF;
529 /* Note:
530 * - Unlike everywhere else the cargo translation table is only used since grf version 8, not 7.
531 * - For translating the cargo type we need to use the GRF which is resolving the variable, which
532 * is object->ro.grffile.
533 * In case of CBID_TRAIN_ALLOW_WAGON_ATTACH this is not the same as v->GetGRF().
534 * - The grffile == nullptr case only happens if this function is called for default vehicles.
535 * And this is only done by CheckCaches().
537 const GRFFile *grffile = object->ro.grffile;
538 uint8 common_bitnum = (common_cargo_type == CT_INVALID) ? 0xFF :
539 (grffile == nullptr || grffile->grf_version < 8) ? CargoSpec::Get(common_cargo_type)->bitnum : grffile->cargo_map[common_cargo_type];
541 return (v->grf_cache.consist_cargo_information & 0xFFFF00FF) | common_bitnum << 8;
544 case 0x43: // Company information
545 if (!HasBit(v->grf_cache.cache_valid, NCVV_COMPANY_INFORMATION)) {
546 v->grf_cache.company_information = GetCompanyInfo(v->owner, LiveryHelper(v->engine_type, v));
547 SetBit(v->grf_cache.cache_valid, NCVV_COMPANY_INFORMATION);
549 return v->grf_cache.company_information;
551 case 0x44: // Aircraft information
552 if (v->type != VEH_AIRCRAFT || !Aircraft::From(v)->IsNormalAircraft()) return UINT_MAX;
555 const Vehicle *w = v->Next();
556 uint16 altitude = ClampToU16(v->z_pos - w->z_pos); // Aircraft height - shadow height
557 byte airporttype = ATP_TTDP_LARGE;
559 const Station *st = GetTargetAirportIfValid(Aircraft::From(v));
561 if (st != nullptr && st->airport.tile != INVALID_TILE) {
562 airporttype = st->airport.GetSpec()->ttd_airport_type;
565 return (Clamp(altitude, 0, 0xFF) << 8) | airporttype;
568 case 0x45: { // Curvature info
569 /* Format: xxxTxBxF
570 * F - previous wagon to current wagon, 0 if vehicle is first
571 * B - current wagon to next wagon, 0 if wagon is last
572 * T - previous wagon to next wagon, 0 in an S-bend
574 if (!v->IsGroundVehicle()) return 0;
576 const Vehicle *u_p = v->Previous();
577 const Vehicle *u_n = v->Next();
578 DirDiff f = (u_p == nullptr) ? DIRDIFF_SAME : DirDifference(u_p->direction, v->direction);
579 DirDiff b = (u_n == nullptr) ? DIRDIFF_SAME : DirDifference(v->direction, u_n->direction);
580 DirDiff t = ChangeDirDiff(f, b);
582 return ((t > DIRDIFF_REVERSE ? t | 8 : t) << 16) |
583 ((b > DIRDIFF_REVERSE ? b | 8 : b) << 8) |
584 ( f > DIRDIFF_REVERSE ? f | 8 : f);
587 case 0x46: // Motion counter
588 return v->motion_counter;
590 case 0x47: { // Vehicle cargo info
591 /* Format: ccccwwtt
592 * tt - the cargo type transported by the vehicle,
593 * translated if a translation table has been installed.
594 * ww - cargo unit weight in 1/16 tons, same as cargo prop. 0F.
595 * cccc - the cargo class value of the cargo transported by the vehicle.
597 const CargoSpec *cs = CargoSpec::Get(v->cargo_type);
599 /* Note:
600 * For translating the cargo type we need to use the GRF which is resolving the variable, which
601 * is object->ro.grffile.
602 * In case of CBID_TRAIN_ALLOW_WAGON_ATTACH this is not the same as v->GetGRF().
604 return (cs->classes << 16) | (cs->weight << 8) | object->ro.grffile->cargo_map[v->cargo_type];
607 case 0x48: return v->GetEngine()->flags; // Vehicle Type Info
608 case 0x49: return v->build_year;
610 case 0x4A:
611 switch (v->type) {
612 case VEH_TRAIN: {
613 if (Train::From(v)->IsVirtual()) return 0x1FF;
614 RailType rt = GetTileRailType(v->tile);
615 return (HasPowerOnRail(Train::From(v)->railtype, rt) ? 0x100 : 0) | GetReverseRailTypeTranslation(rt, object->ro.grffile);
618 case VEH_ROAD: {
619 RoadTypeIdentifier rtid = GetRoadType(v->tile, RoadVehicle::From(v)->rtid.basetype);
620 return 0x100 | GetReverseRoadTypeTranslation(rtid, object->ro.grffile);
623 default:
624 return 0;
627 case 0x4B: // Long date of last service
628 return v->date_of_last_service;
630 case 0x4C: // Current maximum speed in NewGRF units
631 if (!v->IsPrimaryVehicle()) return 0;
632 return v->GetCurrentMaxSpeed();
634 case 0x4D: // Position within articulated vehicle
635 if (!HasBit(v->grf_cache.cache_valid, NCVV_POSITION_IN_VEHICLE)) {
636 byte artic_before = 0;
637 for (const Vehicle *u = v; u->IsArticulatedPart(); u = u->Previous()) artic_before++;
638 byte artic_after = 0;
639 for (const Vehicle *u = v; u->HasArticulatedPart(); u = u->Next()) artic_after++;
640 v->grf_cache.position_in_vehicle = artic_before | artic_after << 8;
641 SetBit(v->grf_cache.cache_valid, NCVV_POSITION_IN_VEHICLE);
643 return v->grf_cache.position_in_vehicle;
645 /* Variables which use the parameter */
646 case 0x60: // Count consist's engine ID occurrence
647 if (v->type != VEH_TRAIN) return v->GetEngine()->grf_prop.local_id == parameter ? 1 : 0;
650 uint count = 0;
651 for (; v != nullptr; v = v->Next()) {
652 if (v->GetEngine()->grf_prop.local_id == parameter) count++;
654 return count;
657 case 0x61: // Get variable of n-th vehicle in chain [signed number relative to vehicle]
658 if (!v->IsGroundVehicle() || parameter == 0x61) {
659 /* Not available */
660 break;
663 /* Only allow callbacks that don't change properties to avoid circular dependencies. */
664 if (object->ro.callback == CBID_NO_CALLBACK || object->ro.callback == CBID_RANDOM_TRIGGER || object->ro.callback == CBID_TRAIN_ALLOW_WAGON_ATTACH ||
665 object->ro.callback == CBID_VEHICLE_START_STOP_CHECK || object->ro.callback == CBID_VEHICLE_32DAY_CALLBACK || object->ro.callback == CBID_VEHICLE_COLOUR_MAPPING ||
666 object->ro.callback == CBID_VEHICLE_SPAWN_VISUAL_EFFECT) {
667 Vehicle *u = v->Move((int32)GetRegister(0x10F));
668 if (u == nullptr) return 0; // available, but zero
670 if (parameter == 0x5F) {
671 /* This seems to be the only variable that makes sense to access via var 61, but is not handled by VehicleGetVariable */
672 return (u->random_bits << 8) | u->waiting_triggers;
673 } else {
674 return VehicleGetVariable(u, object, parameter, GetRegister(0x10E), available);
677 /* Not available */
678 break;
680 case 0x62: { // Curvature/position difference for n-th vehicle in chain [signed number relative to vehicle]
681 /* Format: zzyyxxFD
682 * zz - Signed difference of z position between the selected and this vehicle.
683 * yy - Signed difference of y position between the selected and this vehicle.
684 * xx - Signed difference of x position between the selected and this vehicle.
685 * F - Flags, bit 7 corresponds to VS_HIDDEN.
686 * D - Dir difference, like in 0x45.
688 if (!v->IsGroundVehicle()) return 0;
690 const Vehicle *u = v->Move((int8)parameter);
691 if (u == nullptr) return 0;
693 /* Get direction difference. */
694 bool prev = (int8)parameter < 0;
695 uint32 ret = prev ? DirDifference(u->direction, v->direction) : DirDifference(v->direction, u->direction);
696 if (ret > DIRDIFF_REVERSE) ret |= 0x08;
698 if (u->vehstatus & VS_HIDDEN) ret |= 0x80;
700 /* Get position difference. */
701 ret |= ((prev ? u->x_pos - v->x_pos : v->x_pos - u->x_pos) & 0xFF) << 8;
702 ret |= ((prev ? u->y_pos - v->y_pos : v->y_pos - u->y_pos) & 0xFF) << 16;
703 ret |= ((prev ? u->z_pos - v->z_pos : v->z_pos - u->z_pos) & 0xFF) << 24;
705 return ret;
708 case 0xFE:
709 case 0xFF: {
710 uint16 modflags = 0;
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 bool powered = t->IsEngine() || is_powered_wagon;
717 bool has_power;
718 if (u->IsVirtual()) {
719 has_power = true;
720 } else {
721 RailType railtype = GetRailType(v->tile);
722 has_power = HasPowerOnRail(u->railtype, railtype);
725 if (powered && has_power) SetBit(modflags, 5);
726 if (powered && !has_power) SetBit(modflags, 6);
727 if (HasBit(t->flags, VRF_TOGGLE_REVERSE)) SetBit(modflags, 8);
729 if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING)) SetBit(modflags, 1);
730 if (HasBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE)) SetBit(modflags, 10);
732 return variable == 0xFE ? modflags : GB(modflags, 8, 8);
736 /* General vehicle properties */
737 switch (variable - 0x80) {
738 case 0x00: return v->type + 0x10;
739 case 0x01: return MapOldSubType(v);
740 case 0x04: return v->index;
741 case 0x05: return GB(v->index, 8, 8);
742 case 0x0A: return v->current_order.MapOldOrder();
743 case 0x0B: return v->current_order.GetDestination();
744 case 0x0C: return v->GetNumOrders();
745 case 0x0D: return v->cur_real_order_index;
746 case 0x10:
747 case 0x11: {
748 uint ticks;
749 if (v->current_order.IsType(OT_LOADING)) {
750 ticks = v->load_unload_ticks;
751 } else {
752 switch (v->type) {
753 case VEH_TRAIN: ticks = Train::From(v)->wait_counter; break;
754 case VEH_AIRCRAFT: ticks = Aircraft::From(v)->turn_counter; break;
755 default: ticks = 0; break;
758 return (variable - 0x80) == 0x10 ? ticks : GB(ticks, 8, 8);
760 case 0x12: return Clamp(v->date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF);
761 case 0x13: return GB(Clamp(v->date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF), 8, 8);
762 case 0x14: return v->GetServiceInterval();
763 case 0x15: return GB(v->GetServiceInterval(), 8, 8);
764 case 0x16: return v->last_station_visited;
765 case 0x17: return v->tick_counter;
766 case 0x18:
767 case 0x19: {
768 uint max_speed;
769 switch (v->type) {
770 case VEH_AIRCRAFT:
771 max_speed = Aircraft::From(v)->GetSpeedOldUnits(); // Convert to old units.
772 break;
774 default:
775 max_speed = v->vcache.cached_max_speed;
776 break;
778 return (variable - 0x80) == 0x18 ? max_speed : GB(max_speed, 8, 8);
780 case 0x1A: return v->x_pos;
781 case 0x1B: return GB(v->x_pos, 8, 8);
782 case 0x1C: return v->y_pos;
783 case 0x1D: return GB(v->y_pos, 8, 8);
784 case 0x1E: return v->z_pos;
785 case 0x1F: return object->info_view ? DIR_W : v->direction;
786 case 0x28: return 0; // cur_image is a potential desyncer due to Action1 in static NewGRFs.
787 case 0x29: return 0; // cur_image is a potential desyncer due to Action1 in static NewGRFs.
788 case 0x32: return v->vehstatus;
789 case 0x33: return 0; // non-existent high byte of vehstatus
790 case 0x34: return v->type == VEH_AIRCRAFT ? (v->cur_speed * 10) / 128 : v->cur_speed;
791 case 0x35: return GB(v->type == VEH_AIRCRAFT ? (v->cur_speed * 10) / 128 : v->cur_speed, 8, 8);
792 case 0x36: return v->subspeed;
793 case 0x37: return v->acceleration;
794 case 0x39: return v->cargo_type;
795 case 0x3A: return v->cargo_cap;
796 case 0x3B: return GB(v->cargo_cap, 8, 8);
797 case 0x3C: return ClampToU16(v->cargo.StoredCount());
798 case 0x3D: return GB(ClampToU16(v->cargo.StoredCount()), 8, 8);
799 case 0x3E: return v->cargo.Source();
800 case 0x3F: return ClampU(v->cargo.DaysInTransit(), 0, 0xFF);
801 case 0x40: return ClampToU16(v->age);
802 case 0x41: return GB(ClampToU16(v->age), 8, 8);
803 case 0x42: return ClampToU16(v->max_age);
804 case 0x43: return GB(ClampToU16(v->max_age), 8, 8);
805 case 0x44: return Clamp(v->build_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
806 case 0x45: return v->unitnumber;
807 case 0x46: return v->GetEngine()->grf_prop.local_id;
808 case 0x47: return GB(v->GetEngine()->grf_prop.local_id, 8, 8);
809 case 0x48:
810 if (v->type != VEH_TRAIN || v->spritenum != 0xFD) return v->spritenum;
811 return HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION) ? 0xFE : 0xFD;
813 case 0x49: return v->day_counter;
814 case 0x4A: return v->breakdowns_since_last_service;
815 case 0x4B: return v->breakdown_ctr;
816 case 0x4C: return v->breakdown_delay;
817 case 0x4D: return v->breakdown_chance;
818 case 0x4E: return v->reliability;
819 case 0x4F: return GB(v->reliability, 8, 8);
820 case 0x50: return v->reliability_spd_dec;
821 case 0x51: return GB(v->reliability_spd_dec, 8, 8);
822 case 0x52: return ClampToI32(v->GetDisplayProfitThisYear());
823 case 0x53: return GB(ClampToI32(v->GetDisplayProfitThisYear()), 8, 24);
824 case 0x54: return GB(ClampToI32(v->GetDisplayProfitThisYear()), 16, 16);
825 case 0x55: return GB(ClampToI32(v->GetDisplayProfitThisYear()), 24, 8);
826 case 0x56: return ClampToI32(v->GetDisplayProfitLastYear());
827 case 0x57: return GB(ClampToI32(v->GetDisplayProfitLastYear()), 8, 24);
828 case 0x58: return GB(ClampToI32(v->GetDisplayProfitLastYear()), 16, 16);
829 case 0x59: return GB(ClampToI32(v->GetDisplayProfitLastYear()), 24, 8);
830 case 0x5A: return v->Next() == nullptr ? INVALID_VEHICLE : v->Next()->index;
831 case 0x5C: return ClampToI32(v->value);
832 case 0x5D: return GB(ClampToI32(v->value), 8, 24);
833 case 0x5E: return GB(ClampToI32(v->value), 16, 16);
834 case 0x5F: return GB(ClampToI32(v->value), 24, 8);
835 case 0x72: return v->cargo_subtype;
836 case 0x7A: return v->random_bits;
837 case 0x7B: return v->waiting_triggers;
840 /* Vehicle specific properties */
841 switch (v->type) {
842 case VEH_TRAIN: {
843 Train *t = Train::From(v);
844 switch (variable - 0x80) {
845 case 0x62: return t->track;
846 case 0x66: return t->railtype;
847 case 0x73: return 0x80 + VEHICLE_LENGTH - t->gcache.cached_veh_length;
848 case 0x74: return t->gcache.cached_power;
849 case 0x75: return GB(t->gcache.cached_power, 8, 24);
850 case 0x76: return GB(t->gcache.cached_power, 16, 16);
851 case 0x77: return GB(t->gcache.cached_power, 24, 8);
852 case 0x7C: return t->First()->index;
853 case 0x7D: return GB(t->First()->index, 8, 8);
854 case 0x7F: return 0; // Used for vehicle reversing hack in TTDP
856 break;
859 case VEH_ROAD: {
860 RoadVehicle *rv = RoadVehicle::From(v);
861 switch (variable - 0x80) {
862 case 0x62: return rv->state;
863 case 0x64: return rv->blocked_ctr;
864 case 0x65: return GB(rv->blocked_ctr, 8, 8);
865 case 0x66: return rv->overtaking;
866 case 0x67: return rv->overtaking_ctr;
867 case 0x68: return rv->crashed_ctr;
868 case 0x69: return GB(rv->crashed_ctr, 8, 8);
870 break;
873 case VEH_SHIP: {
874 Ship *s = Ship::From(v);
875 switch (variable - 0x80) {
876 case 0x62: return s->state;
878 break;
881 case VEH_AIRCRAFT: {
882 Aircraft *a = Aircraft::From(v);
883 switch (variable - 0x80) {
884 case 0x62: return MapAircraftMovementState(a); // Current movement state
885 case 0x63: return a->targetairport; // Airport to which the action refers
886 case 0x66: return MapAircraftMovementAction(a); // Current movement action
888 break;
891 default: break;
894 DEBUG(grf, 1, "Unhandled vehicle variable 0x%X, type 0x%X", variable, (uint)v->type);
896 *available = false;
897 return UINT_MAX;
900 /* virtual */ uint32 VehicleScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
902 if (this->v == nullptr) {
903 /* Vehicle does not exist, so we're in a purchase list */
904 switch (variable) {
905 case 0x43: return GetCompanyInfo(_current_company, LiveryHelper(this->self_type, nullptr)); // Owner information
906 case 0x46: return 0; // Motion counter
907 case 0x47: { // Vehicle cargo info
908 const Engine *e = Engine::Get(this->self_type);
909 CargoID cargo_type = e->GetDefaultCargoType();
910 if (cargo_type != CT_INVALID) {
911 const CargoSpec *cs = CargoSpec::Get(cargo_type);
912 return (cs->classes << 16) | (cs->weight << 8) | this->ro.grffile->cargo_map[cargo_type];
913 } else {
914 return 0x000000FF;
917 case 0x48: return Engine::Get(this->self_type)->flags; // Vehicle Type Info
918 case 0x49: return _cur_year; // 'Long' format build year
919 case 0x4B: return _date; // Long date of last service
920 case 0x92: return Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF); // Date of last service
921 case 0x93: return GB(Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF), 8, 8);
922 case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
923 case 0xDA: return INVALID_VEHICLE; // Next vehicle
924 case 0xF2: return 0; // Cargo subtype
927 *available = false;
928 return UINT_MAX;
931 return VehicleGetVariable(const_cast<Vehicle*>(this->v), this, variable, parameter, available);
935 /* virtual */ const SpriteGroup *VehicleResolverObject::ResolveReal(const RealSpriteGroup *group) const
937 const Vehicle *v = this->self_scope.v;
939 if (v == nullptr) {
940 if (group->num_loading > 0) return group->loading[0];
941 if (group->num_loaded > 0) return group->loaded[0];
942 return nullptr;
945 bool in_motion = !v->First()->current_order.IsType(OT_LOADING);
947 uint totalsets = in_motion ? group->num_loaded : group->num_loading;
949 if (totalsets == 0) return nullptr;
951 uint set = (v->cargo.StoredCount() * totalsets) / max((uint16)1, v->cargo_cap);
952 set = min(set, totalsets - 1);
954 return in_motion ? group->loaded[set] : group->loading[set];
958 * Get the grf file associated with an engine type.
959 * @param engine_type Engine to query.
960 * @return grf file associated with the engine.
962 static const GRFFile *GetEngineGrfFile(EngineID engine_type)
964 const Engine *e = Engine::Get(engine_type);
965 return (e != nullptr) ? e->GetGRF() : nullptr;
969 * Resolver of a vehicle (chain).
970 * @param engine_type Engine type
971 * @param v %Vehicle being resolved.
972 * @param wagon_override Application of wagon overrides.
973 * @param info_view Indicates if the item is being drawn in an info window.
974 * @param callback Callback ID.
975 * @param callback_param1 First parameter (var 10) of the callback.
976 * @param callback_param2 Second parameter (var 18) of the callback.
978 VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, WagonOverride wagon_override, bool info_view,
979 CallbackID callback, uint32 callback_param1, uint32 callback_param2)
980 : ResolverObject(GetEngineGrfFile(engine_type), callback, callback_param1, callback_param2),
981 self_scope(*this, engine_type, v, info_view),
982 parent_scope(*this, engine_type, ((v != nullptr) ? v->First() : v), info_view),
983 relative_scope(*this, engine_type, v, info_view),
984 cached_relative_count(0)
986 if (wagon_override == WO_SELF) {
987 this->root_spritegroup = GetWagonOverrideSpriteSet(engine_type, CT_DEFAULT, engine_type);
988 } else {
989 if (wagon_override != WO_NONE && v != nullptr && v->IsGroundVehicle()) {
990 assert(v->engine_type == engine_type); // overrides make little sense with fake scopes
992 /* For trains we always use cached value, except for callbacks because the override spriteset
993 * to use may be different than the one cached. It happens for callback 0x15 (refit engine),
994 * as v->cargo_type is temporary changed to the new type */
995 if (wagon_override == WO_CACHED && v->type == VEH_TRAIN) {
996 this->root_spritegroup = Train::From(v)->tcache.cached_override;
997 } else {
998 this->root_spritegroup = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->GetGroundVehicleCache()->first_engine);
1002 if (this->root_spritegroup == nullptr) {
1003 const Engine *e = Engine::Get(engine_type);
1004 CargoID cargo = v != nullptr ? v->cargo_type : CT_PURCHASE;
1005 assert(cargo < lengthof(e->grf_prop.spritegroup));
1006 this->root_spritegroup = e->grf_prop.spritegroup[cargo] != nullptr ? e->grf_prop.spritegroup[cargo] : e->grf_prop.spritegroup[CT_DEFAULT];
1013 void GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type, VehicleSpriteSeq *result)
1015 VehicleResolverObject object(engine, v, VehicleResolverObject::WO_CACHED, false, CBID_NO_CALLBACK);
1016 result->Clear();
1018 bool sprite_stack = HasBit(EngInfo(engine)->misc_flags, EF_SPRITE_STACK);
1019 uint max_stack = sprite_stack ? lengthof(result->seq) : 1;
1020 for (uint stack = 0; stack < max_stack; ++stack) {
1021 object.ResetState();
1022 object.callback_param1 = image_type | (stack << 8);
1023 const SpriteGroup *group = object.Resolve();
1024 uint32 reg100 = sprite_stack ? GetRegister(0x100) : 0;
1025 if (group != nullptr && group->GetNumResults() != 0) {
1026 result->seq[result->count].sprite = group->GetResult() + (direction % group->GetNumResults());
1027 result->seq[result->count].pal = GB(reg100, 0, 16); // zero means default recolouring
1028 result->count++;
1030 if (!HasBit(reg100, 31)) break;
1035 void GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, bool info_view, EngineImageType image_type, VehicleSpriteSeq *result)
1037 const Engine *e = Engine::Get(engine);
1039 /* Only valid for helicopters */
1040 assert(e->type == VEH_AIRCRAFT);
1041 assert(!(e->u.air.subtype & AIR_CTOL));
1043 VehicleResolverObject object(engine, v, VehicleResolverObject::WO_SELF, info_view, CBID_NO_CALLBACK);
1044 result->Clear();
1045 uint rotor_pos = v == nullptr || info_view ? 0 : v->Next()->Next()->state;
1047 bool sprite_stack = HasBit(e->info.misc_flags, EF_SPRITE_STACK);
1048 uint max_stack = sprite_stack ? lengthof(result->seq) : 1;
1049 for (uint stack = 0; stack < max_stack; ++stack) {
1050 object.ResetState();
1051 object.callback_param1 = image_type | (stack << 8);
1052 const SpriteGroup *group = object.Resolve();
1053 uint32 reg100 = sprite_stack ? GetRegister(0x100) : 0;
1054 if (group != nullptr && group->GetNumResults() != 0) {
1055 result->seq[result->count].sprite = group->GetResult() + (rotor_pos % group->GetNumResults());
1056 result->seq[result->count].pal = GB(reg100, 0, 16); // zero means default recolouring
1057 result->count++;
1059 if (!HasBit(reg100, 31)) break;
1064 * Check if a wagon is currently using a wagon override
1065 * @param v The wagon to check
1066 * @return true if it is using an override, false otherwise
1068 bool UsesWagonOverride(const Vehicle *v)
1070 assert(v->type == VEH_TRAIN);
1071 return Train::From(v)->tcache.cached_override != nullptr;
1075 * Evaluate a newgrf callback for vehicles
1076 * @param callback The callback to evaluate
1077 * @param param1 First parameter of the callback
1078 * @param param2 Second parameter of the callback
1079 * @param engine Engine type of the vehicle to evaluate the callback for
1080 * @param v The vehicle to evaluate the callback for, or nullptr if it doesnt exist yet
1081 * @return The value the callback returned, or CALLBACK_FAILED if it failed
1083 uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
1085 VehicleResolverObject object(engine, v, VehicleResolverObject::WO_UNCACHED, false, callback, param1, param2);
1086 return object.ResolveCallback();
1090 * Evaluate a newgrf callback for vehicles with a different vehicle for parent scope.
1091 * @param callback The callback to evaluate
1092 * @param param1 First parameter of the callback
1093 * @param param2 Second parameter of the callback
1094 * @param engine Engine type of the vehicle to evaluate the callback for
1095 * @param v The vehicle to evaluate the callback for, or nullptr if it doesn't exist yet
1096 * @param parent The vehicle to use for parent scope
1097 * @return The value the callback returned, or CALLBACK_FAILED if it failed
1099 uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent)
1101 VehicleResolverObject object(engine, v, VehicleResolverObject::WO_NONE, false, callback, param1, param2);
1102 object.parent_scope.SetVehicle(parent);
1103 return object.ResolveCallback();
1107 /* Callback 36 handlers */
1108 uint GetVehicleProperty(const Vehicle *v, PropertyID property, uint orig_value)
1110 return GetEngineProperty(v->engine_type, property, orig_value, v);
1114 uint GetEngineProperty(EngineID engine, PropertyID property, uint orig_value, const Vehicle *v)
1116 uint16 callback = GetVehicleCallback(CBID_VEHICLE_MODIFY_PROPERTY, property, 0, engine, v);
1117 if (callback != CALLBACK_FAILED) return callback;
1119 return orig_value;
1123 static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_random_bits, bool first)
1125 /* We can't trigger a non-existent vehicle... */
1126 assert(v != nullptr);
1128 VehicleResolverObject object(v->engine_type, v, VehicleResolverObject::WO_CACHED, false, CBID_RANDOM_TRIGGER);
1129 object.waiting_triggers = v->waiting_triggers | trigger;
1130 v->waiting_triggers = object.waiting_triggers; // store now for var 5F
1132 const SpriteGroup *group = object.Resolve();
1133 if (group == nullptr) return;
1135 /* Store remaining triggers. */
1136 v->waiting_triggers = object.GetRemainingTriggers();
1138 /* Rerandomise bits. Scopes other than SELF are invalid for rerandomisation. For bug-to-bug-compatibility with TTDP we ignore the scope. */
1139 byte new_random_bits = Random();
1140 uint32 reseed = object.GetReseedSum();
1141 v->random_bits &= ~reseed;
1142 v->random_bits |= (first ? new_random_bits : base_random_bits) & reseed;
1144 switch (trigger) {
1145 case VEHICLE_TRIGGER_NEW_CARGO:
1146 /* All vehicles in chain get ANY_NEW_CARGO trigger now.
1147 * So we call it for the first one and they will recurse.
1148 * Indexing part of vehicle random bits needs to be
1149 * same for all triggered vehicles in the chain (to get
1150 * all the random-cargo wagons carry the same cargo,
1151 * i.e.), so we give them all the NEW_CARGO triggered
1152 * vehicle's portion of random bits. */
1153 assert(first);
1154 DoTriggerVehicle(v->First(), VEHICLE_TRIGGER_ANY_NEW_CARGO, new_random_bits, false);
1155 break;
1157 case VEHICLE_TRIGGER_DEPOT:
1158 /* We now trigger the next vehicle in chain recursively.
1159 * The random bits portions may be different for each
1160 * vehicle in chain. */
1161 if (v->Next() != nullptr) DoTriggerVehicle(v->Next(), trigger, 0, true);
1162 break;
1164 case VEHICLE_TRIGGER_EMPTY:
1165 /* We now trigger the next vehicle in chain
1166 * recursively. The random bits portions must be same
1167 * for each vehicle in chain, so we give them all
1168 * first chained vehicle's portion of random bits. */
1169 if (v->Next() != nullptr) DoTriggerVehicle(v->Next(), trigger, first ? new_random_bits : base_random_bits, false);
1170 break;
1172 case VEHICLE_TRIGGER_ANY_NEW_CARGO:
1173 /* Now pass the trigger recursively to the next vehicle
1174 * in chain. */
1175 assert(!first);
1176 if (v->Next() != nullptr) DoTriggerVehicle(v->Next(), VEHICLE_TRIGGER_ANY_NEW_CARGO, base_random_bits, false);
1177 break;
1179 case VEHICLE_TRIGGER_CALLBACK_32:
1180 /* Do not do any recursion */
1181 break;
1185 void TriggerVehicle(Vehicle *v, VehicleTrigger trigger)
1187 if (trigger == VEHICLE_TRIGGER_DEPOT) {
1188 /* store that the vehicle entered a depot this tick */
1189 VehicleEnteredDepotThisTick(v);
1192 v->InvalidateNewGRFCacheOfChain();
1193 DoTriggerVehicle(v, trigger, 0, true);
1194 v->InvalidateNewGRFCacheOfChain();
1197 /* Functions for changing the order of vehicle purchase lists */
1199 struct ListOrderChange {
1200 EngineID engine;
1201 uint target; ///< local ID
1204 static SmallVector<ListOrderChange, 16> _list_order_changes;
1207 * Record a vehicle ListOrderChange.
1208 * @param engine Engine to move
1209 * @param target Local engine ID to move \a engine in front of
1210 * @note All sorting is done later in CommitVehicleListOrderChanges
1212 void AlterVehicleListOrder(EngineID engine, uint target)
1214 /* Add the list order change to a queue */
1215 ListOrderChange *loc = _list_order_changes.Append();
1216 loc->engine = engine;
1217 loc->target = target;
1221 * Comparator function to sort engines via scope-GRFID and local ID.
1222 * @param a left side
1223 * @param b right side
1224 * @return comparison result
1226 static int CDECL EnginePreSort(const EngineID *a, const EngineID *b)
1228 const EngineIDMapping *id_a = _engine_mngr.Get(*a);
1229 const EngineIDMapping *id_b = _engine_mngr.Get(*b);
1231 /* 1. Sort by engine type */
1232 if (id_a->type != id_b->type) return (int)id_a->type - (int)id_b->type;
1234 /* 2. Sort by scope-GRFID */
1235 if (id_a->grfid != id_b->grfid) return id_a->grfid < id_b->grfid ? -1 : 1;
1237 /* 3. Sort by local ID */
1238 return (int)id_a->internal_id - (int)id_b->internal_id;
1242 * Deternine default engine sorting and execute recorded ListOrderChanges from AlterVehicleListOrder.
1244 void CommitVehicleListOrderChanges()
1246 /* Pre-sort engines by scope-grfid and local index */
1247 SmallVector<EngineID, 16> ordering;
1248 Engine *e;
1249 FOR_ALL_ENGINES(e) {
1250 *ordering.Append() = e->index;
1252 QSortT(ordering.Begin(), ordering.Length(), EnginePreSort);
1254 /* Apply Insertion-Sort operations */
1255 const ListOrderChange *end = _list_order_changes.End();
1256 for (const ListOrderChange *it = _list_order_changes.Begin(); it != end; ++it) {
1257 EngineID source = it->engine;
1258 uint local_target = it->target;
1260 const EngineIDMapping *id_source = _engine_mngr.Get(source);
1261 if (id_source->internal_id == local_target) continue;
1263 EngineID target = _engine_mngr.GetID(id_source->type, local_target, id_source->grfid);
1264 if (target == INVALID_ENGINE) continue;
1266 int source_index = ordering.FindIndex(source);
1267 int target_index = ordering.FindIndex(target);
1269 assert(source_index >= 0 && target_index >= 0);
1270 assert(source_index != target_index);
1272 EngineID *list = ordering.Begin();
1273 if (source_index < target_index) {
1274 --target_index;
1275 for (int i = source_index; i < target_index; ++i) list[i] = list[i + 1];
1276 list[target_index] = source;
1277 } else {
1278 for (int i = source_index; i > target_index; --i) list[i] = list[i - 1];
1279 list[target_index] = source;
1283 /* Store final sort-order */
1284 const EngineID *idend = ordering.End();
1285 uint index = 0;
1286 for (const EngineID *it = ordering.Begin(); it != idend; ++it, ++index) {
1287 Engine::Get(*it)->list_position = index;
1290 /* Clear out the queue */
1291 _list_order_changes.Reset();
1295 * Fill the grf_cache of the given vehicle.
1296 * @param v The vehicle to fill the cache for.
1298 void FillNewGRFVehicleCache(const Vehicle *v)
1300 VehicleResolverObject ro(v->engine_type, v, VehicleResolverObject::WO_NONE);
1302 /* These variables we have to check; these are the ones with a cache. */
1303 static const int cache_entries[][2] = {
1304 { 0x40, NCVV_POSITION_CONSIST_LENGTH },
1305 { 0x41, NCVV_POSITION_SAME_ID_LENGTH },
1306 { 0x42, NCVV_CONSIST_CARGO_INFORMATION },
1307 { 0x43, NCVV_COMPANY_INFORMATION },
1308 { 0x4D, NCVV_POSITION_IN_VEHICLE },
1310 assert_compile(NCVV_END == lengthof(cache_entries));
1312 /* Resolve all the variables, so their caches are set. */
1313 for (size_t i = 0; i < lengthof(cache_entries); i++) {
1314 /* Only resolve when the cache isn't valid. */
1315 if (HasBit(v->grf_cache.cache_valid, cache_entries[i][1])) continue;
1316 bool stub;
1317 ro.GetScope(VSG_SCOPE_SELF)->GetVariable(cache_entries[i][0], 0, &stub);
1320 /* Make sure really all bits are set. */
1321 assert(v->grf_cache.cache_valid == (1 << NCVV_END) - 1);