OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

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