MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / GetBestFittingSubType

Function GetBestFittingSubType

src/vehicle_gui.cpp:600–661  ·  view source on GitHub ↗

* Get the best fitting subtype when 'cloning'/'replacing' \a v_from with \a v_for. * All articulated parts of both vehicles are tested to find a possibly shared subtype. * For \a v_for only vehicle refittable to \a dest_cargo_type are considered. * @param v_from the vehicle to match the subtype from * @param v_for the vehicle to get the subtype for * @param dest_cargo_type Destination cargo

Source from the content-addressed store, hash-verified

598 * @return the best sub type
599 */
600uint8_t GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoType dest_cargo_type)
601{
602 v_from = v_from->GetFirstEnginePart();
603 v_for = v_for->GetFirstEnginePart();
604
605 /* Create a list of subtypes used by the various parts of v_for */
606 static std::vector<StringID> subtypes;
607 subtypes.clear();
608 for (; v_from != nullptr; v_from = v_from->HasArticulatedPart() ? v_from->GetNextArticulatedPart() : nullptr) {
609 const Engine *e_from = v_from->GetEngine();
610 if (!e_from->CanCarryCargo() || !e_from->info.callback_mask.Test(VehicleCallbackMask::CargoSuffix)) continue;
611 include(subtypes, GetCargoSubtypeText(v_from));
612 }
613
614 uint8_t ret_refit_cyc = 0;
615 bool success = false;
616 if (!subtypes.empty()) {
617 /* Check whether any articulated part is refittable to 'dest_cargo_type' with a subtype listed in 'subtypes' */
618 for (Vehicle *v = v_for; v != nullptr; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : nullptr) {
619 const Engine *e = v->GetEngine();
620 if (!e->CanCarryCargo() || !e->info.callback_mask.Test(VehicleCallbackMask::CargoSuffix)) continue;
621 if (!HasBit(e->info.refit_mask, dest_cargo_type) && v->cargo_type != dest_cargo_type) continue;
622
623 CargoType old_cargo_type = v->cargo_type;
624 uint8_t old_cargo_subtype = v->cargo_subtype;
625
626 /* Set the 'destination' cargo */
627 v->cargo_type = dest_cargo_type;
628
629 /* Cycle through the refits */
630 for (uint refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) {
631 v->cargo_subtype = refit_cyc;
632
633 /* Make sure we don't pick up anything cached. */
634 v->First()->InvalidateNewGRFCache();
635 v->InvalidateNewGRFCache();
636
637 StringID subtype = GetCargoSubtypeText(v);
638 if (subtype == STR_EMPTY) break;
639
640 if (std::ranges::find(subtypes, subtype) == subtypes.end()) continue;
641
642 /* We found something matching. */
643 ret_refit_cyc = refit_cyc;
644 success = true;
645 break;
646 }
647
648 /* Reset the vehicle's cargo type */
649 v->cargo_type = old_cargo_type;
650 v->cargo_subtype = old_cargo_subtype;
651
652 /* Make sure we don't taint the vehicle. */
653 v->First()->InvalidateNewGRFCache();
654 v->InvalidateNewGRFCache();
655
656 if (success) break;
657 }

Callers 4

BuildReplacementVehicleFunction · 0.85
RefitVehicleFunction · 0.85
CmdCloneVehicleFunction · 0.85
HandleRefitMethod · 0.85

Calls 15

includeFunction · 0.85
GetCargoSubtypeTextFunction · 0.85
HasBitFunction · 0.85
HasArticulatedPartMethod · 0.80
CanCarryCargoMethod · 0.80
TestMethod · 0.80
InvalidateNewGRFCacheMethod · 0.80
findFunction · 0.50
GetFirstEnginePartMethod · 0.45
clearMethod · 0.45
GetEngineMethod · 0.45

Tested by

no test coverage detected