diff --git a/src/tbtr_template_vehicle.cpp b/src/tbtr_template_vehicle.cpp index 6143249464..bfe83c6fc3 100644 --- a/src/tbtr_template_vehicle.cpp +++ b/src/tbtr_template_vehicle.cpp @@ -158,8 +158,8 @@ bool ShouldServiceTrainForTemplateReplacement(const Train *t, const TemplateVehi if (tv->IsReplaceOldOnly() && !t->NeedsAutorenewing(c, false)) return false; Money needed_money = c->settings.engine_renew_money; if (needed_money > c->money) return false; - bool need_replacement = !TrainMatchesTemplate(t, tv); - if (need_replacement) { + TBTRDiffFlags diff = TrainTemplateDifference(t, tv); + if (diff & TBTRDF_CONSIST) { /* Check money. * We want 2*(the price of the whole template) without looking at the value of the vehicle(s) we are going to sell, or not need to buy. */ for (const TemplateVehicle *tv_unit = tv; tv_unit != nullptr; tv_unit = tv_unit->GetNextUnit()) { @@ -167,10 +167,8 @@ bool ShouldServiceTrainForTemplateReplacement(const Train *t, const TemplateVehi needed_money += 2 * Engine::Get(tv->engine_type)->GetCost(); } return needed_money <= c->money; - } else if (!TrainMatchesTemplateRefit(t, tv) && tv->refit_as_template) { - return true; } else { - return false; + return diff != TBTRDF_NONE; } } diff --git a/src/tbtr_template_vehicle_func.cpp b/src/tbtr_template_vehicle_func.cpp index 8e702b17b2..7d1d29ec0e 100644 --- a/src/tbtr_template_vehicle_func.cpp +++ b/src/tbtr_template_vehicle_func.cpp @@ -277,35 +277,25 @@ void NeutralizeStatus(Train *t) DoCommand(0, t->index, 0, DC_EXEC, CMD_RENAME_VEHICLE, nullptr); } -bool TrainMatchesTemplate(const Train *t, const TemplateVehicle *tv) { - while (t && tv) { +TBTRDiffFlags TrainTemplateDifference(const Train *t, const TemplateVehicle *tv) { + TBTRDiffFlags diff = TBTRDF_NONE; + while (t != nullptr && tv != nullptr) { if (t->engine_type != tv->engine_type) { - return false; + return TBTRDF_ALL; + } + if (tv->refit_as_template && (t->cargo_type != tv->cargo_type || t->cargo_subtype != tv->cargo_subtype)) { + diff |= TBTRDF_REFIT; + } + if (HasBit(t->flags, VRF_REVERSE_DIRECTION) != HasBit(tv->ctrl_flags, TVCF_REVERSED)) { + diff |= TBTRDF_DIR; } t = t->GetNextUnit(); tv = tv->GetNextUnit(); } - if ((t && !tv) || (!t && tv)) { - return false; + if ((t != nullptr) != (tv != nullptr)) { + return TBTRDF_ALL; } - return true; -} - - -bool TrainMatchesTemplateRefit(const Train *t, const TemplateVehicle *tv) -{ - if (!tv->refit_as_template) { - return true; - } - - while (t && tv) { - if (t->cargo_type != tv->cargo_type || t->cargo_subtype != tv->cargo_subtype || HasBit(t->flags, VRF_REVERSE_DIRECTION) != HasBit(tv->ctrl_flags, TVCF_REVERSED)) { - return false; - } - t = t->GetNextUnit(); - tv = tv->GetNextUnit(); - } - return true; + return diff; } void BreakUpRemainders(Train *t) @@ -336,7 +326,7 @@ uint CountsTrainsNeedingTemplateReplacement(GroupID g_id, const TemplateVehicle if (!tv) return count; for (Train *t : Train::Iterate()) { - if (t->IsPrimaryVehicle() && t->group_id == g_id && (!TrainMatchesTemplate(t, tv) || !TrainMatchesTemplateRefit(t, tv))) { + if (t->IsPrimaryVehicle() && t->group_id == g_id && TrainTemplateDifference(t, tv) != TBTRDF_NONE) { count++; } } diff --git a/src/tbtr_template_vehicle_func.h b/src/tbtr_template_vehicle_func.h index df8aeb3763..e4a13783fd 100644 --- a/src/tbtr_template_vehicle_func.h +++ b/src/tbtr_template_vehicle_func.h @@ -55,8 +55,16 @@ void TransferCargoForTrain(Train *old_veh, Train *new_head); void NeutralizeStatus(Train *t); -bool TrainMatchesTemplate(const Train *t, const TemplateVehicle *tv); -bool TrainMatchesTemplateRefit(const Train *t, const TemplateVehicle *tv); +enum TBTRDiffFlags { + TBTRDF_NONE = 0, ///< no difference between train and template + TBTRDF_CONSIST = 1 << 0, ///< consist (vehicle units) differs between train and template + TBTRDF_REFIT = 1 << 1, ///< refit differs between train and template + TBTRDF_DIR = 1 << 2, ///< unit direction differs between train and template + TBTRDF_ALL = TBTRDF_CONSIST | TBTRDF_REFIT | TBTRDF_DIR, +}; +DECLARE_ENUM_AS_BIT_SET(TBTRDiffFlags) + +TBTRDiffFlags TrainTemplateDifference(const Train *t, const TemplateVehicle *tv); void UpdateAllTemplateVehicleImages(); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 528da9f544..6d5e7a6f36 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -7185,13 +7185,17 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3 if (tv->IsReplaceOldOnly() && !incoming->NeedsAutorenewing(Company::Get(incoming->owner), false)) { return CommandCost(); } - bool need_replacement = !TrainMatchesTemplate(incoming, tv); - bool need_refit = !TrainMatchesTemplateRefit(incoming, tv); - bool use_refit = tv->refit_as_template; + const TBTRDiffFlags diff = TrainTemplateDifference(incoming, tv); + if (diff == TBTRDF_NONE) return CommandCost(); + + const bool need_replacement = (diff & TBTRDF_CONSIST); + const bool need_refit = (diff & TBTRDF_REFIT); + const bool refit_to_template = tv->refit_as_template; + CargoID store_refit_ct = CT_INVALID; uint16 store_refit_csubt = 0; // if a train shall keep its old refit, store the refit setting of its first vehicle - if (!use_refit) { + if (!refit_to_template) { for (Train *getc = incoming; getc != nullptr; getc = getc->GetNextUnit()) { if (getc->cargo_type != CT_INVALID && getc->cargo_cap > 0) { store_refit_ct = getc->cargo_type; @@ -7200,11 +7204,7 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3 } } - if (!need_replacement) { - if (!need_refit || !use_refit) { - return CommandCost(); - } - } else { + if (need_replacement) { CommandCost buy_cost = TestBuyAllTemplateVehiclesInChain(tv, tile); if (buy_cost.Failed()) { if (buy_cost.GetErrorMessage() == INVALID_STRING_ID) return CommandCost(STR_ERROR_CAN_T_BUY_TRAIN); @@ -7214,7 +7214,7 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3 } } - if (need_replacement || (need_refit && use_refit)) RegisterGameEvents(GEF_TBTR_REPLACEMENT); + RegisterGameEvents(GEF_TBTR_REPLACEMENT); TemplateDepotVehicles depot_vehicles; if (tv->IsSetReuseDepotVehicles()) depot_vehicles.Init(tile); @@ -7291,7 +7291,7 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3 // additionally, if we don't want to use the template refit, refit as incoming // the template refit will be set further down, if we use it at all - if (!use_refit) { + if (!refit_to_template) { buy.AddCost(DoCommand(new_chain->tile, new_chain->index, store_refit_ct | store_refit_csubt << 8 | (1 << 16) | (1 << 31), flags, GetCmdRefitVeh(new_chain))); } } @@ -7352,7 +7352,7 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3 } // TODO: is this enough ? might it be that we bought a new wagon here and it now has std refit ? if (need_refit && new_part != nullptr) { - if (use_refit) { + if (refit_to_template) { DoCommand(tile, new_part->index, cur_tmpl->cargo_type | (cur_tmpl->cargo_subtype << 8) | (1 << 16) | (1 << 31), flags, GetCmdRefitVeh(new_part)); } else { DoCommand(tile, new_part->index, store_refit_ct | (store_refit_csubt << 8) | (1 << 16) | (1 << 31), flags, GetCmdRefitVeh(new_part)); @@ -7374,7 +7374,7 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3 // neutralize each remaining engine's status // refit, only if the template option is set so - if (use_refit && (need_refit || need_replacement)) { + if (refit_to_template && (need_refit || need_replacement)) { buy.AddCost(CmdRefitTrainFromTemplate(new_chain, tv, flags)); }