From 21faae910ba9d64c3674db827c2bf1b656c2dbe7 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 8 Mar 2019 19:20:36 +0000 Subject: [PATCH 01/12] TBTR: Remove duplicated function: SetupTemplateVehicleFromVirtual (cherry picked from commit c6fa43d76799d8759eb7c65cf8366013053ebede) --- src/tbtr_template_vehicle_func.cpp | 2 +- src/tbtr_template_vehicle_func.h | 2 +- src/vehicle_cmd.cpp | 28 ---------------------------- 3 files changed, 2 insertions(+), 30 deletions(-) diff --git a/src/tbtr_template_vehicle_func.cpp b/src/tbtr_template_vehicle_func.cpp index 7be8d42540..50864f805d 100644 --- a/src/tbtr_template_vehicle_func.cpp +++ b/src/tbtr_template_vehicle_func.cpp @@ -141,7 +141,7 @@ void DrawTemplate(const TemplateVehicle *tv, int left, int right, int y) } // copy important stuff from the virtual vehicle to the template -inline void SetupTemplateVehicleFromVirtual(TemplateVehicle *tmp, TemplateVehicle *prev, Train *virt) +void SetupTemplateVehicleFromVirtual(TemplateVehicle *tmp, TemplateVehicle *prev, Train *virt) { if (prev) { prev->SetNext(tmp); diff --git a/src/tbtr_template_vehicle_func.h b/src/tbtr_template_vehicle_func.h index 5882ad1252..a927948a0a 100644 --- a/src/tbtr_template_vehicle_func.h +++ b/src/tbtr_template_vehicle_func.h @@ -26,8 +26,8 @@ Money CalculateOverallTemplateCost(const TemplateVehicle*); void DrawTemplate(const TemplateVehicle*, int, int, int); TemplateVehicle* TemplateVehicleFromVirtualTrain(Train *virt); - Train* DeleteVirtualTrain(Train*, Train *); +void SetupTemplateVehicleFromVirtual(TemplateVehicle *tmp, TemplateVehicle *prev, Train *virt); CommandCost CmdTemplateReplaceVehicle(Train*, bool, DoCommandFlag); diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 4a8419b2cf..dd706b7a5a 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -784,34 +784,6 @@ static void CloneVehicleName(const Vehicle *src, Vehicle *dst) /* All done. If we didn't find a name, it'll just use its default. */ } -inline void SetupTemplateVehicleFromVirtual(TemplateVehicle *tmp, TemplateVehicle *prev, Train *virt) -{ - if (prev) { - prev->SetNext(tmp); - tmp->SetPrev(prev); - tmp->SetFirst(prev->First()); - } - tmp->railtype = virt->railtype; - tmp->owner = virt->owner; - tmp->value = virt->value; - - // set the subtype but also clear the virtual flag while doing it - tmp->subtype = virt->subtype & ~(1 << GVSF_VIRTUAL); - // set the cargo type and capacity - tmp->cargo_type = virt->cargo_type; - tmp->cargo_subtype = virt->cargo_subtype; - tmp->cargo_cap = virt->cargo_cap; - - const GroundVehicleCache *gcache = virt->GetGroundVehicleCache(); - tmp->max_speed = virt->GetDisplayMaxSpeed(); - tmp->power = gcache->cached_power; - tmp->weight = gcache->cached_weight; - tmp->max_te = gcache->cached_max_te / 1000; - - virt->GetImage(DIR_W, EIT_IN_DEPOT, &tmp->sprite_seq); - tmp->image_dimensions.SetFromTrain(virt); -} - /** * Toggles 'reuse depot vehicles' on a template vehicle. * @param tile unused From 324ce7ae96ea27df1d0baba002b6a7e7f5951806 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 27 Apr 2019 21:25:56 +0100 Subject: [PATCH 02/12] TBTR: Allow cloning virtual/template trains with unavailable engines (cherry picked from commit 9d861fb8a045cdaa2a2b471fffb12a33109ffcda) --- src/train.h | 2 +- src/train_cmd.cpp | 20 ++++++-------------- src/vehicle_cmd.cpp | 15 ++++++++------- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/train.h b/src/train.h index 04e2e450b1..0b679a45a9 100644 --- a/src/train.h +++ b/src/train.h @@ -353,7 +353,7 @@ CommandCost CmdMoveRailVehicle(TileIndex, DoCommandFlag , uint32, uint32, const CommandCost CmdMoveVirtualRailVehicle(TileIndex, DoCommandFlag, uint32, uint32, const char*); Train* CmdBuildVirtualRailWagon(const Engine*); -Train* CmdBuildVirtualRailVehicle(EngineID, bool lax_engine_check, StringID &error); +Train* CmdBuildVirtualRailVehicle(EngineID, StringID &error); #define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 21f3593a98..dd91d4d28f 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -4149,22 +4149,14 @@ Train* CmdBuildVirtualRailWagon(const Engine *e) return v; } -Train* CmdBuildVirtualRailVehicle(EngineID eid, bool lax_engine_check, StringID &error) +Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error) { - if (lax_engine_check) { - const Engine *e = Engine::GetIfValid(eid); - if (e == NULL || e->type != VEH_TRAIN) { - error = STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + VEH_TRAIN; - return NULL; - } - } else { - if (!IsEngineBuildable(eid, VEH_TRAIN, _current_company)) { - error = STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + VEH_TRAIN; - return NULL; - } + const Engine *e = Engine::GetIfValid(eid); + if (e == nullptr || e->type != VEH_TRAIN) { + error = STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + VEH_TRAIN; + return nullptr; } - const Engine* e = Engine::Get(eid); const RailVehicleInfo *rvi = &e->u.rail; int num_vehicles = (e->u.rail.railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + CountArticulatedParts(eid, false); @@ -4250,7 +4242,7 @@ CommandCost CmdBuildVirtualRailVehicle(TileIndex tile, DoCommandFlag flags, uint if (should_execute) { StringID err = INVALID_STRING_ID; - Train* train = CmdBuildVirtualRailVehicle(eid, false, err); + Train* train = CmdBuildVirtualRailVehicle(eid, err); if (train == NULL) { return_cmd_error(err); diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index dd706b7a5a..a910658543 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -946,13 +946,13 @@ Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err) assert(tv->owner == _current_company); - head = CmdBuildVirtualRailVehicle(tv->engine_type, true, err); - if (!head) return NULL; + head = CmdBuildVirtualRailVehicle(tv->engine_type, err); + if (!head) return nullptr; tail = head; tv = tv->GetNextUnit(); while (tv) { - tmp = CmdBuildVirtualRailVehicle(tv->engine_type, true, err); + tmp = CmdBuildVirtualRailVehicle(tv->engine_type, err); if (!tmp) { CmdDeleteVirtualTrain(INVALID_TILE, DC_EXEC, head->index, 0, NULL); return NULL; @@ -998,13 +998,13 @@ CommandCost CmdVirtualTrainFromTrain(TileIndex tile, DoCommandFlag flags, uint32 Train *tmp, *head, *tail; StringID err = INVALID_STRING_ID; - head = CmdBuildVirtualRailVehicle(train->engine_type, false, err); + head = CmdBuildVirtualRailVehicle(train->engine_type, err); if (!head) return_cmd_error(err); tail = head; train = train->GetNextUnit(); while (train) { - tmp = CmdBuildVirtualRailVehicle(train->engine_type, false, err); + tmp = CmdBuildVirtualRailVehicle(train->engine_type, err); if (!tmp) { CmdDeleteVirtualTrain(tile, flags, head->index, 0, NULL); return_cmd_error(err); @@ -1136,8 +1136,9 @@ CommandCost CmdTemplateVehicleFromTrain(TileIndex tile, DoCommandFlag flags, uin return CMD_ERROR; } - for (Train *v = clicked; v != NULL; v = v->GetNextUnit()) { - if (!IsEngineBuildable(v->engine_type, VEH_TRAIN, _current_company)) { + for (Train *v = clicked; v != nullptr; v = v->GetNextUnit()) { + const Engine *e = Engine::GetIfValid(v->engine_type); + if (e == nullptr || e->type != VEH_TRAIN) { return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + VEH_TRAIN); } } From e0578a6e0c3a13ffdc7bcf3529ec6e27e5445293 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 27 Apr 2019 22:47:31 +0100 Subject: [PATCH 03/12] TBTR: Show warning on templates which include unavailable vehicles (cherry picked from commit 6d3e9093c404ffd73d350bca47a9a4cee6cea872) --- src/lang/english.txt | 2 +- src/tbtr_template_gui_create.cpp | 20 ++++++++++++++++---- src/tbtr_template_gui_main.cpp | 12 ++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index d49e57ae61..eab7346271 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5009,7 +5009,7 @@ STR_TMPL_TEMPLATE_OVR_VALUE_nogoldandcurrency :{TINY_FONT}{BLA STR_TMPL_TEMPLATE_OVR_VALUE_notinyfont :{BLACK}Buying Cost: {GOLD}{CURRENCY_LONG} STR_TMPL_TEMPLATE_OVR_VALUE_notinyfontandblack :Buying Cost: {GOLD}{CURRENCY_LONG} STR_TMPL_WARNING_FREE_WAGON :{RED}Free Chain: not runnable! -STR_TMPL_TEST :{ORANGE}Test String: {RAW_STRING} {RAW_STRING} +STR_TMPL_WARNING_VEH_UNAVAILABLE :{RED}Train not buildable: vehicle unavailable! STR_TMPL_GROUP_USES_TEMPLATE :{BLACK}Template in use: {NUM} STR_TMP_TEMPLATE_IN_USE :Template is in use STR_TMPL_GROUP_NUM_TRAINS :{BLACK}{NUM} diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index 0c1a40f196..26b7d9f32b 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -307,19 +307,28 @@ public: old_dpi = _cur_dpi; _cur_dpi = &tmp_dpi; + int y = 4 - this->vscroll->GetPosition(); + bool buildable = true; + for (Train *train = this->virtual_train; train != nullptr; train = train->Next()) { + if (!IsEngineBuildable(train->engine_type, VEH_TRAIN, train->owner)) buildable = false; + } + if (!buildable) { + DrawString(8, r.right, y, STR_TMPL_WARNING_VEH_UNAVAILABLE); + y += FONT_HEIGHT_NORMAL; + } /* Draw vehicle performance info */ const GroundVehicleCache *gcache = this->virtual_train->GetGroundVehicleCache(); SetDParam(2, this->virtual_train->GetDisplayMaxSpeed()); SetDParam(1, gcache->cached_power); SetDParam(0, gcache->cached_weight); SetDParam(3, gcache->cached_max_te / 1000); - DrawString(8, r.right, 4 - this->vscroll->GetPosition(), STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE); + DrawString(8, r.right, y, STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE); /* Draw cargo summary */ CargoArray cargo_caps; for (const Train *tmp = this->virtual_train; tmp != NULL; tmp = tmp->Next()) { cargo_caps[tmp->cargo_type] += tmp->cargo_cap; } - int y = 30 - this->vscroll->GetPosition(); + y += 26; for (CargoID i = 0; i < NUM_CARGO; ++i) { if (cargo_caps[i] > 0) { SetDParam(0, i); @@ -443,11 +452,14 @@ public: uint height = 30; CargoArray cargo_caps; - if (virtual_train != NULL) { - for (Train *train = virtual_train; train != NULL; train = train->Next()) { + if (virtual_train != nullptr) { + bool buildable = true; + for (Train *train = virtual_train; train != nullptr; train = train->Next()) { width += train->GetDisplayImageWidth(); cargo_caps[train->cargo_type] += train->cargo_cap; + if (!IsEngineBuildable(train->engine_type, VEH_TRAIN, train->owner)) buildable = false; } + if (!buildable) height += FONT_HEIGHT_NORMAL; for (CargoID i = 0; i < NUM_CARGO; ++i) { if (cargo_caps[i] > 0) { diff --git a/src/tbtr_template_gui_main.cpp b/src/tbtr_template_gui_main.cpp index 77de26a9dd..0f3ecb7867 100644 --- a/src/tbtr_template_gui_main.cpp +++ b/src/tbtr_template_gui_main.cpp @@ -682,6 +682,18 @@ public: DrawString(left, right - ScaleGUITrad(24), y + ScaleGUITrad(2), STR_TMPL_WARNING_FREE_WAGON, TC_RED, SA_RIGHT); } + bool buildable = true; + for (const TemplateVehicle *u = v; u != nullptr; u = u->Next()) { + if (!IsEngineBuildable(u->engine_type, VEH_TRAIN, u->owner)) { + buildable = false; + break; + } + } + /* Draw a notification string for chains that are not buildable */ + if (!buildable) { + DrawString(left, right - ScaleGUITrad(24), y + ScaleGUITrad(2), STR_TMPL_WARNING_VEH_UNAVAILABLE, TC_RED, SA_CENTER); + } + /* Draw the template's length in tile-units */ SetDParam(0, v->GetRealLength()); SetDParam(1, 1); From 2e929a88a928d505f3897788c29beb9d6b95f56b Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Thu, 16 May 2019 20:01:56 +0100 Subject: [PATCH 04/12] TBTR: Fix incorrect deletion of template vehicles when deleting company (cherry picked from commit fff3018b4272e45a2558c3d0d66a6f1a7a113ce6) --- src/economy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/economy.cpp b/src/economy.cpp index 2eb46a0929..9487bcbf32 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -490,7 +490,7 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) if (new_owner == INVALID_OWNER) { TemplateVehicle *tv; FOR_ALL_TEMPLATES(tv) { - if (tv->owner == old_owner) { + if (tv->owner == old_owner && tv->Prev() == nullptr) { TemplateReplacement *tr; FOR_ALL_TEMPLATE_REPLACEMENTS(tr) { if (tr->Template() == tv->index) { From 835562d81d53c3d54ecd08dc77f6a1814d1c85e6 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Thu, 16 May 2019 20:02:39 +0100 Subject: [PATCH 05/12] TBTR: Remove unused function: TemplateReplacement::GetTemplateVehicle (cherry picked from commit 8afb21cf9c7e5e2a0a7febb133560d6805f8da62) --- src/tbtr_template_vehicle.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/tbtr_template_vehicle.h b/src/tbtr_template_vehicle.h index f86bbb865b..cf2ed446e7 100644 --- a/src/tbtr_template_vehicle.h +++ b/src/tbtr_template_vehicle.h @@ -205,17 +205,6 @@ struct TemplateReplacement : TemplateReplacementPool::PoolItem<&_template_replac inline void SetTemplate(TemplateID tid) { this->sel_template = tid; } inline TemplateID GetTemplateVehicleID() { return sel_template; } - - inline const TemplateVehicle* GetTemplateVehicle() - { - const TemplateVehicle *tv; - FOR_ALL_TEMPLATES(tv) { - if (tv->index == this->sel_template) { - return tv; - } - } - return NULL; - } }; TemplateReplacement* GetTemplateReplacementByGroupID(GroupID); From 2557cec6f354cc6c0c1e218ba6e4a76b71899242 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Thu, 16 May 2019 20:04:48 +0100 Subject: [PATCH 06/12] TBTR: Skip virtual vehicles in company rating/value and group stats (cherry picked from commit 34d7f12a70791018e9563af16ef31edbc3029f0f) --- src/economy.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/economy.cpp b/src/economy.cpp index 9487bcbf32..d181657eba 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -127,6 +127,7 @@ Money CalculateCompanyValue(const Company *c, bool including_loan) Vehicle *v; FOR_ALL_VEHICLES(v) { if (v->owner != owner) continue; + if (HasBit(v->subtype, GVSF_VIRTUAL)) continue; if (v->type == VEH_TRAIN || v->type == VEH_ROAD || @@ -167,7 +168,7 @@ int UpdateCompanyRatingAndValue(Company *c, bool update) FOR_ALL_VEHICLES(v) { if (v->owner != owner) continue; - if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle()) { + if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle() && !HasBit(v->subtype, GVSF_VIRTUAL)) { if (v->profit_last_year > 0) num++; // For the vehicle score only count profitable vehicles if (v->age > 730) { /* Find the vehicle with the lowest amount of profit */ @@ -473,7 +474,7 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) if (v->IsEngineCountable()) { GroupStatistics::CountEngine(v, 1); } - if (v->IsPrimaryVehicle()) { + if (v->IsPrimaryVehicle() && !HasBit(v->subtype, GVSF_VIRTUAL)) { GroupStatistics::CountVehicle(v, 1); v->unitnumber = unitidgen[v->type].NextID(); } From 2ccb6e1743b2c69e2c6f467423b2fa2766478294 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 18 May 2019 10:17:30 +0100 Subject: [PATCH 07/12] TBTR: Fix front engine not being cleared when being replaced. and kept in depot (cherry picked from commit ee0625862917f03439676311e2b175c41893c0e6) --- src/tbtr_template_vehicle_func.cpp | 2 +- src/train_cmd.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tbtr_template_vehicle_func.cpp b/src/tbtr_template_vehicle_func.cpp index 50864f805d..b678e26a5d 100644 --- a/src/tbtr_template_vehicle_func.cpp +++ b/src/tbtr_template_vehicle_func.cpp @@ -331,7 +331,7 @@ void BreakUpRemainders(Train *t) if (HasBit(t->subtype, GVSF_ENGINE)) { move = t; t = t->Next(); - DoCommand(move->tile, move->index, INVALID_VEHICLE, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); + DoCommand(move->tile, move->index | (1 << 22), INVALID_VEHICLE, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); NeutralizeStatus(move); } else { t = t->Next(); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index dd91d4d28f..4e3aae1d07 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1173,6 +1173,7 @@ static void NormaliseTrainHead(Train *head) * - p1 (bit 0 - 19) source vehicle index * - p1 (bit 20) move all vehicles following the source vehicle * - p1 (bit 21) this is a virtual vehicle (for creating TemplateVehicles) + * - p1 (bit 22) when moving a head vehicle, always reset the head state * @param p2 what wagon to put the source wagon AFTER, XXX - INVALID_VEHICLE to make a new line * @param text unused * @return the cost of this operation or an error @@ -1182,6 +1183,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u VehicleID s = GB(p1, 0, 20); VehicleID d = GB(p2, 0, 20); bool move_chain = HasBit(p1, 20); + bool new_head = HasBit(p1, 22); Train *src = Train::GetIfValid(s); if (src == NULL) return CMD_ERROR; @@ -1317,7 +1319,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u * 6) non front engine gets moved within a train / to another train, nothing hapens * 7) wagon gets moved, nothing happens */ - if (src == original_src_head && src->IsEngine() && !src->IsFrontEngine()) { + if (src == original_src_head && src->IsEngine() && (!src->IsFrontEngine() || new_head)) { /* Cases #2 and #3: the front engine gets trashed. */ DeleteWindowById(WC_VEHICLE_VIEW, src->index); DeleteWindowById(WC_VEHICLE_ORDERS, src->index); @@ -1336,7 +1338,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u /* We weren't a front engine but are becoming one. So * we should be put in the default group. */ - if (original_src_head != src && dst_head == src) { + if ((original_src_head != src || new_head) && dst_head == src) { SetTrainGroupID(src, DEFAULT_GROUP); SetWindowDirty(WC_COMPANY, _current_company); } From aa1055652252f5a3ab70768c1b2c7a3b8e7dc70b Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 11 Jun 2019 01:59:17 +0100 Subject: [PATCH 08/12] TBTR: Avoid articulated/rear units being added to tile hash (cherry picked from commit 5a2e4981824cf30f13dde50a4a518a71d00ad000) --- src/articulated_vehicles.cpp | 2 ++ src/train_cmd.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp index 44ad587895..a46ac7f7af 100644 --- a/src/articulated_vehicles.cpp +++ b/src/articulated_vehicles.cpp @@ -394,6 +394,8 @@ void AddArticulatedParts(Vehicle *first) } t->refit_cap = 0; + if (front->IsVirtual()) t->SetVirtual(); + t->SetArticulatedPart(); break; } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 4e3aae1d07..762b268554 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -722,6 +722,7 @@ static void AddRearEngineToMultiheadedTrain(Train *v) u->random_bits = VehicleRandomBits(); v->SetMultiheaded(); u->SetMultiheaded(); + if (v->IsVirtual()) u->SetVirtual(); v->SetNext(u); u->UpdatePosition(); @@ -4121,6 +4122,7 @@ Train* CmdBuildVirtualRailWagon(const Engine *e) v->SetWagon(); v->SetFreeWagon(); + v->SetVirtual(); v->cargo_type = e->GetDefaultCargoType(); v->cargo_cap = rvi->capacity; @@ -4204,6 +4206,7 @@ Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error) v->SetFrontEngine(); v->SetEngine(); + v->SetVirtual(); if (rvi->railveh_type == RAILVEH_MULTIHEAD) { AddRearEngineToMultiheadedTrain(v); From ccfd187677e0b28aeb366e0da3d050d921379eab Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 11 Jun 2019 01:59:50 +0100 Subject: [PATCH 09/12] TBTR: Avoid built virtual wagons which can't be attached being orphaned (cherry picked from commit f3daada67f20eaf41a340a38fcf69795960d309f) --- src/build_vehicle_gui.cpp | 2 +- src/train_cmd.cpp | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 972e5df705..d5393146e2 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1521,7 +1521,7 @@ struct BuildVehicleWindow : Window { } else { VehicleID target = (*(this->virtual_train_out))->GetLastUnit()->index; - DoCommandP(0, (1 << 21) | toadd->index, target, CMD_MOVE_RAIL_VEHICLE); + DoCommandP(0, (1 << 23) | (1 << 21) | toadd->index, target, CMD_MOVE_RAIL_VEHICLE); } InvalidateWindowClassesData(WC_CREATE_TEMPLATE); InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 762b268554..793e99d5ad 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1175,6 +1175,7 @@ static void NormaliseTrainHead(Train *head) * - p1 (bit 20) move all vehicles following the source vehicle * - p1 (bit 21) this is a virtual vehicle (for creating TemplateVehicles) * - p1 (bit 22) when moving a head vehicle, always reset the head state + * - p1 (bit 23) if move fails, and source vehicle is virtual, delete it * @param p2 what wagon to put the source wagon AFTER, XXX - INVALID_VEHICLE to make a new line * @param text unused * @return the cost of this operation or an error @@ -1185,12 +1186,21 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u VehicleID d = GB(p2, 0, 20); bool move_chain = HasBit(p1, 20); bool new_head = HasBit(p1, 22); + bool delete_failed_virtual = HasBit(p1, 23); Train *src = Train::GetIfValid(s); if (src == NULL) return CMD_ERROR; + auto check_on_failure = [&](CommandCost cost) -> CommandCost { + if (delete_failed_virtual && src->IsVirtual()) { + return DoCommand(src->tile, src->index | (1 << 21), 0, flags, CMD_SELL_VEHICLE); + } else { + return cost; + } + }; + CommandCost ret = CheckOwnership(src->owner); - if (ret.Failed()) return ret; + if (ret.Failed()) return check_on_failure(ret); /* Do not allow moving crashed vehicles inside the depot, it is likely to cause asserts later */ if (src->vehstatus & VS_CRASHED) return CMD_ERROR; @@ -1201,10 +1211,10 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u dst = src->IsEngine() ? NULL : FindGoodVehiclePos(src); } else { dst = Train::GetIfValid(d); - if (dst == NULL) return CMD_ERROR; + if (dst == nullptr) return check_on_failure(CMD_ERROR); CommandCost ret = CheckOwnership(dst->owner); - if (ret.Failed()) return ret; + if (ret.Failed()) return check_on_failure(ret); /* Do not allow appending to crashed vehicles, too */ if (dst->vehstatus & VS_CRASHED) return CMD_ERROR; @@ -1286,7 +1296,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u /* Restore the train we had. */ RestoreTrainBackup(original_src); RestoreTrainBackup(original_dst); - return ret; + return check_on_failure(ret); } } From 2b40007ca10f697d7d089fae44dbf0c4df36f5ea Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 3 Jul 2019 02:48:24 +0100 Subject: [PATCH 10/12] TBTR: Do not allocate virtual trains a unit number in NormaliseTrainHead (cherry picked from commit 8fefef9d19c8aa4d802c560adfb630eedc1fb08d) --- src/train_cmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 793e99d5ad..4e3ab4ce4f 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1161,7 +1161,7 @@ static void NormaliseTrainHead(Train *head) SetWindowWidgetDirty(WC_VEHICLE_VIEW, head->index, WID_VV_REFIT); /* If we don't have a unit number yet, set one. */ - if (head->unitnumber != 0) return; + if (head->unitnumber != 0 || HasBit(head->subtype, GVSF_VIRTUAL)) return; head->unitnumber = GetFreeUnitNumber(VEH_TRAIN); } From 858e90acb9b83ea1aa4e615737c91a4e8c513220 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 3 Jul 2019 03:24:03 +0100 Subject: [PATCH 11/12] TBTR: Avoid leaking virtual trains from template editing window When pressing OK to convert to template When (unsuccessfully) selling the head unit (cherry picked from commit 85e9a0195d620f7af2cda8ee6cfdf3c8266ae8b2) --- src/tbtr_template_gui_create.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index 26b7d9f32b..e843d10d11 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -241,7 +241,6 @@ public: case TCW_OK: { if (virtual_train != NULL) { DoCommandP(0, this->template_index, virtual_train->index, CMD_REPLACE_TEMPLATE_VEHICLE); - virtual_train = NULL; } else if (this->template_index != INVALID_VEHICLE) { DoCommandP(0, this->template_index, 0, CMD_DELETE_TEMPLATE_VEHICLE); } @@ -554,6 +553,7 @@ public: void RearrangeVirtualTrain() { + if (!virtual_train) return; virtual_train = virtual_train->First(); assert(HasBit(virtual_train->subtype, GVSF_VIRTUAL)); } @@ -600,6 +600,7 @@ void CcDeleteVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, Window* window = FindWindowById(WC_CREATE_TEMPLATE, 0); if (window) { + ((TemplateCreateWindow*)window)->RearrangeVirtualTrain(); window->InvalidateData(); } } From f1946af7075588e7dd8544c59828b2a5762b3c72 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 3 Jul 2019 22:22:50 +0100 Subject: [PATCH 12/12] TBTR: Delete leftover virtual trains on non-network client load --- src/saveload/vehicle_sl.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index bb3db3fe3e..3405066d38 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -368,6 +368,15 @@ void AfterLoadVehicles(bool part_of_load) v->SetServiceIntervalIsPercent(c->settings.vehicle.servint_ispercent); } } + + if (SlXvIsFeaturePresent(XSLFI_TEMPLATE_REPLACEMENT) && (_network_server || !_networking)) { + Train *t; + FOR_ALL_TRAINS(t) { + if (t->IsVirtual() && t->First() == t) { + delete t; + } + } + } } CheckValidVehicles();