18 #include "train.h" |
18 #include "train.h" |
19 #include "aircraft.h" |
19 #include "aircraft.h" |
20 #include "newgrf_cargo.h" |
20 #include "newgrf_cargo.h" |
21 #include "date.h" |
21 #include "date.h" |
22 #include "table/engines.h" |
22 #include "table/engines.h" |
|
23 #include "group.h" |
23 |
24 |
24 EngineInfo _engine_info[TOTAL_NUM_ENGINES]; |
25 EngineInfo _engine_info[TOTAL_NUM_ENGINES]; |
25 RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES]; |
26 RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES]; |
26 ShipVehicleInfo _ship_vehicle_info[NUM_SHIP_ENGINES]; |
27 ShipVehicleInfo _ship_vehicle_info[NUM_SHIP_ENGINES]; |
27 AircraftVehicleInfo _aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES]; |
28 AircraftVehicleInfo _aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES]; |
67 |
68 |
68 |
69 |
69 static void CalcEngineReliability(Engine *e) |
70 static void CalcEngineReliability(Engine *e) |
70 { |
71 { |
71 uint age = e->age; |
72 uint age = e->age; |
|
73 |
|
74 /* Check for early retirement */ |
|
75 if (e->player_avail != 0 && !_patches.never_expire_vehicles) { |
|
76 uint retire_early = EngInfo(e - _engines)->retire_early; |
|
77 if (retire_early > 0 && age >= e->duration_phase_1 + e->duration_phase_2 - retire_early * 12) { |
|
78 /* Early retirement is enabled and we're past the date... */ |
|
79 e->player_avail = 0; |
|
80 AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type); |
|
81 } |
|
82 } |
72 |
83 |
73 if (age < e->duration_phase_1) { |
84 if (age < e->duration_phase_1) { |
74 uint start = e->reliability_start; |
85 uint start = e->reliability_start; |
75 e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start; |
86 e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start; |
76 } else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _patches.never_expire_vehicles) { |
87 } else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _patches.never_expire_vehicles) { |
399 if (e->type != type) return false; |
410 if (e->type != type) return false; |
400 |
411 |
401 /* check if it's available */ |
412 /* check if it's available */ |
402 if (!HASBIT(e->player_avail, player)) return false; |
413 if (!HASBIT(e->player_avail, player)) return false; |
403 |
414 |
|
415 if (type == VEH_TRAIN) { |
|
416 /* Check if the rail type is available to this player */ |
|
417 const Player *p = GetPlayer(player); |
|
418 if (!HASBIT(p->avail_railtypes, RailVehInfo(engine)->railtype)) return false; |
|
419 } |
|
420 |
404 return true; |
421 return true; |
405 } |
422 } |
406 |
423 |
407 /** Get the default cargo type for a certain engine type |
424 /** Get the default cargo type for a certain engine type |
408 * @param engine The ID to get the cargo for |
425 * @param engine The ID to get the cargo for |
463 for (er = GetEngineRenew(0); er != NULL; er = (er->index + 1U < GetEngineRenewPoolSize()) ? GetEngineRenew(er->index + 1U) : NULL) { |
480 for (er = GetEngineRenew(0); er != NULL; er = (er->index + 1U < GetEngineRenewPoolSize()) ? GetEngineRenew(er->index + 1U) : NULL) { |
464 if (IsValidEngineRenew(er)) continue; |
481 if (IsValidEngineRenew(er)) continue; |
465 |
482 |
466 er->to = INVALID_ENGINE; |
483 er->to = INVALID_ENGINE; |
467 er->next = NULL; |
484 er->next = NULL; |
|
485 er->group_id = DEFAULT_GROUP; |
468 return er; |
486 return er; |
469 } |
487 } |
470 |
488 |
471 /* Check if we can add a block to the pool */ |
489 /* Check if we can add a block to the pool */ |
472 if (AddBlockToPool(&_EngineRenew_pool)) return AllocateEngineRenew(); |
490 if (AddBlockToPool(&_EngineRenew_pool)) return AllocateEngineRenew(); |
475 } |
493 } |
476 |
494 |
477 /** |
495 /** |
478 * Retrieves the EngineRenew that specifies the replacement of the given |
496 * Retrieves the EngineRenew that specifies the replacement of the given |
479 * engine type from the given renewlist */ |
497 * engine type from the given renewlist */ |
480 static EngineRenew *GetEngineReplacement(EngineRenewList erl, EngineID engine) |
498 static EngineRenew *GetEngineReplacement(EngineRenewList erl, EngineID engine, GroupID group) |
481 { |
499 { |
482 EngineRenew *er = (EngineRenew *)erl; |
500 EngineRenew *er = (EngineRenew *)erl; |
483 |
501 |
484 while (er) { |
502 while (er) { |
485 if (er->from == engine) return er; |
503 if (er->from == engine && er->group_id == group) return er; |
486 er = er->next; |
504 er = er->next; |
487 } |
505 } |
488 return NULL; |
506 return NULL; |
489 } |
507 } |
490 |
508 |
499 er = next; |
517 er = next; |
500 } |
518 } |
501 *erl = NULL; // Empty list |
519 *erl = NULL; // Empty list |
502 } |
520 } |
503 |
521 |
504 EngineID EngineReplacement(EngineRenewList erl, EngineID engine) |
522 EngineID EngineReplacement(EngineRenewList erl, EngineID engine, GroupID group) |
505 { |
523 { |
506 const EngineRenew *er = GetEngineReplacement(erl, engine); |
524 const EngineRenew *er = GetEngineReplacement(erl, engine, group); |
507 return er == NULL ? INVALID_ENGINE : er->to; |
525 return er == NULL ? INVALID_ENGINE : er->to; |
508 } |
526 } |
509 |
527 |
510 int32 AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, uint32 flags) |
528 int32 AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, GroupID group, uint32 flags) |
511 { |
529 { |
512 EngineRenew *er; |
530 EngineRenew *er; |
513 |
531 |
514 /* Check if the old vehicle is already in the list */ |
532 /* Check if the old vehicle is already in the list */ |
515 er = GetEngineReplacement(*erl, old_engine); |
533 er = GetEngineReplacement(*erl, old_engine, group); |
516 if (er != NULL) { |
534 if (er != NULL) { |
517 if (flags & DC_EXEC) er->to = new_engine; |
535 if (flags & DC_EXEC) er->to = new_engine; |
518 return 0; |
536 return 0; |
519 } |
537 } |
520 |
538 |
522 if (er == NULL) return CMD_ERROR; |
540 if (er == NULL) return CMD_ERROR; |
523 |
541 |
524 if (flags & DC_EXEC) { |
542 if (flags & DC_EXEC) { |
525 er->from = old_engine; |
543 er->from = old_engine; |
526 er->to = new_engine; |
544 er->to = new_engine; |
|
545 er->group_id = group; |
527 |
546 |
528 /* Insert before the first element */ |
547 /* Insert before the first element */ |
529 er->next = (EngineRenew *)(*erl); |
548 er->next = (EngineRenew *)(*erl); |
530 *erl = (EngineRenewList)er; |
549 *erl = (EngineRenewList)er; |
531 } |
550 } |
532 |
551 |
533 return 0; |
552 return 0; |
534 } |
553 } |
535 |
554 |
536 int32 RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, uint32 flags) |
555 int32 RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, GroupID group, uint32 flags) |
537 { |
556 { |
538 EngineRenew *er = (EngineRenew *)(*erl); |
557 EngineRenew *er = (EngineRenew *)(*erl); |
539 EngineRenew *prev = NULL; |
558 EngineRenew *prev = NULL; |
540 |
559 |
541 while (er) |
560 while (er) |
542 { |
561 { |
543 if (er->from == engine) { |
562 if (er->from == engine && er->group_id == group) { |
544 if (flags & DC_EXEC) { |
563 if (flags & DC_EXEC) { |
545 if (prev == NULL) { // First element |
564 if (prev == NULL) { // First element |
546 /* The second becomes the new first element */ |
565 /* The second becomes the new first element */ |
547 *erl = (EngineRenewList)er->next; |
566 *erl = (EngineRenewList)er->next; |
548 } else { |
567 } else { |
559 |
578 |
560 return CMD_ERROR; |
579 return CMD_ERROR; |
561 } |
580 } |
562 |
581 |
563 static const SaveLoad _engine_renew_desc[] = { |
582 static const SaveLoad _engine_renew_desc[] = { |
564 SLE_VAR(EngineRenew, from, SLE_UINT16), |
583 SLE_VAR(EngineRenew, from, SLE_UINT16), |
565 SLE_VAR(EngineRenew, to, SLE_UINT16), |
584 SLE_VAR(EngineRenew, to, SLE_UINT16), |
566 |
585 |
567 SLE_REF(EngineRenew, next, REF_ENGINE_RENEWS), |
586 SLE_REF(EngineRenew, next, REF_ENGINE_RENEWS), |
568 |
587 SLE_CONDVAR(EngineRenew, group_id, SLE_UINT16, 60, SL_MAX_VERSION), |
569 SLE_END() |
588 SLE_END() |
570 }; |
589 }; |
571 |
590 |
572 static void Save_ERNW() |
591 static void Save_ERNW() |
573 { |
592 { |
589 if (!AddBlockIfNeeded(&_EngineRenew_pool, index)) |
608 if (!AddBlockIfNeeded(&_EngineRenew_pool, index)) |
590 error("EngineRenews: failed loading savegame: too many EngineRenews"); |
609 error("EngineRenews: failed loading savegame: too many EngineRenews"); |
591 |
610 |
592 er = GetEngineRenew(index); |
611 er = GetEngineRenew(index); |
593 SlObject(er, _engine_renew_desc); |
612 SlObject(er, _engine_renew_desc); |
|
613 |
|
614 /* Advanced vehicle lists got added */ |
|
615 if (CheckSavegameVersion(60)) er->group_id = DEFAULT_GROUP; |
594 } |
616 } |
595 } |
617 } |
596 |
618 |
597 static const SaveLoad _engine_desc[] = { |
619 static const SaveLoad _engine_desc[] = { |
598 SLE_CONDVAR(Engine, intro_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), |
620 SLE_CONDVAR(Engine, intro_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), |