TBTR: Refactor train/template match function to return difference flags

This commit is contained in:
Jonathan G Rennison
2023-08-20 21:09:22 +01:00
parent 2b44d3302e
commit 2cf95eea36
4 changed files with 40 additions and 44 deletions

View File

@@ -158,8 +158,8 @@ bool ShouldServiceTrainForTemplateReplacement(const Train *t, const TemplateVehi
if (tv->IsReplaceOldOnly() && !t->NeedsAutorenewing(c, false)) return false; if (tv->IsReplaceOldOnly() && !t->NeedsAutorenewing(c, false)) return false;
Money needed_money = c->settings.engine_renew_money; Money needed_money = c->settings.engine_renew_money;
if (needed_money > c->money) return false; if (needed_money > c->money) return false;
bool need_replacement = !TrainMatchesTemplate(t, tv); TBTRDiffFlags diff = TrainTemplateDifference(t, tv);
if (need_replacement) { if (diff & TBTRDF_CONSIST) {
/* Check money. /* 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. */ * 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()) { 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(); needed_money += 2 * Engine::Get(tv->engine_type)->GetCost();
} }
return needed_money <= c->money; return needed_money <= c->money;
} else if (!TrainMatchesTemplateRefit(t, tv) && tv->refit_as_template) {
return true;
} else { } else {
return false; return diff != TBTRDF_NONE;
} }
} }

View File

@@ -277,35 +277,25 @@ void NeutralizeStatus(Train *t)
DoCommand(0, t->index, 0, DC_EXEC, CMD_RENAME_VEHICLE, nullptr); DoCommand(0, t->index, 0, DC_EXEC, CMD_RENAME_VEHICLE, nullptr);
} }
bool TrainMatchesTemplate(const Train *t, const TemplateVehicle *tv) { TBTRDiffFlags TrainTemplateDifference(const Train *t, const TemplateVehicle *tv) {
while (t && tv) { TBTRDiffFlags diff = TBTRDF_NONE;
while (t != nullptr && tv != nullptr) {
if (t->engine_type != tv->engine_type) { 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(); t = t->GetNextUnit();
tv = tv->GetNextUnit(); tv = tv->GetNextUnit();
} }
if ((t && !tv) || (!t && tv)) { if ((t != nullptr) != (tv != nullptr)) {
return false; return TBTRDF_ALL;
} }
return true; return diff;
}
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;
} }
void BreakUpRemainders(Train *t) void BreakUpRemainders(Train *t)
@@ -336,7 +326,7 @@ uint CountsTrainsNeedingTemplateReplacement(GroupID g_id, const TemplateVehicle
if (!tv) return count; if (!tv) return count;
for (Train *t : Train::Iterate()) { 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++; count++;
} }
} }

View File

@@ -55,8 +55,16 @@ void TransferCargoForTrain(Train *old_veh, Train *new_head);
void NeutralizeStatus(Train *t); void NeutralizeStatus(Train *t);
bool TrainMatchesTemplate(const Train *t, const TemplateVehicle *tv); enum TBTRDiffFlags {
bool TrainMatchesTemplateRefit(const Train *t, const TemplateVehicle *tv); 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(); void UpdateAllTemplateVehicleImages();

View File

@@ -7185,13 +7185,17 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3
if (tv->IsReplaceOldOnly() && !incoming->NeedsAutorenewing(Company::Get(incoming->owner), false)) { if (tv->IsReplaceOldOnly() && !incoming->NeedsAutorenewing(Company::Get(incoming->owner), false)) {
return CommandCost(); return CommandCost();
} }
bool need_replacement = !TrainMatchesTemplate(incoming, tv); const TBTRDiffFlags diff = TrainTemplateDifference(incoming, tv);
bool need_refit = !TrainMatchesTemplateRefit(incoming, tv); if (diff == TBTRDF_NONE) return CommandCost();
bool use_refit = tv->refit_as_template;
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; CargoID store_refit_ct = CT_INVALID;
uint16 store_refit_csubt = 0; uint16 store_refit_csubt = 0;
// if a train shall keep its old refit, store the refit setting of its first vehicle // 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()) { for (Train *getc = incoming; getc != nullptr; getc = getc->GetNextUnit()) {
if (getc->cargo_type != CT_INVALID && getc->cargo_cap > 0) { if (getc->cargo_type != CT_INVALID && getc->cargo_cap > 0) {
store_refit_ct = getc->cargo_type; store_refit_ct = getc->cargo_type;
@@ -7200,11 +7204,7 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3
} }
} }
if (!need_replacement) { if (need_replacement) {
if (!need_refit || !use_refit) {
return CommandCost();
}
} else {
CommandCost buy_cost = TestBuyAllTemplateVehiclesInChain(tv, tile); CommandCost buy_cost = TestBuyAllTemplateVehiclesInChain(tv, tile);
if (buy_cost.Failed()) { if (buy_cost.Failed()) {
if (buy_cost.GetErrorMessage() == INVALID_STRING_ID) return CommandCost(STR_ERROR_CAN_T_BUY_TRAIN); 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; TemplateDepotVehicles depot_vehicles;
if (tv->IsSetReuseDepotVehicles()) depot_vehicles.Init(tile); 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 // 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 // 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))); 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 ? // 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 (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)); DoCommand(tile, new_part->index, cur_tmpl->cargo_type | (cur_tmpl->cargo_subtype << 8) | (1 << 16) | (1 << 31), flags, GetCmdRefitVeh(new_part));
} else { } else {
DoCommand(tile, new_part->index, store_refit_ct | (store_refit_csubt << 8) | (1 << 16) | (1 << 31), flags, GetCmdRefitVeh(new_part)); 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 // neutralize each remaining engine's status
// refit, only if the template option is set so // 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)); buy.AddCost(CmdRefitTrainFromTemplate(new_chain, tv, flags));
} }