255 } |
254 } |
256 |
255 |
257 AdjustAvailAircraft(); |
256 AdjustAvailAircraft(); |
258 } |
257 } |
259 |
258 |
260 // TODO: We don't support cargo-specific wagon overrides. Pretty exotic... ;-) --pasky |
|
261 |
|
262 typedef struct WagonOverride { |
|
263 byte *train_id; |
|
264 int trains; |
|
265 SpriteGroup *group; |
|
266 } WagonOverride; |
|
267 |
|
268 typedef struct WagonOverrides { |
|
269 int overrides_count; |
|
270 WagonOverride *overrides; |
|
271 } WagonOverrides; |
|
272 |
|
273 static WagonOverrides _engine_wagon_overrides[TOTAL_NUM_ENGINES]; |
|
274 |
|
275 void SetWagonOverrideSprites(EngineID engine, SpriteGroup *group, byte *train_id, |
|
276 int trains) |
|
277 { |
|
278 WagonOverrides *wos; |
|
279 WagonOverride *wo; |
|
280 |
|
281 wos = &_engine_wagon_overrides[engine]; |
|
282 wos->overrides_count++; |
|
283 wos->overrides = realloc(wos->overrides, |
|
284 wos->overrides_count * sizeof(*wos->overrides)); |
|
285 |
|
286 wo = &wos->overrides[wos->overrides_count - 1]; |
|
287 /* FIXME: If we are replacing an override, release original SpriteGroup |
|
288 * to prevent leaks. But first we need to refcount the SpriteGroup. |
|
289 * --pasky */ |
|
290 wo->group = group; |
|
291 group->ref_count++; |
|
292 wo->trains = trains; |
|
293 wo->train_id = malloc(trains); |
|
294 memcpy(wo->train_id, train_id, trains); |
|
295 } |
|
296 |
|
297 static const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, byte overriding_engine) |
|
298 { |
|
299 const WagonOverrides *wos = &_engine_wagon_overrides[engine]; |
|
300 int i; |
|
301 |
|
302 // XXX: This could turn out to be a timesink on profiles. We could |
|
303 // always just dedicate 65535 bytes for an [engine][train] trampoline |
|
304 // for O(1). Or O(logMlogN) and searching binary tree or smt. like |
|
305 // that. --pasky |
|
306 |
|
307 for (i = 0; i < wos->overrides_count; i++) { |
|
308 const WagonOverride *wo = &wos->overrides[i]; |
|
309 int j; |
|
310 |
|
311 for (j = 0; j < wo->trains; j++) { |
|
312 if (wo->train_id[j] == overriding_engine) |
|
313 return wo->group; |
|
314 } |
|
315 } |
|
316 return NULL; |
|
317 } |
|
318 |
|
319 /** |
|
320 * Unload all wagon override sprite groups. |
|
321 */ |
|
322 void UnloadWagonOverrides(void) |
|
323 { |
|
324 WagonOverrides *wos; |
|
325 WagonOverride *wo; |
|
326 EngineID engine; |
|
327 int i; |
|
328 |
|
329 for (engine = 0; engine < TOTAL_NUM_ENGINES; engine++) { |
|
330 wos = &_engine_wagon_overrides[engine]; |
|
331 for (i = 0; i < wos->overrides_count; i++) { |
|
332 wo = &wos->overrides[i]; |
|
333 UnloadSpriteGroup(&wo->group); |
|
334 free(wo->train_id); |
|
335 } |
|
336 free(wos->overrides); |
|
337 wos->overrides_count = 0; |
|
338 wos->overrides = NULL; |
|
339 } |
|
340 } |
|
341 |
|
342 // 0 - 28 are cargos, 29 is default, 30 is the advert (purchase list) |
|
343 // (It isn't and shouldn't be like this in the GRF files since new cargo types |
|
344 // may appear in future - however it's more convenient to store it like this in |
|
345 // memory. --pasky) |
|
346 static SpriteGroup *engine_custom_sprites[TOTAL_NUM_ENGINES][NUM_GLOBAL_CID]; |
|
347 |
|
348 void SetCustomEngineSprites(EngineID engine, byte cargo, SpriteGroup *group) |
|
349 { |
|
350 if (engine_custom_sprites[engine][cargo] != NULL) { |
|
351 DEBUG(grf, 6)("SetCustomEngineSprites: engine `%d' cargo `%d' already has group -- removing.", engine, cargo); |
|
352 UnloadSpriteGroup(&engine_custom_sprites[engine][cargo]); |
|
353 } |
|
354 engine_custom_sprites[engine][cargo] = group; |
|
355 group->ref_count++; |
|
356 } |
|
357 |
|
358 /** |
|
359 * Unload all engine sprite groups. |
|
360 */ |
|
361 void UnloadCustomEngineSprites(void) |
|
362 { |
|
363 EngineID engine; |
|
364 CargoID cargo; |
|
365 |
|
366 for (engine = 0; engine < TOTAL_NUM_ENGINES; engine++) { |
|
367 for (cargo = 0; cargo < NUM_GLOBAL_CID; cargo++) { |
|
368 if (engine_custom_sprites[engine][cargo] != NULL) { |
|
369 DEBUG(grf, 6)("UnloadCustomEngineSprites: Unloading group for engine `%d' cargo `%d'.", engine, cargo); |
|
370 UnloadSpriteGroup(&engine_custom_sprites[engine][cargo]); |
|
371 } |
|
372 } |
|
373 } |
|
374 } |
|
375 |
|
376 static int MapOldSubType(const Vehicle *v) |
|
377 { |
|
378 if (v->type != VEH_Train) return v->subtype; |
|
379 if (IsTrainEngine(v)) return 0; |
|
380 if (IsFreeWagon(v)) return 4; |
|
381 return 2; |
|
382 } |
|
383 |
|
384 typedef SpriteGroup *(*resolve_callback)(const SpriteGroup *spritegroup, |
|
385 const Vehicle *veh, uint16 callback_info, void *resolve_func); /* XXX data pointer used as function pointer */ |
|
386 |
|
387 static const SpriteGroup* ResolveVehicleSpriteGroup(const SpriteGroup *spritegroup, |
|
388 const Vehicle *veh, uint16 callback_info, resolve_callback resolve_func) |
|
389 { |
|
390 if (spritegroup == NULL) |
|
391 return NULL; |
|
392 |
|
393 //debug("spgt %d", spritegroup->type); |
|
394 switch (spritegroup->type) { |
|
395 case SGT_REAL: |
|
396 case SGT_CALLBACK: |
|
397 return spritegroup; |
|
398 |
|
399 case SGT_DETERMINISTIC: { |
|
400 const DeterministicSpriteGroup *dsg = &spritegroup->g.determ; |
|
401 const SpriteGroup *target; |
|
402 int value = -1; |
|
403 |
|
404 //debug("[%p] Having fun resolving variable %x", veh, dsg->variable); |
|
405 if (dsg->variable == 0x0C) { |
|
406 /* Callback ID */ |
|
407 value = callback_info & 0xFF; |
|
408 } else if (dsg->variable == 0x10) { |
|
409 value = (callback_info >> 8) & 0xFF; |
|
410 } else if ((dsg->variable >> 6) == 0) { |
|
411 /* General property */ |
|
412 value = GetDeterministicSpriteValue(dsg->variable); |
|
413 } else { |
|
414 /* Vehicle-specific property. */ |
|
415 |
|
416 if (veh == NULL) { |
|
417 /* We are in a purchase list of something, |
|
418 * and we are checking for something undefined. |
|
419 * That means we should get the first target |
|
420 * (NOT the default one). */ |
|
421 if (dsg->num_ranges > 0) { |
|
422 target = dsg->ranges[0].group; |
|
423 } else { |
|
424 target = dsg->default_group; |
|
425 } |
|
426 return resolve_func(target, NULL, callback_info, resolve_func); |
|
427 } |
|
428 |
|
429 if (dsg->var_scope == VSG_SCOPE_PARENT) { |
|
430 /* First engine in the vehicle chain */ |
|
431 if (veh->type == VEH_Train) |
|
432 veh = GetFirstVehicleInChain(veh); |
|
433 } |
|
434 |
|
435 if (dsg->variable == 0x40 || dsg->variable == 0x41) { |
|
436 if (veh->type == VEH_Train) { |
|
437 const Vehicle *u = GetFirstVehicleInChain(veh); |
|
438 byte chain_before = 0, chain_after = 0; |
|
439 |
|
440 while (u != veh) { |
|
441 chain_before++; |
|
442 if (dsg->variable == 0x41 && u->engine_type != veh->engine_type) |
|
443 chain_before = 0; |
|
444 u = u->next; |
|
445 } |
|
446 while (u->next != NULL && (dsg->variable == 0x40 || u->next->engine_type == veh->engine_type)) { |
|
447 chain_after++; |
|
448 u = u->next; |
|
449 }; |
|
450 |
|
451 value = chain_before | chain_after << 8 |
|
452 | (chain_before + chain_after) << 16; |
|
453 } else { |
|
454 value = 1; /* 1 vehicle in the chain */ |
|
455 } |
|
456 |
|
457 } else { |
|
458 // TTDPatch runs on little-endian arch; |
|
459 // Variable is 0x80 + offset in TTD's vehicle structure |
|
460 switch (dsg->variable - 0x80) { |
|
461 #define veh_prop(id_, value_) case (id_): value = (value_); break |
|
462 veh_prop(0x00, veh->type); |
|
463 veh_prop(0x01, MapOldSubType(veh)); |
|
464 veh_prop(0x04, veh->index); |
|
465 veh_prop(0x05, veh->index & 0xFF); |
|
466 /* XXX? Is THIS right? */ |
|
467 veh_prop(0x0A, PackOrder(&veh->current_order)); |
|
468 veh_prop(0x0B, PackOrder(&veh->current_order) & 0xff); |
|
469 veh_prop(0x0C, veh->num_orders); |
|
470 veh_prop(0x0D, veh->cur_order_index); |
|
471 veh_prop(0x10, veh->load_unload_time_rem); |
|
472 veh_prop(0x11, veh->load_unload_time_rem & 0xFF); |
|
473 veh_prop(0x12, veh->date_of_last_service); |
|
474 veh_prop(0x13, veh->date_of_last_service & 0xFF); |
|
475 veh_prop(0x14, veh->service_interval); |
|
476 veh_prop(0x15, veh->service_interval & 0xFF); |
|
477 veh_prop(0x16, veh->last_station_visited); |
|
478 veh_prop(0x17, veh->tick_counter); |
|
479 veh_prop(0x18, veh->max_speed); |
|
480 veh_prop(0x19, veh->max_speed & 0xFF); |
|
481 veh_prop(0x1F, veh->direction); |
|
482 veh_prop(0x28, veh->cur_image); |
|
483 veh_prop(0x29, veh->cur_image & 0xFF); |
|
484 veh_prop(0x32, veh->vehstatus); |
|
485 veh_prop(0x33, veh->vehstatus); |
|
486 veh_prop(0x34, veh->cur_speed); |
|
487 veh_prop(0x35, veh->cur_speed & 0xFF); |
|
488 veh_prop(0x36, veh->subspeed); |
|
489 veh_prop(0x37, veh->acceleration); |
|
490 veh_prop(0x39, veh->cargo_type); |
|
491 veh_prop(0x3A, veh->cargo_cap); |
|
492 veh_prop(0x3B, veh->cargo_cap & 0xFF); |
|
493 veh_prop(0x3C, veh->cargo_count); |
|
494 veh_prop(0x3D, veh->cargo_count & 0xFF); |
|
495 veh_prop(0x3E, veh->cargo_source); // Probably useless; so what |
|
496 veh_prop(0x3F, veh->cargo_days); |
|
497 veh_prop(0x40, veh->age); |
|
498 veh_prop(0x41, veh->age & 0xFF); |
|
499 veh_prop(0x42, veh->max_age); |
|
500 veh_prop(0x43, veh->max_age & 0xFF); |
|
501 veh_prop(0x44, veh->build_year); |
|
502 veh_prop(0x45, veh->unitnumber); |
|
503 veh_prop(0x46, veh->engine_type); |
|
504 veh_prop(0x47, veh->engine_type & 0xFF); |
|
505 veh_prop(0x48, veh->spritenum); |
|
506 veh_prop(0x49, veh->day_counter); |
|
507 veh_prop(0x4A, veh->breakdowns_since_last_service); |
|
508 veh_prop(0x4B, veh->breakdown_ctr); |
|
509 veh_prop(0x4C, veh->breakdown_delay); |
|
510 veh_prop(0x4D, veh->breakdown_chance); |
|
511 veh_prop(0x4E, veh->reliability); |
|
512 veh_prop(0x4F, veh->reliability & 0xFF); |
|
513 veh_prop(0x50, veh->reliability_spd_dec); |
|
514 veh_prop(0x51, veh->reliability_spd_dec & 0xFF); |
|
515 veh_prop(0x52, veh->profit_this_year); |
|
516 veh_prop(0x53, veh->profit_this_year & 0xFFFFFF); |
|
517 veh_prop(0x54, veh->profit_this_year & 0xFFFF); |
|
518 veh_prop(0x55, veh->profit_this_year & 0xFF); |
|
519 veh_prop(0x56, veh->profit_last_year); |
|
520 veh_prop(0x57, veh->profit_last_year & 0xFF); |
|
521 veh_prop(0x58, veh->profit_last_year); |
|
522 veh_prop(0x59, veh->profit_last_year & 0xFF); |
|
523 veh_prop(0x5A, veh->next == NULL ? INVALID_VEHICLE : veh->next->index); |
|
524 veh_prop(0x5C, veh->value); |
|
525 veh_prop(0x5D, veh->value & 0xFFFFFF); |
|
526 veh_prop(0x5E, veh->value & 0xFFFF); |
|
527 veh_prop(0x5F, veh->value & 0xFF); |
|
528 veh_prop(0x60, veh->string_id); |
|
529 veh_prop(0x61, veh->string_id & 0xFF); |
|
530 /* 00h..07h=sub image? 40h=in tunnel; actually some kind of status |
|
531 * aircraft: >=13h when in flight |
|
532 * train, ship: 80h=in depot |
|
533 * rv: 0feh=in depot */ |
|
534 /* TODO veh_prop(0x62, veh->???); */ |
|
535 |
|
536 /* TODO: The rest is per-vehicle, I hope no GRF file looks so far. |
|
537 * But they won't let us have an easy ride so surely *some* GRF |
|
538 * file does. So someone needs to do this too. --pasky */ |
|
539 |
|
540 #undef veh_prop |
|
541 } |
|
542 } |
|
543 } |
|
544 |
|
545 target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group; |
|
546 //debug("Resolved variable %x: %d, %p", dsg->variable, value, callback); |
|
547 return resolve_func(target, veh, callback_info, resolve_func); |
|
548 } |
|
549 |
|
550 case SGT_RANDOMIZED: { |
|
551 const RandomizedSpriteGroup *rsg = &spritegroup->g.random; |
|
552 |
|
553 if (veh == NULL) { |
|
554 /* Purchase list of something. Show the first one. */ |
|
555 assert(rsg->num_groups > 0); |
|
556 //debug("going for %p: %d", rsg->groups[0], rsg->groups[0].type); |
|
557 return resolve_func(rsg->groups[0], NULL, callback_info, resolve_func); |
|
558 } |
|
559 |
|
560 if (rsg->var_scope == VSG_SCOPE_PARENT) { |
|
561 /* First engine in the vehicle chain */ |
|
562 if (veh->type == VEH_Train) |
|
563 veh = GetFirstVehicleInChain(veh); |
|
564 } |
|
565 |
|
566 return resolve_func(EvalRandomizedSpriteGroup(rsg, veh->random_bits), veh, callback_info, resolve_func); |
|
567 } |
|
568 |
|
569 default: |
|
570 error("I don't know how to handle such a spritegroup %d!", spritegroup->type); |
|
571 return NULL; |
|
572 } |
|
573 } |
|
574 |
|
575 static const SpriteGroup *GetVehicleSpriteGroup(EngineID engine, const Vehicle *v) |
|
576 { |
|
577 const SpriteGroup *group; |
|
578 byte cargo = GC_PURCHASE; |
|
579 |
|
580 if (v != NULL) { |
|
581 cargo = _global_cargo_id[_opt.landscape][v->cargo_type]; |
|
582 assert(cargo != GC_INVALID); |
|
583 } |
|
584 |
|
585 group = engine_custom_sprites[engine][cargo]; |
|
586 |
|
587 if (v != NULL && v->type == VEH_Train) { |
|
588 const SpriteGroup *overset = GetWagonOverrideSpriteSet(engine, v->u.rail.first_engine); |
|
589 |
|
590 if (overset != NULL) group = overset; |
|
591 } |
|
592 |
|
593 return group; |
|
594 } |
|
595 |
|
596 int GetCustomEngineSprite(EngineID engine, const Vehicle *v, byte direction) |
|
597 { |
|
598 const SpriteGroup *group; |
|
599 const RealSpriteGroup *rsg; |
|
600 byte cargo = GC_PURCHASE; |
|
601 byte loaded = 0; |
|
602 bool in_motion = 0; |
|
603 int totalsets, spriteset; |
|
604 int r; |
|
605 |
|
606 if (v != NULL) { |
|
607 int capacity = v->cargo_cap; |
|
608 |
|
609 cargo = _global_cargo_id[_opt.landscape][v->cargo_type]; |
|
610 assert(cargo != GC_INVALID); |
|
611 |
|
612 if (capacity == 0) capacity = 1; |
|
613 loaded = (v->cargo_count * 100) / capacity; |
|
614 |
|
615 if (v->type == VEH_Train) { |
|
616 in_motion = GetFirstVehicleInChain(v)->current_order.type != OT_LOADING; |
|
617 } else { |
|
618 in_motion = v->current_order.type != OT_LOADING; |
|
619 } |
|
620 } |
|
621 |
|
622 group = GetVehicleSpriteGroup(engine, v); |
|
623 group = ResolveVehicleSpriteGroup(group, v, 0, (resolve_callback) ResolveVehicleSpriteGroup); |
|
624 |
|
625 if (group == NULL && cargo != GC_DEFAULT) { |
|
626 // This group is empty but perhaps there'll be a default one. |
|
627 group = ResolveVehicleSpriteGroup(engine_custom_sprites[engine][GC_DEFAULT], v, 0, |
|
628 (resolve_callback) ResolveVehicleSpriteGroup); |
|
629 } |
|
630 |
|
631 if (group == NULL) |
|
632 return 0; |
|
633 |
|
634 assert(group->type == SGT_REAL); |
|
635 rsg = &group->g.real; |
|
636 |
|
637 if (!rsg->sprites_per_set) { |
|
638 // This group is empty. This function users should therefore |
|
639 // look up the sprite number in _engine_original_sprites. |
|
640 return 0; |
|
641 } |
|
642 |
|
643 assert(rsg->sprites_per_set <= 8); |
|
644 direction %= rsg->sprites_per_set; |
|
645 |
|
646 totalsets = in_motion ? rsg->loaded_count : rsg->loading_count; |
|
647 |
|
648 // My aim here is to make it possible to visually determine absolutely |
|
649 // empty and totally full vehicles. --pasky |
|
650 if (loaded == 100 || totalsets == 1) { // full |
|
651 spriteset = totalsets - 1; |
|
652 } else if (loaded == 0 || totalsets == 2) { // empty |
|
653 spriteset = 0; |
|
654 } else { // something inbetween |
|
655 spriteset = loaded * (totalsets - 2) / 100 + 1; |
|
656 // correct possible rounding errors |
|
657 if (!spriteset) |
|
658 spriteset = 1; |
|
659 else if (spriteset == totalsets - 1) |
|
660 spriteset--; |
|
661 } |
|
662 |
|
663 r = (in_motion ? rsg->loaded[spriteset]->g.result.result : rsg->loading[spriteset]->g.result.result) + direction; |
|
664 return r; |
|
665 } |
|
666 |
|
667 /** |
|
668 * Check if a wagon is currently using a wagon override |
|
669 * @param v The wagon to check |
|
670 * @return true if it is using an override, false otherwise |
|
671 */ |
|
672 bool UsesWagonOverride(const Vehicle* v) |
|
673 { |
|
674 assert(v->type == VEH_Train); |
|
675 return GetWagonOverrideSpriteSet(v->engine_type, v->u.rail.first_engine) != NULL; |
|
676 } |
|
677 |
|
678 /** |
|
679 * Evaluates a newgrf callback |
|
680 * @param callback_info info about which callback to evaluate |
|
681 * (bit 0-7) = CallBack id of the callback to use, see CallBackId enum |
|
682 * (bit 8-15) = Other info some callbacks need to have, callback specific, see CallBackId enum, not used yet |
|
683 * @param engine Engine type of the vehicle to evaluate the callback for |
|
684 * @param vehicle The vehicle to evaluate the callback for, NULL if it doesnt exist (yet) |
|
685 * @return The value the callback returned, or CALLBACK_FAILED if it failed |
|
686 */ |
|
687 uint16 GetCallBackResult(uint16 callback_info, EngineID engine, const Vehicle *v) |
|
688 { |
|
689 const SpriteGroup *group; |
|
690 byte cargo = GC_DEFAULT; |
|
691 |
|
692 if (v != NULL) |
|
693 cargo = _global_cargo_id[_opt.landscape][v->cargo_type]; |
|
694 |
|
695 group = engine_custom_sprites[engine][cargo]; |
|
696 |
|
697 if (v != NULL && v->type == VEH_Train) { |
|
698 const SpriteGroup *overset = GetWagonOverrideSpriteSet(engine, v->u.rail.first_engine); |
|
699 |
|
700 if (overset != NULL) group = overset; |
|
701 } |
|
702 |
|
703 group = ResolveVehicleSpriteGroup(group, v, callback_info, (resolve_callback) ResolveVehicleSpriteGroup); |
|
704 |
|
705 if (group == NULL && cargo != GC_DEFAULT) { |
|
706 // This group is empty but perhaps there'll be a default one. |
|
707 group = ResolveVehicleSpriteGroup(engine_custom_sprites[engine][GC_DEFAULT], v, callback_info, |
|
708 (resolve_callback) ResolveVehicleSpriteGroup); |
|
709 } |
|
710 |
|
711 if (group == NULL || group->type != SGT_CALLBACK) |
|
712 return CALLBACK_FAILED; |
|
713 |
|
714 return group->g.callback.result; |
|
715 } |
|
716 |
|
717 |
|
718 |
|
719 // Global variables are evil, yes, but we would end up with horribly overblown |
|
720 // calling convention otherwise and this should be 100% reentrant. |
|
721 static byte _vsg_random_triggers; |
|
722 static byte _vsg_bits_to_reseed; |
|
723 |
|
724 static const SpriteGroup *TriggerVehicleSpriteGroup(const SpriteGroup *spritegroup, |
|
725 Vehicle *veh, uint16 callback_info, resolve_callback resolve_func) |
|
726 { |
|
727 if (spritegroup == NULL) |
|
728 return NULL; |
|
729 |
|
730 if (spritegroup->type == SGT_RANDOMIZED) { |
|
731 _vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits( |
|
732 &spritegroup->g.random, |
|
733 _vsg_random_triggers, |
|
734 &veh->waiting_triggers |
|
735 ); |
|
736 } |
|
737 |
|
738 return ResolveVehicleSpriteGroup(spritegroup, veh, callback_info, resolve_func); |
|
739 } |
|
740 |
|
741 static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_random_bits, bool first) |
|
742 { |
|
743 const SpriteGroup *group; |
|
744 const RealSpriteGroup *rsg; |
|
745 byte new_random_bits; |
|
746 |
|
747 _vsg_random_triggers = trigger; |
|
748 _vsg_bits_to_reseed = 0; |
|
749 group = TriggerVehicleSpriteGroup(GetVehicleSpriteGroup(veh->engine_type, veh), veh, 0, |
|
750 (resolve_callback) TriggerVehicleSpriteGroup); |
|
751 |
|
752 if (group == NULL && veh->cargo_type != GC_DEFAULT) { |
|
753 // This group turned out to be empty but perhaps there'll be a default one. |
|
754 group = TriggerVehicleSpriteGroup(engine_custom_sprites[veh->engine_type][GC_DEFAULT], veh, 0, |
|
755 (resolve_callback) TriggerVehicleSpriteGroup); |
|
756 } |
|
757 |
|
758 if (group == NULL) |
|
759 return; |
|
760 |
|
761 assert(group->type == SGT_REAL); |
|
762 rsg = &group->g.real; |
|
763 |
|
764 new_random_bits = Random(); |
|
765 veh->random_bits &= ~_vsg_bits_to_reseed; |
|
766 veh->random_bits |= (first ? new_random_bits : base_random_bits) & _vsg_bits_to_reseed; |
|
767 |
|
768 switch (trigger) { |
|
769 case VEHICLE_TRIGGER_NEW_CARGO: |
|
770 /* All vehicles in chain get ANY_NEW_CARGO trigger now. |
|
771 * So we call it for the first one and they will recurse. */ |
|
772 /* Indexing part of vehicle random bits needs to be |
|
773 * same for all triggered vehicles in the chain (to get |
|
774 * all the random-cargo wagons carry the same cargo, |
|
775 * i.e.), so we give them all the NEW_CARGO triggered |
|
776 * vehicle's portion of random bits. */ |
|
777 assert(first); |
|
778 DoTriggerVehicle(GetFirstVehicleInChain(veh), VEHICLE_TRIGGER_ANY_NEW_CARGO, new_random_bits, false); |
|
779 break; |
|
780 case VEHICLE_TRIGGER_DEPOT: |
|
781 /* We now trigger the next vehicle in chain recursively. |
|
782 * The random bits portions may be different for each |
|
783 * vehicle in chain. */ |
|
784 if (veh->next != NULL) |
|
785 DoTriggerVehicle(veh->next, trigger, 0, true); |
|
786 break; |
|
787 case VEHICLE_TRIGGER_EMPTY: |
|
788 /* We now trigger the next vehicle in chain |
|
789 * recursively. The random bits portions must be same |
|
790 * for each vehicle in chain, so we give them all |
|
791 * first chained vehicle's portion of random bits. */ |
|
792 if (veh->next != NULL) |
|
793 DoTriggerVehicle(veh->next, trigger, first ? new_random_bits : base_random_bits, false); |
|
794 break; |
|
795 case VEHICLE_TRIGGER_ANY_NEW_CARGO: |
|
796 /* Now pass the trigger recursively to the next vehicle |
|
797 * in chain. */ |
|
798 assert(!first); |
|
799 if (veh->next != NULL) |
|
800 DoTriggerVehicle(veh->next, VEHICLE_TRIGGER_ANY_NEW_CARGO, base_random_bits, false); |
|
801 break; |
|
802 } |
|
803 } |
|
804 |
|
805 void TriggerVehicle(Vehicle *veh, VehicleTrigger trigger) |
|
806 { |
|
807 if (trigger == VEHICLE_TRIGGER_DEPOT) { |
|
808 // store that the vehicle entered a depot this tick |
|
809 VehicleEnteredDepotThisTick(veh); |
|
810 } |
|
811 |
|
812 DoTriggerVehicle(veh, trigger, 0, true); |
|
813 } |
|
814 |
|
815 static char *_engine_custom_names[TOTAL_NUM_ENGINES]; |
|
816 |
|
817 void SetCustomEngineName(EngineID engine, const char *name) |
|
818 { |
|
819 _engine_custom_names[engine] = strdup(name); |
|
820 } |
|
821 |
|
822 void UnloadCustomEngineNames(void) |
|
823 { |
|
824 char **i; |
|
825 for (i = _engine_custom_names; i != endof(_engine_custom_names); i++) { |
|
826 free(*i); |
|
827 *i = NULL; |
|
828 } |
|
829 } |
|
830 |
|
831 StringID GetCustomEngineName(EngineID engine) |
|
832 { |
|
833 if (!_engine_custom_names[engine]) |
|
834 return _engine_name_strings[engine]; |
|
835 ttd_strlcpy(_userstring, _engine_custom_names[engine], lengthof(_userstring)); |
|
836 return STR_SPEC_USERSTRING; |
|
837 } |
|
838 |
|
839 |
|
840 static void AcceptEnginePreview(Engine *e, PlayerID player) |
259 static void AcceptEnginePreview(Engine *e, PlayerID player) |
841 { |
260 { |
842 Player *p = GetPlayer(player); |
261 Player *p = GetPlayer(player); |
843 |
262 |
844 assert(e->railtype < RAILTYPE_END); |
263 assert(e->railtype < RAILTYPE_END); |