* Start/Stop a vehicle * @param flags type of operation * @param veh_id vehicle to start/stop, don't forget to change CcStartStopVehicle if you modify this! * @param evaluate_startstop_cb Shall the start/stop newgrf callback be evaluated (only valid with DoCommandFlag::AutoReplace for network safety) * @return the cost of this operation or an error */
| 573 | * @return the cost of this operation or an error |
| 574 | */ |
| 575 | CommandCost CmdStartStopVehicle(DoCommandFlags flags, VehicleID veh_id, bool evaluate_startstop_cb) |
| 576 | { |
| 577 | /* Disable the effect of evaluate_startstop_cb, when DoCommandFlag::AutoReplace is not set */ |
| 578 | if (!flags.Test(DoCommandFlag::AutoReplace)) evaluate_startstop_cb = true; |
| 579 | |
| 580 | Vehicle *v = Vehicle::GetIfValid(veh_id); |
| 581 | if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR; |
| 582 | |
| 583 | CommandCost ret = CheckOwnership(v->owner); |
| 584 | if (ret.Failed()) return ret; |
| 585 | |
| 586 | if (v->vehstatus.Test(VehState::Crashed)) return CommandCost(STR_ERROR_VEHICLE_IS_DESTROYED); |
| 587 | |
| 588 | switch (v->type) { |
| 589 | case VEH_TRAIN: |
| 590 | if (v->vehstatus.Test(VehState::Stopped) && Train::From(v)->gcache.cached_power == 0) return CommandCost(STR_ERROR_TRAIN_START_NO_POWER); |
| 591 | break; |
| 592 | |
| 593 | case VEH_SHIP: |
| 594 | case VEH_ROAD: |
| 595 | break; |
| 596 | |
| 597 | case VEH_AIRCRAFT: { |
| 598 | Aircraft *a = Aircraft::From(v); |
| 599 | /* cannot stop airplane when in flight, or when taking off / landing */ |
| 600 | if (a->state >= STARTTAKEOFF && a->state < TERM7) return CommandCost(STR_ERROR_AIRCRAFT_IS_IN_FLIGHT); |
| 601 | if (HasBit(a->flags, VAF_HELI_DIRECT_DESCENT)) return CommandCost(STR_ERROR_AIRCRAFT_IS_IN_FLIGHT); |
| 602 | break; |
| 603 | } |
| 604 | |
| 605 | default: return CMD_ERROR; |
| 606 | } |
| 607 | |
| 608 | if (evaluate_startstop_cb) { |
| 609 | /* Check if this vehicle can be started/stopped. Failure means 'allow'. */ |
| 610 | std::array<int32_t, 1> regs100; |
| 611 | uint16_t callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v, regs100); |
| 612 | StringID error = STR_NULL; |
| 613 | if (callback != CALLBACK_FAILED) { |
| 614 | if (v->GetGRF()->grf_version < 8) { |
| 615 | /* 8 bit result 0xFF means 'allow' */ |
| 616 | if (callback < 0x400 && GB(callback, 0, 8) != 0xFF) error = GetGRFStringID(v->GetGRFID(), GRFSTR_MISC_GRF_TEXT + callback); |
| 617 | } else { |
| 618 | if (callback < 0x400) { |
| 619 | error = GetGRFStringID(v->GetGRFID(), GRFSTR_MISC_GRF_TEXT + callback); |
| 620 | } else { |
| 621 | switch (callback) { |
| 622 | case 0x400: // allow |
| 623 | break; |
| 624 | |
| 625 | case 0x40F: |
| 626 | error = GetGRFStringID(v->GetGRFID(), static_cast<GRFStringID>(regs100[0])); |
| 627 | break; |
| 628 | |
| 629 | default: // unknown reason -> disallow |
| 630 | error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES; |
| 631 | break; |
| 632 | } |
nothing calls this directly
no test coverage detected