diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -4,7 +4,6 @@ #include "stdafx.h" #include "company_func.h" -#include "vehicle_gui.h" #include "train.h" #include "rail.h" #include "command_func.h" @@ -18,6 +17,10 @@ #include "table/strings.h" +extern void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index); +extern void ChangeVehicleNews(VehicleID from_index, VehicleID to_index); +extern void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index); + /** Figure out if two engines got at least one type of cargo in common (refitting if needed) * @param engine_a one of the EngineIDs * @param engine_b the other EngineID @@ -332,8 +335,10 @@ static CommandCost CopyHeadSpecificThing /* Copy other things which cannot be copied by a command and which shall not stay resetted from the build vehicle command */ new_head->CopyVehicleConfigAndStatistics(old_head); - /* Switch vehicle windows to the new vehicle, so they are not closed when the old vehicle is sold */ + /* Switch vehicle windows/news to the new vehicle, so they are not closed/deleted when the old vehicle is sold */ + ChangeVehicleViewports(old_head->index, new_head->index); ChangeVehicleViewWindow(old_head->index, new_head->index); + ChangeVehicleNews(old_head->index, new_head->index); } return cost; diff --git a/src/news_func.h b/src/news_func.h --- a/src/news_func.h +++ b/src/news_func.h @@ -17,6 +17,15 @@ static inline void AddCompanyNewsItem(St AddNewsItem(string, subtype, NR_NONE, UINT32_MAX, NR_NONE, UINT32_MAX, cni); } +/** + * Adds a newsitem referencing a vehicle. + * + * @warning + * Be careful! + * Vehicles are a special case, as news are kept when vehicles are autoreplaced/renewed. + * You have to make sure, #ChangeVehicleNews catches the DParams of your message. + * This is NOT ensured by the references. + */ static inline void AddVehicleNewsItem(StringID string, NewsSubtype subtype, VehicleID vehicle, StationID station = INVALID_STATION) { AddNewsItem(string, subtype, NR_VEHICLE, vehicle, station == INVALID_STATION ? NR_NONE : NR_STATION, station); diff --git a/src/news_gui.cpp b/src/news_gui.cpp --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -673,6 +673,29 @@ void RemoveOldNewsItems() } } +/** + * Report a change in vehicle IDs (due to autoreplace) to affected vehicle news. + * @note Viewports of currently displayed news is changed via #ChangeVehicleViewports + * @param from_index the old vehicle ID + * @param to_index the new vehicle ID + */ +void ChangeVehicleNews(VehicleID from_index, VehicleID to_index) +{ + for (NewsItem *ni = _oldest_news; ni != NULL; ni = ni->next) { + if (ni->reftype1 == NR_VEHICLE && ni->ref1 == from_index) ni->ref1 = to_index; + if (ni->reftype2 == NR_VEHICLE && ni->ref2 == from_index) ni->ref2 = to_index; + + /* Oh noes :( + * Autoreplace is breaking the whole news-reference concept here, as we want to keep the news, + * but do not know which DParams to change. + * + * Currently only NS_ADVICE news have vehicle IDs in their DParams. + * And all NS_ADVICE news have the ID in param 0. + */ + if (ni->subtype == NS_ADVICE && ni->params[0] == from_index) ni->params[0] = to_index; + } +} + void NewsLoop() { /* no news item yet */ diff --git a/src/news_type.h b/src/news_type.h --- a/src/news_type.h +++ b/src/news_type.h @@ -68,6 +68,12 @@ enum NewsMode { /** * References to objects in news. + * + * @warning + * Be careful! + * Vehicles are a special case, as news are kept when vehicles are autoreplaced/renewed. + * You have to make sure, #ChangeVehicleNews catches the DParams of your message. + * This is NOT ensured by the references. */ enum NewsReferenceType { NR_NONE, ///< Empty reference diff --git a/src/vehicle_gui.h b/src/vehicle_gui.h --- a/src/vehicle_gui.h +++ b/src/vehicle_gui.h @@ -78,10 +78,6 @@ void ShowVehicleListWindow(CompanyID com void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, TileIndex depot_tile); -/* ChangeVehicleViewWindow() moves all windows for one vehicle to another vehicle. - * For ease of use it can be called with both Vehicle pointers and VehicleIDs. */ -void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index); - static inline uint GetVehicleListHeight(VehicleType type) { return (type == VEH_TRAIN || type == VEH_ROAD) ? 14 : 24; diff --git a/src/window.cpp b/src/window.cpp --- a/src/window.cpp +++ b/src/window.cpp @@ -2663,6 +2663,24 @@ void SetHScrollCount(Window *w, int num) if (num < w->hscroll.pos) w->hscroll.pos = num; } + +/** + * Switches viewports following vehicles, which get autoreplaced + * @param from_index the old vehicle ID + * @param to_index the new vehicle ID + */ +void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index) +{ + Window *w; + FOR_ALL_WINDOWS_FROM_BACK(w) { + if (w->viewport != NULL && w->viewport->follow_vehicle == from_index) { + w->viewport->follow_vehicle = to_index; + w->SetDirty(); + } + } +} + + /** * Relocate all windows to fit the new size of the game application screen * @param neww New width of the game application screen