* Collects all (cargo, subcargo) refit options of a vehicle chain. */
| 762 | * Collects all (cargo, subcargo) refit options of a vehicle chain. |
| 763 | */ |
| 764 | void BuildRefitList() |
| 765 | { |
| 766 | /* Store the currently selected RefitOption. */ |
| 767 | std::optional<RefitOption> current_refit_option; |
| 768 | if (this->selected_refit != nullptr) current_refit_option = *(this->selected_refit); |
| 769 | this->selected_refit = nullptr; |
| 770 | |
| 771 | this->refit_list.clear(); |
| 772 | Vehicle *v = Vehicle::Get(this->window_number); |
| 773 | |
| 774 | /* Check only the selected vehicles. */ |
| 775 | VehicleSet vehicles_to_refit; |
| 776 | GetVehicleSet(vehicles_to_refit, Vehicle::Get(this->selected_vehicle), this->num_vehicles); |
| 777 | |
| 778 | do { |
| 779 | if (v->type == VEH_TRAIN && std::ranges::find(vehicles_to_refit, v->index) == vehicles_to_refit.end()) continue; |
| 780 | const Engine *e = v->GetEngine(); |
| 781 | CargoTypes cmask = e->info.refit_mask; |
| 782 | VehicleCallbackMasks callback_mask = e->info.callback_mask; |
| 783 | |
| 784 | /* Skip this engine if it does not carry anything */ |
| 785 | if (!e->CanCarryCargo()) continue; |
| 786 | /* Skip this engine if we build the list for auto-refitting and engine doesn't allow it. */ |
| 787 | if (this->auto_refit && !e->info.misc_flags.Test(EngineMiscFlag::AutoRefit)) continue; |
| 788 | |
| 789 | /* Loop through all cargoes in the refit mask */ |
| 790 | for (const auto &cs : _sorted_cargo_specs) { |
| 791 | CargoType cargo_type = cs->Index(); |
| 792 | /* Skip cargo type if it's not listed */ |
| 793 | if (!HasBit(cmask, cargo_type)) continue; |
| 794 | |
| 795 | auto &list = this->refit_list[cargo_type]; |
| 796 | bool first_vehicle = list.empty(); |
| 797 | if (first_vehicle) { |
| 798 | /* Keeping the current subtype is always an option. It also serves as the option in case of no subtypes */ |
| 799 | list.emplace_back(cargo_type, UINT8_MAX, STR_EMPTY); |
| 800 | } |
| 801 | |
| 802 | /* Check the vehicle's callback mask for cargo suffixes. |
| 803 | * This is not supported for ordered refits, since subtypes only have a meaning |
| 804 | * for a specific vehicle at a specific point in time, which conflicts with shared orders, |
| 805 | * autoreplace, autorenew, clone, order restoration, ... */ |
| 806 | if (this->order == INVALID_VEH_ORDER_ID && callback_mask.Test(VehicleCallbackMask::CargoSuffix)) { |
| 807 | /* Make a note of the original cargo type. It has to be |
| 808 | * changed to test the cargo & subtype... */ |
| 809 | CargoType temp_cargo = v->cargo_type; |
| 810 | uint8_t temp_subtype = v->cargo_subtype; |
| 811 | |
| 812 | v->cargo_type = cargo_type; |
| 813 | |
| 814 | for (uint refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) { |
| 815 | v->cargo_subtype = refit_cyc; |
| 816 | |
| 817 | /* Make sure we don't pick up anything cached. */ |
| 818 | v->First()->InvalidateNewGRFCache(); |
| 819 | v->InvalidateNewGRFCache(); |
| 820 | |
| 821 | StringID subtype = GetCargoSubtypeText(v); |
no test coverage detected