From 77abb375ec1ac5412c2cfbf398f9622fce26a8a1 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 7 Jan 2025 22:50:02 +0100 Subject: [PATCH] Codechange: use std::variant instead of a custom version for news references --- src/aircraft_cmd.cpp | 10 +-- src/autoreplace_cmd.cpp | 10 +-- src/company_cmd.cpp | 2 +- src/crashlog.cpp | 4 +- src/disaster_vehicle.cpp | 2 +- src/engine.cpp | 2 +- src/industry_cmd.cpp | 10 +-- src/news_func.h | 33 ++++--- src/news_gui.cpp | 174 ++++++++++++++++++++++--------------- src/news_type.h | 19 ++-- src/order_cmd.cpp | 4 +- src/roadveh_cmd.cpp | 8 +- src/saveload/afterload.cpp | 2 +- src/ship_cmd.cpp | 4 +- src/station.cpp | 2 +- src/station_cmd.cpp | 2 +- src/subsidy.cpp | 32 +++---- src/subsidy_func.h | 2 +- src/town_cmd.cpp | 4 +- src/train_cmd.cpp | 6 +- src/vehicle.cpp | 16 ++-- src/vehicle_cmd.cpp | 2 +- 22 files changed, 197 insertions(+), 153 deletions(-) diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index bb6d344fec..f7a9bc8949 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -1357,7 +1357,7 @@ static void CrashAirplane(Aircraft *v) newstype = NT_ACCIDENT_OTHER; } - AddTileNewsItem(newsitem, newstype, vt, nullptr, st != nullptr ? st->index : INVALID_STATION); + AddTileNewsItem(newsitem, newstype, vt, st); ModifyStationRatingAround(vt, v->owner, -160, 30); if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v); @@ -1413,8 +1413,8 @@ static void AircraftEntersTerminal(Aircraft *v) AddVehicleNewsItem( STR_NEWS_FIRST_AIRCRAFT_ARRIVAL, (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, - v->index, - st->index + v, + st ); AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index)); Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index)); @@ -2064,7 +2064,7 @@ static void AircraftHandleDestTooFar(Aircraft *v, bool too_far) if (v->owner == _local_company) { /* Post a news message. */ SetDParam(0, v->index); - AddVehicleAdviceNewsItem(AdviceType::AircraftDestinationTooFar, STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v->index); + AddVehicleAdviceNewsItem(AdviceType::AircraftDestinationTooFar, STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v); } } return; @@ -2074,7 +2074,7 @@ static void AircraftHandleDestTooFar(Aircraft *v, bool too_far) /* Not too far anymore, clear flag and message. */ ClrBit(v->flags, VAF_DEST_TOO_FAR); SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); - DeleteVehicleNews(v->index, AdviceType::AircraftDestinationTooFar); + DeleteVehicleNews(v, AdviceType::AircraftDestinationTooFar); } } diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 31a131d487..874ba11f2c 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -34,7 +34,7 @@ #include "safeguards.h" extern void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index); -extern void ChangeVehicleNews(VehicleID from_index, VehicleID to_index); +extern void ChangeVehicleNews(const Vehicle *from, const Vehicle *to); extern void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index); /** @@ -334,8 +334,8 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic if (!IsValidCargoID(refit_cargo)) { if (!IsLocalCompany() || (flags & DC_EXEC) == 0) return CommandCost(); - VehicleID old_veh_id = (old_veh->type == VEH_TRAIN) ? Train::From(old_veh)->First()->index : old_veh->index; - SetDParam(0, old_veh_id); + const Vehicle *old_front = (old_veh->type == VEH_TRAIN) ? Train::From(old_veh)->First() : old_veh; + SetDParam(0, old_front->index); int order_id = GetIncompatibleRefitOrderIdForAutoreplace(old_veh, e); if (order_id != -1) { @@ -348,7 +348,7 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic SetDParam(2, CargoSpec::Get(old_veh->cargo_type)->name); } - AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, STR_NEWS_VEHICLE_AUTORENEW_FAILED, old_veh_id); + AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, STR_NEWS_VEHICLE_AUTORENEW_FAILED, old_front); return CommandCost(); } @@ -435,7 +435,7 @@ static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head, /* 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); + ChangeVehicleNews(old_head, new_head); } return cost; diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 1a6d96583c..ba5f6bf53c 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -431,7 +431,7 @@ set_name:; SetDParam(1, STR_NEWS_COMPANY_LAUNCH_DESCRIPTION); SetDParamStr(2, cni->company_name); SetDParam(3, t->index); - AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NT_COMPANY_INFO, NF_COMPANY, NR_TILE, c->last_build_coordinate.base(), NR_NONE, UINT32_MAX, std::move(cni)); + AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NT_COMPANY_INFO, NF_COMPANY, c->last_build_coordinate, {}, std::move(cni)); } return; } diff --git a/src/crashlog.cpp b/src/crashlog.cpp index 04129d7c3b..e684905ad4 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -18,6 +18,7 @@ #include "saveload/saveload.h" #include "screenshot.h" #include "network/network_survey.h" +#include "news_func.h" #include "news_gui.h" #include "fileio_func.h" #include "fileio_type.h" @@ -60,7 +61,8 @@ static void SurveyRecentNews(nlohmann::json &json) TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(news.date); json.push_back(fmt::format("({}-{:02}-{:02}) StringID: {}, Type: {}, Ref1: {}, {}, Ref2: {}, {}", ymd.year, ymd.month + 1, ymd.day, news.string_id, news.type, - news.reftype1, news.ref1, news.reftype2, news.ref2)); + news.ref1.index(), SerialiseNewsReference(news.ref1), + news.ref2.index(), SerialiseNewsReference(news.ref2))); if (++i > 32) break; } } diff --git a/src/disaster_vehicle.cpp b/src/disaster_vehicle.cpp index 063f48da37..380debc3e8 100644 --- a/src/disaster_vehicle.cpp +++ b/src/disaster_vehicle.cpp @@ -466,7 +466,7 @@ static bool DisasterTick_Aircraft(DisasterVehicle *v, uint16_t image_override, b DestructIndustry(i); SetDParam(0, i->town->index); - AddIndustryNewsItem(news_message, NT_ACCIDENT, i->index); + AddIndustryNewsItem(news_message, NT_ACCIDENT, i); if (_settings_client.sound.disaster) SndPlayTileFx(SND_12_EXPLOSION, i->location.tile); } } else if (v->state == 0) { diff --git a/src/engine.cpp b/src/engine.cpp index ad27071f62..e8f7400c37 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1131,7 +1131,7 @@ static void NewVehicleAvailable(Engine *e) if (!IsVehicleTypeDisabled(e->type, false) && !HasFlag(e->info.extra_flags, ExtraEngineFlags::NoNews)) { SetDParam(0, GetEngineCategoryName(index)); SetDParam(1, PackEngineNameDParam(index, EngineNameContext::PreviewNews)); - AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, NT_NEW_VEHICLES, NF_VEHICLE, NR_ENGINE, index); + AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, NT_NEW_VEHICLES, NF_VEHICLE, e); } /* Update the toolbar. */ diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 9d5d761639..8a41b4ce1f 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -193,7 +193,7 @@ Industry::~Industry() auto it = std::ranges::lower_bound(industries, this->index); industries.erase(it); - DeleteIndustryNews(this->index); + DeleteIndustryNews(this); CloseWindowById(WC_INDUSTRY_VIEW, this->index); DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index); @@ -1722,7 +1722,7 @@ static void AdvertiseIndustryOpening(const Industry *ind) } else { SetDParam(1, ind->town->index); } - AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind->index); + AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind); AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index)); Game::NewEvent(new ScriptEventIndustryOpen(ind->index)); } @@ -2199,7 +2199,7 @@ CommandCost CmdIndustrySetProduction(DoCommandFlag flags, IndustryID ind_id, uin } else { SetDParam(0, ind->index); } - AddIndustryNewsItem(str, nt, ind->index); + AddIndustryNewsItem(str, nt, ind); } } @@ -2780,7 +2780,7 @@ static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int AddIndustryNewsItem( percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH, nt, - ind->index + ind ); } @@ -2996,7 +2996,7 @@ static void ChangeIndustryProduction(Industry *i, bool monthly) if (closeit) { AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1)); } else { - AddIndustryNewsItem(str, nt, i->index); + AddIndustryNewsItem(str, nt, i); } } } diff --git a/src/news_func.h b/src/news_func.h index c2ab08f876..449c3e1b02 100644 --- a/src/news_func.h +++ b/src/news_func.h @@ -11,15 +11,12 @@ #define NEWS_FUNC_H #include "news_type.h" -#include "vehicle_type.h" -#include "station_type.h" -#include "industry_type.h" -void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1 = NR_NONE, uint32_t ref1 = UINT32_MAX, NewsReferenceType reftype2 = NR_NONE, uint32_t ref2 = UINT32_MAX, std::unique_ptr &&data = nullptr, AdviceType advice_type = AdviceType::Invalid); +void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReference ref1 = {}, NewsReference ref2 = {}, std::unique_ptr &&data = nullptr, AdviceType advice_type = AdviceType::Invalid); inline void AddCompanyNewsItem(StringID string, std::unique_ptr cni) { - AddNewsItem(string, NT_COMPANY_INFO, NF_COMPANY, NR_NONE, UINT32_MAX, NR_NONE, UINT32_MAX, std::move(cni)); + AddNewsItem(string, NT_COMPANY_INFO, NF_COMPANY, {}, {}, std::move(cni)); } /** @@ -27,9 +24,9 @@ inline void AddCompanyNewsItem(StringID string, std::unique_ptr &&data = nullptr, StationID station = INVALID_STATION) +inline void AddTileNewsItem(StringID string, NewsType type, TileIndex tile, const Station *station = nullptr) { - AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_TILE, tile.base(), station == INVALID_STATION ? NR_NONE : NR_STATION, station, std::move(data)); + AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, tile, station == nullptr ? NewsReference{} : station); } -inline void AddIndustryNewsItem(StringID string, NewsType type, IndustryID industry, std::unique_ptr &&data = nullptr) +inline void AddIndustryNewsItem(StringID string, NewsType type, const Industry *industry) { - AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_INDUSTRY, industry, NR_NONE, UINT32_MAX, std::move(data)); + AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, industry); } void NewsLoop(); @@ -57,9 +54,11 @@ void InitNewsItemStructs(); const NewsItem *GetStatusbarNews(); -void DeleteInvalidEngineNews(); -void DeleteVehicleNews(VehicleID vid, AdviceType advice_type = AdviceType::Invalid); -void DeleteStationNews(StationID sid); -void DeleteIndustryNews(IndustryID iid); +void DeleteEngineNews(); +void DeleteVehicleNews(const Vehicle *vehicle, AdviceType advice_type = AdviceType::Invalid); +void DeleteStationNews(const Station *station); +void DeleteIndustryNews(const Industry *industry); + +uint32_t SerialiseNewsReference(const NewsReference &reference); #endif /* NEWS_FUNC_H */ diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 1342d99d6d..d17659aeb6 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -81,21 +81,44 @@ const NewsContainer &GetNews() return _news; } +/** + * Encode a NewsReference for serialisation, e.g. for writing in the crash log. + * @param reference The reference to serialise. + * @return Reference serialised into a single uint32_t. + */ +uint32_t SerialiseNewsReference(const NewsReference &reference) +{ + struct visitor { + uint32_t operator()(const std::monostate &) { return 0; } + uint32_t operator()(const TileIndex &t) { return t.base(); } + uint32_t operator()(const Vehicle *v) { return v->index; } + uint32_t operator()(const Station *s) { return s->index; } + uint32_t operator()(const Industry *i) { return i->index; } + uint32_t operator()(const Town *t) { return t->index; } + uint32_t operator()(const Engine *e) { return e->index; } + }; + + return std::visit(visitor{}, reference); +} + /** * Get the position a news-reference is referencing. - * @param reftype The type of reference. - * @param ref The reference. + * @param reference The reference. * @return A tile for the referenced object, or INVALID_TILE if none. */ -static TileIndex GetReferenceTile(NewsReferenceType reftype, uint32_t ref) +static TileIndex GetReferenceTile(const NewsReference &reference) { - switch (reftype) { - case NR_TILE: return (TileIndex)ref; - case NR_STATION: return Station::Get((StationID)ref)->xy; - case NR_INDUSTRY: return Industry::Get((IndustryID)ref)->location.tile + TileDiffXY(1, 1); - case NR_TOWN: return Town::Get((TownID)ref)->xy; - default: return INVALID_TILE; - } + struct visitor { + TileIndex operator()(const std::monostate &) { return INVALID_TILE; } + TileIndex operator()(const TileIndex &t) { return t; } + TileIndex operator()(const Vehicle *) { return INVALID_TILE; } + TileIndex operator()(const Station *s) { return s->xy; } + TileIndex operator()(const Industry *i) { return i->location.tile + TileDiffXY(1, 1); } + TileIndex operator()(const Town *t) { return t->xy; } + TileIndex operator()(const Engine *) { return INVALID_TILE; } + }; + + return std::visit(visitor{}, reference); } /* Normal news items. */ @@ -366,8 +389,8 @@ struct NewsWindow : Window { if (&desc == &_company_news_desc) this->GetWidget(WID_N_TITLE)->SetString(static_cast(std::get(this->ni->params[0]))); NWidgetCore *nwid = this->GetWidget(WID_N_SHOW_GROUP); - if (ni->reftype1 == NR_VEHICLE && nwid != nullptr) { - const Vehicle *v = Vehicle::Get(ni->ref1); + if (std::holds_alternative(ni->ref1) && nwid != nullptr) { + const Vehicle *v = std::get(ni->ref1); switch (v->type) { case VEH_TRAIN: nwid->SetString(STR_TRAIN); @@ -391,10 +414,10 @@ struct NewsWindow : Window { /* Initialize viewport if it exists. */ NWidgetViewport *nvp = this->GetWidget(WID_N_VIEWPORT); if (nvp != nullptr) { - if (ni->reftype1 == NR_VEHICLE) { - nvp->InitializeViewport(this, static_cast(ni->ref1), ScaleZoomGUI(ZOOM_LVL_NEWS)); + if (std::holds_alternative(ni->ref1)) { + nvp->InitializeViewport(this, std::get(ni->ref1)->index, ScaleZoomGUI(ZOOM_LVL_NEWS)); } else { - nvp->InitializeViewport(this, GetReferenceTile(ni->reftype1, ni->ref1), ScaleZoomGUI(ZOOM_LVL_NEWS)); + nvp->InitializeViewport(this, GetReferenceTile(ni->ref1), ScaleZoomGUI(ZOOM_LVL_NEWS)); } if (this->ni->flags & NF_NO_TRANSPARENT) nvp->disp_flags |= ND_NO_TRANSPARENCY; if ((this->ni->flags & NF_INCOLOUR) == 0) { @@ -457,14 +480,13 @@ struct NewsWindow : Window { break; case WID_N_VEH_INFO: { - assert(this->ni->reftype1 == NR_ENGINE); - EngineID engine = this->ni->ref1; - str = GetEngineInfoString(engine); + const Engine *engine = std::get(this->ni->ref1); + str = GetEngineInfoString(engine->index); break; } case WID_N_SHOW_GROUP: - if (this->ni->reftype1 == NR_VEHICLE) { + if (std::holds_alternative(this->ni->ref1)) { Dimension d2 = GetStringBoundingBox(this->GetWidget(WID_N_SHOW_GROUP)->GetString()); d2.height += WidgetDimensions::scaled.captiontext.Vertical(); d2.width += WidgetDimensions::scaled.captiontext.Horizontal(); @@ -541,16 +563,14 @@ struct NewsWindow : Window { break; case WID_N_VEH_SPR: { - assert(this->ni->reftype1 == NR_ENGINE); - EngineID engine = this->ni->ref1; - DrawVehicleEngine(r.left, r.right, CenterBounds(r.left, r.right, 0), CenterBounds(r.top, r.bottom, 0), engine, GetEnginePalette(engine, _local_company), EIT_PREVIEW); + const Engine *engine = std::get(this->ni->ref1); + DrawVehicleEngine(r.left, r.right, CenterBounds(r.left, r.right, 0), CenterBounds(r.top, r.bottom, 0), engine->index, GetEnginePalette(engine->index, _local_company), EIT_PREVIEW); GfxFillRect(r.left, r.top, r.right, r.bottom, PALETTE_NEWSPAPER, FILLRECT_RECOLOUR); break; } case WID_N_VEH_INFO: { - assert(this->ni->reftype1 == NR_ENGINE); - EngineID engine = this->ni->ref1; - DrawStringMultiLine(r.left, r.right, r.top, r.bottom, GetEngineInfoString(engine), TC_FROMSTRING, SA_CENTER); + const Engine *engine = std::get(this->ni->ref1); + DrawStringMultiLine(r.left, r.right, r.top, r.bottom, GetEngineInfoString(engine->index), TC_FROMSTRING, SA_CENTER); break; } } @@ -566,9 +586,8 @@ struct NewsWindow : Window { break; case WID_N_CAPTION: - if (this->ni->reftype1 == NR_VEHICLE) { - const Vehicle *v = Vehicle::Get(this->ni->ref1); - ShowVehicleViewWindow(v); + if (std::holds_alternative(this->ni->ref1)) { + ShowVehicleViewWindow(std::get(this->ni->ref1)); } break; @@ -576,18 +595,17 @@ struct NewsWindow : Window { break; // Ignore clicks case WID_N_SHOW_GROUP: - if (this->ni->reftype1 == NR_VEHICLE) { - const Vehicle *v = Vehicle::Get(this->ni->ref1); - ShowCompanyGroupForVehicle(v); + if (std::holds_alternative(this->ni->ref1)) { + ShowCompanyGroupForVehicle(std::get(this->ni->ref1)); } break; default: - if (this->ni->reftype1 == NR_VEHICLE) { - const Vehicle *v = Vehicle::Get(this->ni->ref1); + if (std::holds_alternative(this->ni->ref1)) { + const Vehicle *v = std::get(this->ni->ref1); ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos); } else { - TileIndex tile1 = GetReferenceTile(this->ni->reftype1, this->ni->ref1); - TileIndex tile2 = GetReferenceTile(this->ni->reftype2, this->ni->ref2); + TileIndex tile1 = GetReferenceTile(this->ni->ref1); + TileIndex tile2 = GetReferenceTile(this->ni->ref2); if (_ctrl_pressed) { if (tile1 != INVALID_TILE) ShowExtraViewportWindow(tile1); if (tile2 != INVALID_TILE) ShowExtraViewportWindow(tile2); @@ -607,8 +625,8 @@ struct NewsWindow : Window { NWidgetViewport *nvp = this->GetWidget(WID_N_VIEWPORT); nvp->UpdateViewportCoordinates(this); - if (ni->reftype1 != NR_VEHICLE) { - ScrollWindowToTile(GetReferenceTile(ni->reftype1, ni->ref1), this, true); // Re-center viewport. + if (!std::holds_alternative(ni->ref1)) { + ScrollWindowToTile(GetReferenceTile(ni->ref1), this, true); // Re-center viewport. } } @@ -677,16 +695,15 @@ private: StringID GetNewVehicleMessageString(WidgetID widget) const { - assert(this->ni->reftype1 == NR_ENGINE); - EngineID engine = this->ni->ref1; + const Engine *engine = std::get(this->ni->ref1); switch (widget) { case WID_N_VEH_TITLE: - SetDParam(0, GetEngineCategoryName(engine)); + SetDParam(0, GetEngineCategoryName(engine->index)); return STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE; case WID_N_VEH_NAME: - SetDParam(0, PackEngineNameDParam(engine, EngineNameContext::PreviewNews)); + SetDParam(0, PackEngineNameDParam(engine->index, EngineNameContext::PreviewNews)); return STR_NEWS_NEW_VEHICLE_TYPE; default: @@ -865,17 +882,15 @@ static std::list::iterator DeleteNewsItem(std::list::iterato * @param string_id String to display. * @param type The type of news. * @param flags Flags related to how to display the news. - * @param reftype1 Type of ref1. * @param ref1 Reference 1 to some object: Used for a possible viewport, scrolling after clicking on the news, and for deleting the news when the object is deleted. - * @param reftype2 Type of ref2. * @param ref2 Reference 2 to some object: Used for scrolling after clicking on the news, and for deleting the news when the object is deleted. * @param data Pointer to data that must be released once the news message is cleared. * @param advice_type Sub-type in case the news type is #NT_ADVICE. * * @see NewsSubtype */ -NewsItem::NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, std::unique_ptr &&data, AdviceType advice_type) : - string_id(string_id), date(TimerGameCalendar::date), economy_date(TimerGameEconomy::date), type(type), advice_type(advice_type), flags(flags), reftype1(reftype1), reftype2(reftype2), ref1(ref1), ref2(ref2), data(std::move(data)) +NewsItem::NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReference ref1, NewsReference ref2, std::unique_ptr &&data, AdviceType advice_type) : + string_id(string_id), date(TimerGameCalendar::date), economy_date(TimerGameEconomy::date), type(type), advice_type(advice_type), flags(flags), ref1(ref1), ref2(ref2), data(std::move(data)) { /* show this news message in colour? */ if (TimerGameCalendar::year >= _settings_client.gui.coloured_news_year) this->flags |= NF_INCOLOUR; @@ -887,21 +902,19 @@ NewsItem::NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsRefere * @param string String to display * @param type news category * @param flags display flags for the news - * @param reftype1 Type of ref1 * @param ref1 Reference 1 to some object: Used for a possible viewport, scrolling after clicking on the news, and for deleting the news when the object is deleted. - * @param reftype2 Type of ref2 * @param ref2 Reference 2 to some object: Used for scrolling after clicking on the news, and for deleting the news when the object is deleted. * @param data Pointer to data that must be released once the news message is cleared. * @param advice_type Sub-type in case the news type is #NT_ADVICE. * * @see NewsSubtype */ -void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, std::unique_ptr &&data, AdviceType advice_type) +void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReference ref1, NewsReference ref2, std::unique_ptr &&data, AdviceType advice_type) { if (_game_mode == GM_MENU) return; /* Create new news item node */ - _news.emplace_front(string, type, flags, reftype1, ref1, reftype2, ref2, std::move(data), advice_type); + _news.emplace_front(string, type, flags, ref1, ref2, std::move(data), advice_type); /* Keep the number of stored news items to a managable number */ if (std::size(_news) > MAX_NEWS_AMOUNT) { @@ -929,30 +942,37 @@ CommandCost CmdCustomNewsItem(DoCommandFlag flags, NewsType type, NewsReferenceT if (type >= NT_END) return CMD_ERROR; if (text.empty()) return CMD_ERROR; + NewsReference news_reference{}; switch (reftype1) { case NR_NONE: break; case NR_TILE: if (!IsValidTile(reference)) return CMD_ERROR; + news_reference = TileIndex{reference}; break; case NR_VEHICLE: if (!Vehicle::IsValidID(reference)) return CMD_ERROR; + news_reference = Vehicle::Get(reference); break; case NR_STATION: if (!Station::IsValidID(reference)) return CMD_ERROR; + news_reference = Station::Get(reference); break; case NR_INDUSTRY: if (!Industry::IsValidID(reference)) return CMD_ERROR; + news_reference = Industry::Get(reference); break; case NR_TOWN: if (!Town::IsValidID(reference)) return CMD_ERROR; + news_reference = Town::Get(reference); break; case NR_ENGINE: if (!Engine::IsValidID(reference)) return CMD_ERROR; + news_reference = Engine::Get(reference); break; default: return CMD_ERROR; @@ -962,7 +982,7 @@ CommandCost CmdCustomNewsItem(DoCommandFlag flags, NewsType type, NewsReferenceT if (flags & DC_EXEC) { SetDParamStr(0, text); - AddNewsItem(STR_NEWS_CUSTOM_ITEM, type, NF_NORMAL, reftype1, reference, NR_NONE, UINT32_MAX); + AddNewsItem(STR_NEWS_CUSTOM_ITEM, type, NF_NORMAL, news_reference); } return CommandCost(); @@ -991,28 +1011,40 @@ void DeleteNews(Tpredicate predicate) if (dirty) InvalidateWindowData(WC_MESSAGE_HISTORY, 0); } +template +static bool IsReferenceObject(const NewsReference &reference, const T *object) +{ + return std::holds_alternative(reference) && std::get(reference) == object; +} + +template +static bool HasReferenceObject(const NewsItem &ni, const T *object) +{ + return IsReferenceObject(ni.ref1, object) || IsReferenceObject(ni.ref2, object); +} + /** * Delete news with a given advice type about a vehicle. * When the advice_type is #AdviceType::Invalid all news about the vehicle gets deleted. - * @param vid The vehicle to remove the news for. + * @param v The vehicle to remove the news for. * @param advice_type The advice type to remove for. */ -void DeleteVehicleNews(VehicleID vid, AdviceType advice_type) +void DeleteVehicleNews(const Vehicle *v, AdviceType advice_type) { DeleteNews([&](const auto &ni) { - return ((ni.reftype1 == NR_VEHICLE && ni.ref1 == vid) || (ni.reftype2 == NR_VEHICLE && ni.ref2 == vid)) && (advice_type == AdviceType::Invalid || ni.advice_type == advice_type); + return HasReferenceObject(ni, v) && (advice_type == AdviceType::Invalid || ni.advice_type == advice_type); }); } /** * Remove news regarding given station so there are no 'unknown station now accepts Mail' * or 'First train arrived at unknown station' news items. - * @param sid station to remove news about + * @param s station to remove news about */ -void DeleteStationNews(StationID sid) +void DeleteStationNews(const Station *s) { DeleteNews([&](const auto &ni) { - return (ni.reftype1 == NR_STATION && ni.ref1 == sid) || (ni.reftype2 == NR_STATION && ni.ref2 == sid); + return HasReferenceObject(ni, s); }); } @@ -1020,21 +1052,20 @@ void DeleteStationNews(StationID sid) * Remove news regarding given industry * @param iid industry to remove news about */ -void DeleteIndustryNews(IndustryID iid) +void DeleteIndustryNews(const Industry *i) { DeleteNews([&](const auto &ni) { - return (ni.reftype1 == NR_INDUSTRY && ni.ref1 == iid) || (ni.reftype2 == NR_INDUSTRY && ni.ref2 == iid); + return HasReferenceObject(ni, i); }); } /** - * Remove engine announcements for invalid engines. + * Remove engine announcements. */ -void DeleteInvalidEngineNews() +void DeleteEngineNews() { DeleteNews([](const auto &ni) { - return (ni.reftype1 == NR_ENGINE && (!Engine::IsValidID(ni.ref1) || !Engine::Get(ni.ref1)->IsEnabled())) || - (ni.reftype2 == NR_ENGINE && (!Engine::IsValidID(ni.ref2) || !Engine::Get(ni.ref2)->IsEnabled())); + return std::holds_alternative(ni.ref1) || std::holds_alternative(ni.ref2); }); } @@ -1045,18 +1076,25 @@ static void RemoveOldNewsItems() }); } +template +static void ChangeObject(NewsReference reference, const T *from, const T *to) +{ + if (!std::holds_alternative(reference)) return; + if (std::get(reference) == from) reference = to; +} + /** * 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 + * @param from the old vehicle + * @param to the new vehicle */ -void ChangeVehicleNews(VehicleID from_index, VehicleID to_index) +void ChangeVehicleNews(const Vehicle *from, const Vehicle *to) { for (auto &ni : _news) { - 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; - if (ni.flags & NF_VEHICLE_PARAM0 && std::get(ni.params[0]) == from_index) ni.params[0] = to_index; + ChangeObject(ni.ref1, from, to); + ChangeObject(ni.ref2, from, to); + if (ni.flags & NF_VEHICLE_PARAM0 && std::get(ni.params[0]) == from->index) ni.params[0] = to->index; } } diff --git a/src/news_type.h b/src/news_type.h index 7f642a5425..2f71e20ba8 100644 --- a/src/news_type.h +++ b/src/news_type.h @@ -11,11 +11,16 @@ #define NEWS_TYPE_H #include "core/enum_type.hpp" +#include "engine_type.h" #include "gfx_type.h" +#include "industry_type.h" +#include "sound_type.h" +#include "station_type.h" +#include "strings_type.h" #include "timer/timer_game_calendar.h" #include "timer/timer_game_economy.h" -#include "strings_type.h" -#include "sound_type.h" +#include "town_type.h" +#include "vehicle_type.h" /** * Type of news. @@ -74,6 +79,8 @@ enum NewsReferenceType : uint8_t { NR_ENGINE, ///< Reference engine. }; +using NewsReference = std::variant; + /** * Various OR-able news-item flags. * @note #NF_INCOLOUR is set automatically if needed. @@ -148,16 +155,14 @@ struct NewsItem { AdviceType advice_type; ///< The type of advice, to be able to remove specific advices later on. NewsFlag flags; ///< NewsFlags bits @see NewsFlag - NewsReferenceType reftype1; ///< Type of ref1 - NewsReferenceType reftype2; ///< Type of ref2 - uint32_t ref1; ///< Reference 1 to some object: Used for a possible viewport, scrolling after clicking on the news, and for deleting the news when the object is deleted. - uint32_t ref2; ///< Reference 2 to some object: Used for scrolling after clicking on the news, and for deleting the news when the object is deleted. + NewsReference ref1; ///< Reference 1 to some object: Used for a possible viewport, scrolling after clicking on the news, and for deleting the news when the object is deleted. + NewsReference ref2; ///< Reference 2 to some object: Used for scrolling after clicking on the news, and for deleting the news when the object is deleted. std::unique_ptr data; ///< Custom data for the news item that will be deallocated (deleted) when the news item has reached its end. std::vector params; ///< Parameters for string resolving. - NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, std::unique_ptr &&data, AdviceType advice_type); + NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReference ref1, NewsReference ref2, std::unique_ptr &&data, AdviceType advice_type); }; /** diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 2bcba9ca4a..e134e3ca78 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -626,7 +626,7 @@ static inline bool OrderGoesToStation(const Vehicle *v, const Order *o) */ static void DeleteOrderWarnings(const Vehicle *v) { - DeleteVehicleNews(v->index, AdviceType::Order); + DeleteVehicleNews(v, AdviceType::Order); } /** @@ -1768,7 +1768,7 @@ void CheckOrders(const Vehicle *v) if (message == INVALID_STRING_ID) return; SetDParam(0, v->index); - AddVehicleAdviceNewsItem(AdviceType::Order, message, v->index); + AddVehicleAdviceNewsItem(AdviceType::Order, message, v); } } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index b54c0f9d7f..e0341b742b 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -693,8 +693,8 @@ static void RoadVehArrivesAt(const RoadVehicle *v, Station *st) AddVehicleNewsItem( RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL, (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, - v->index, - st->index + v, + st ); AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index)); Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index)); @@ -707,8 +707,8 @@ static void RoadVehArrivesAt(const RoadVehicle *v, Station *st) AddVehicleNewsItem( RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL, (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, - v->index, - st->index + v, + st ); AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index)); Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index)); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 87e4e21240..765fa3f87b 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -3402,7 +3402,7 @@ void ReloadNewGRFData() /* Check and update house and town values */ UpdateHousesAndTowns(); /* Delete news referring to no longer existing entities */ - DeleteInvalidEngineNews(); + DeleteEngineNews(); /* Update livery selection windows */ for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) InvalidateWindowData(WC_COMPANY_COLOUR, i); /* Update company infrastructure counts. */ diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index b4ac67cb08..b562905378 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -475,8 +475,8 @@ static void ShipArrivesAt(const Vehicle *v, Station *st) AddVehicleNewsItem( STR_NEWS_FIRST_SHIP_ARRIVAL, (v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, - v->index, - st->index + v, + st ); AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index)); Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index)); diff --git a/src/station.cpp b/src/station.cpp index d822b10324..0745461e63 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -148,7 +148,7 @@ Station::~Station() RemoveOrderFromAllVehicles(OT_GOTO_STATION, this->index); /* Remove all news items */ - DeleteStationNews(this->index); + DeleteStationNews(this); for (GoodsEntry &ge : this->goods) { if (!ge.HasData()) continue; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index ff639c4fb5..2674737adb 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -534,7 +534,7 @@ static void ShowRejectOrAcceptNews(const Station *st, CargoTypes cargoes, bool r SetDParam(0, st->index); SetDParam(1, cargoes); StringID msg = reject ? STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_LIST : STR_NEWS_STATION_NOW_ACCEPTS_CARGO_LIST; - AddNewsItem(msg, NT_ACCEPTANCE, NF_INCOLOUR | NF_SMALL, NR_STATION, st->index); + AddNewsItem(msg, NT_ACCEPTANCE, NF_INCOLOUR | NF_SMALL, st); } /** diff --git a/src/subsidy.cpp b/src/subsidy.cpp index aaf85aeb62..92c05906fe 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -51,13 +51,13 @@ void Subsidy::AwardTo(CompanyID company) std::string company_name = GetString(STR_COMPANY_NAME); /* Add a news item */ - std::pair reftype = SetupSubsidyDecodeParam(this, SubsidyDecodeParamType::NewsAwarded, 1); + std::pair references = SetupSubsidyDecodeParam(this, SubsidyDecodeParamType::NewsAwarded, 1); SetDParamStr(0, company_name); AddNewsItem( STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier, NT_SUBSIDIES, NF_NORMAL, - reftype.first, this->src, reftype.second, this->dst + references.first, references.second ); AI::BroadcastNewEvent(new ScriptEventSubsidyAwarded(this->index)); Game::NewEvent(new ScriptEventSubsidyAwarded(this->index)); @@ -72,10 +72,10 @@ void Subsidy::AwardTo(CompanyID company) * @param parameter_offset The location/index in the String DParams to start decoding the subsidy's parameters. Defaults to 0. * @return Reference of the subsidy in the news system. */ -std::pair SetupSubsidyDecodeParam(const Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset) +std::pair SetupSubsidyDecodeParam(const Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset) { - NewsReferenceType reftype1 = NR_NONE; - NewsReferenceType reftype2 = NR_NONE; + NewsReference reference2{}; + NewsReference reference1{}; /* Always use the plural form of the cargo name - trying to decide between plural or singular causes issues for translations */ const CargoSpec *cs = CargoSpec::Get(s->cargo_type); @@ -83,11 +83,11 @@ std::pair SetupSubsidyDecodeParam(const Su switch (s->src_type) { case SourceType::Industry: - reftype1 = NR_INDUSTRY; + reference1 = Industry::Get(s->src); SetDParam(parameter_offset + 1, STR_INDUSTRY_NAME); break; case SourceType::Town: - reftype1 = NR_TOWN; + reference1 = Town::Get(s->src); SetDParam(parameter_offset + 1, STR_TOWN_NAME); break; default: NOT_REACHED(); @@ -96,11 +96,11 @@ std::pair SetupSubsidyDecodeParam(const Su switch (s->dst_type) { case SourceType::Industry: - reftype2 = NR_INDUSTRY; + reference2 = Industry::Get(s->dst); SetDParam(parameter_offset + 4, STR_INDUSTRY_NAME); break; case SourceType::Town: - reftype2 = NR_TOWN; + reference2 = Town::Get(s->dst); SetDParam(parameter_offset + 4, STR_TOWN_NAME); break; default: NOT_REACHED(); @@ -112,7 +112,7 @@ std::pair SetupSubsidyDecodeParam(const Su SetDParam(parameter_offset + 7, _settings_game.difficulty.subsidy_duration); } - return std::pair(reftype1, reftype2); + return {reference1, reference2}; } /** @@ -221,8 +221,8 @@ void CreateSubsidy(CargoID cid, SourceType src_type, SourceID src, SourceType ds s->remaining = SUBSIDY_OFFER_MONTHS; s->awarded = INVALID_COMPANY; - std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsOffered); - AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); + std::pair references = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsOffered); + AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NT_SUBSIDIES, NF_NORMAL, references.first, references.second); SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC); SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST); AI::BroadcastNewEvent(new ScriptEventSubsidyOffer(s->index)); @@ -487,14 +487,14 @@ static IntervalTimer _economy_subsidies_monthly({TimerGameEcon for (Subsidy *s : Subsidy::Iterate()) { if (--s->remaining == 0) { if (!s->IsAwarded()) { - std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn); - AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); + std::pair references = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn); + AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NT_SUBSIDIES, NF_NORMAL, references.first, references.second); AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index)); Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index)); } else { if (s->awarded == _local_company) { - std::pair reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn); - AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst); + std::pair references = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn); + AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NT_SUBSIDIES, NF_NORMAL, references.first, references.second); } AI::BroadcastNewEvent(new ScriptEventSubsidyExpired(s->index)); Game::NewEvent(new ScriptEventSubsidyExpired(s->index)); diff --git a/src/subsidy_func.h b/src/subsidy_func.h index 89bf0f1fe2..60e6cfc364 100644 --- a/src/subsidy_func.h +++ b/src/subsidy_func.h @@ -17,7 +17,7 @@ #include "news_type.h" #include "subsidy_base.h" -std::pair SetupSubsidyDecodeParam(const struct Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset = 0); +std::pair SetupSubsidyDecodeParam(const struct Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset = 0); void DeleteSubsidyWith(SourceType type, SourceID index); bool CheckSubsidised(CargoID cargo_type, CompanyID company, SourceType src_type, SourceID src, const Station *st); void RebuildSubsidisedSourceAndDestinationCache(); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 28259aed75..fe44d64e19 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -3379,7 +3379,7 @@ static CommandCost TownActionRoadRebuild(Town *t, DoCommandFlag flags) AddNewsItem( TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_ROAD_REBUILDING_MINUTES : STR_NEWS_ROAD_REBUILDING_MONTHS, - NT_GENERAL, NF_NORMAL, NR_TOWN, t->index, NR_NONE, UINT32_MAX); + NT_GENERAL, NF_NORMAL, t); AI::BroadcastNewEvent(new ScriptEventRoadReconstruction((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); Game::NewEvent(new ScriptEventRoadReconstruction((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); } @@ -3534,7 +3534,7 @@ static CommandCost TownActionBuyRights(Town *t, DoCommandFlag flags) SetDParam(1, TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MINUTES : STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MONTHS); SetDParam(2, t->index); SetDParamStr(3, cni->company_name); - AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NT_GENERAL, NF_COMPANY, NR_TOWN, t->index, NR_NONE, UINT32_MAX, std::move(cni)); + AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NT_GENERAL, NF_COMPANY, t, {}, std::move(cni)); AI::BroadcastNewEvent(new ScriptEventExclusiveTransportRights((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); Game::NewEvent(new ScriptEventExclusiveTransportRights((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 26f62869ee..b72557882e 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -3012,8 +3012,8 @@ static void TrainEnterStation(Train *v, StationID station) AddVehicleNewsItem( STR_NEWS_FIRST_TRAIN_ARRIVAL, v->owner == _local_company ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER, - v->index, - st->index + v, + st ); AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index)); Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index)); @@ -4009,7 +4009,7 @@ static bool TrainLocoHandler(Train *v, bool mode) /* Show message to player. */ if (_settings_client.gui.lost_vehicle_warn && v->owner == _local_company) { SetDParam(0, v->index); - AddVehicleAdviceNewsItem(AdviceType::TrainStuck, STR_NEWS_TRAIN_IS_STUCK, v->index); + AddVehicleAdviceNewsItem(AdviceType::TrainStuck, STR_NEWS_TRAIN_IS_STUCK, v); } v->wait_counter = 0; } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index a9983a5f4d..9aff045a74 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -799,7 +799,7 @@ void Vehicle::HandlePathfindingResult(bool path_found) SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP); InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type)); /* Delete the news item. */ - DeleteVehicleNews(this->index, AdviceType::VehicleLost); + DeleteVehicleNews(this, AdviceType::VehicleLost); return; } @@ -818,7 +818,7 @@ void Vehicle::HandlePathfindingResult(bool path_found) AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index)); if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) { SetDParam(0, this->index); - AddVehicleAdviceNewsItem(AdviceType::VehicleLost, STR_NEWS_VEHICLE_IS_LOST, this->index); + AddVehicleAdviceNewsItem(AdviceType::VehicleLost, STR_NEWS_VEHICLE_IS_LOST, this); } } @@ -909,7 +909,7 @@ Vehicle::~Vehicle() UpdateVehicleTileHash(this, true); UpdateVehicleViewportHash(this, INVALID_COORD, 0, this->sprite_cache.old_coord.left, this->sprite_cache.old_coord.top); if (this->type != VEH_EFFECT) { - DeleteVehicleNews(this->index); + DeleteVehicleNews(this); DeleteNewGRFInspectWindow(GetGrfSpecFeature(this->type), this->index); } } @@ -1111,7 +1111,7 @@ void CallVehicleTicks() SetDParam(0, v->index); SetDParam(1, error_message); - AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, message, v->index); + AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, message, v); } cur_company.Restore(); @@ -1478,7 +1478,7 @@ void AgeVehicle(Vehicle *v) } SetDParam(0, v->index); - AddVehicleAdviceNewsItem(AdviceType::VehicleOld, str, v->index); + AddVehicleAdviceNewsItem(AdviceType::VehicleOld, str, v); } /** @@ -1634,7 +1634,7 @@ void VehicleEnterDepot(Vehicle *v) if (v->owner == _local_company) { /* Notify the user that we stopped the vehicle */ SetDParam(0, v->index); - AddVehicleAdviceNewsItem(AdviceType::RefitFailed, STR_NEWS_ORDER_REFIT_FAILED, v->index); + AddVehicleAdviceNewsItem(AdviceType::RefitFailed, STR_NEWS_ORDER_REFIT_FAILED, v); } } else if (cost.GetCost() != 0) { v->profit_this_year -= cost.GetCost() << 8; @@ -1664,7 +1664,7 @@ void VehicleEnterDepot(Vehicle *v) /* Announce that the vehicle is waiting to players and AIs. */ if (v->owner == _local_company) { SetDParam(0, v->index); - AddVehicleAdviceNewsItem(AdviceType::VehicleWaiting, STR_NEWS_TRAIN_IS_WAITING + v->type, v->index); + AddVehicleAdviceNewsItem(AdviceType::VehicleWaiting, STR_NEWS_TRAIN_IS_WAITING + v->type, v); } AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index)); } @@ -3029,7 +3029,7 @@ static IntervalTimer _economy_vehicles_yearly({TimerGameEconom SetDParam(1, profit); AddVehicleAdviceNewsItem(AdviceType::VehicleUnprofitable, TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD : STR_NEWS_VEHICLE_UNPROFITABLE_YEAR, - v->index); + v); } AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index)); } diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index d9905747a1..4d08e9d612 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -629,7 +629,7 @@ CommandCost CmdStartStopVehicle(DoCommandFlag flags, VehicleID veh_id, bool eval } if (flags & DC_EXEC) { - if (v->IsStoppedInDepot() && (flags & DC_AUTOREPLACE) == 0) DeleteVehicleNews(veh_id, AdviceType::VehicleWaiting); + if (v->IsStoppedInDepot() && (flags & DC_AUTOREPLACE) == 0) DeleteVehicleNews(v, AdviceType::VehicleWaiting); v->vehstatus ^= VS_STOPPED; if (v->type != VEH_TRAIN) v->cur_speed = 0; // trains can stop 'slowly'