1
0
Fork 0

Codechange: use std::variant instead of a custom version for news references

pull/13297/head
Rubidium 2025-01-07 22:50:02 +01:00
parent 4db0af99a7
commit 77abb375ec
22 changed files with 197 additions and 153 deletions

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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. */

View File

@ -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);
}
}
}

View File

@ -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<NewsAllocatedData> &&data = nullptr, AdviceType advice_type = AdviceType::Invalid);
void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReference ref1 = {}, NewsReference ref2 = {}, std::unique_ptr<NewsAllocatedData> &&data = nullptr, AdviceType advice_type = AdviceType::Invalid);
inline void AddCompanyNewsItem(StringID string, std::unique_ptr<CompanyNewsInformation> 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<CompanyNewsInfor
*
* @warning The DParams may not reference the vehicle due to autoreplace stuff. See AddVehicleAdviceNewsItem for how that can be done.
*/
inline void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle, StationID station = INVALID_STATION)
inline void AddVehicleNewsItem(StringID string, NewsType type, const Vehicle *vehicle, const Station *station = nullptr)
{
AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_VEHICLE, vehicle, station == INVALID_STATION ? NR_NONE : NR_STATION, station);
AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, vehicle, station == nullptr ? NewsReference{} : station);
}
/**
@ -37,19 +34,19 @@ inline void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle
*
* @warning DParam 0 must reference the vehicle!
*/
inline void AddVehicleAdviceNewsItem(AdviceType advice_type, StringID string, VehicleID vehicle)
inline void AddVehicleAdviceNewsItem(AdviceType advice_type, StringID string, const Vehicle *vehicle)
{
AddNewsItem(string, NT_ADVICE, NF_INCOLOUR | NF_SMALL | NF_VEHICLE_PARAM0, NR_VEHICLE, vehicle, NR_NONE, {}, nullptr, advice_type);
AddNewsItem(string, NT_ADVICE, NF_INCOLOUR | NF_SMALL | NF_VEHICLE_PARAM0, vehicle, {}, nullptr, advice_type);
}
inline void AddTileNewsItem(StringID string, NewsType type, TileIndex tile, std::unique_ptr<NewsAllocatedData> &&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<NewsAllocatedData> &&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 */

View File

@ -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<NWidgetCore>(WID_N_TITLE)->SetString(static_cast<StringID>(std::get<uint64_t>(this->ni->params[0])));
NWidgetCore *nwid = this->GetWidget<NWidgetCore>(WID_N_SHOW_GROUP);
if (ni->reftype1 == NR_VEHICLE && nwid != nullptr) {
const Vehicle *v = Vehicle::Get(ni->ref1);
if (std::holds_alternative<const Vehicle *>(ni->ref1) && nwid != nullptr) {
const Vehicle *v = std::get<const Vehicle *>(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<NWidgetViewport>(WID_N_VIEWPORT);
if (nvp != nullptr) {
if (ni->reftype1 == NR_VEHICLE) {
nvp->InitializeViewport(this, static_cast<VehicleID>(ni->ref1), ScaleZoomGUI(ZOOM_LVL_NEWS));
if (std::holds_alternative<const Vehicle *>(ni->ref1)) {
nvp->InitializeViewport(this, std::get<const Vehicle *>(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<const Engine *>(this->ni->ref1);
str = GetEngineInfoString(engine->index);
break;
}
case WID_N_SHOW_GROUP:
if (this->ni->reftype1 == NR_VEHICLE) {
if (std::holds_alternative<const Vehicle *>(this->ni->ref1)) {
Dimension d2 = GetStringBoundingBox(this->GetWidget<NWidgetCore>(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<const Engine *>(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<const Engine *>(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<const Vehicle *>(this->ni->ref1)) {
ShowVehicleViewWindow(std::get<const Vehicle *>(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<const Vehicle *>(this->ni->ref1)) {
ShowCompanyGroupForVehicle(std::get<const Vehicle *>(this->ni->ref1));
}
break;
default:
if (this->ni->reftype1 == NR_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->ni->ref1);
if (std::holds_alternative<const Vehicle *>(this->ni->ref1)) {
const Vehicle *v = std::get<const Vehicle *>(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<NWidgetViewport>(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<const Vehicle *>(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<const Engine *>(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<NewsItem>::iterator DeleteNewsItem(std::list<NewsItem>::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<NewsAllocatedData> &&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<NewsAllocatedData> &&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<NewsAllocatedData> &&data, AdviceType advice_type)
void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReference ref1, NewsReference ref2, std::unique_ptr<NewsAllocatedData> &&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 <typename T>
static bool IsReferenceObject(const NewsReference &reference, const T *object)
{
return std::holds_alternative<const T *>(reference) && std::get<const T *>(reference) == object;
}
template <typename T>
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<const Engine *>(ni.ref1) || std::holds_alternative<const Engine *>(ni.ref2);
});
}
@ -1045,18 +1076,25 @@ static void RemoveOldNewsItems()
});
}
template <typename T>
static void ChangeObject(NewsReference reference, const T *from, const T *to)
{
if (!std::holds_alternative<const T *>(reference)) return;
if (std::get<const T *>(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<uint64_t>(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<uint64_t>(ni.params[0]) == from->index) ni.params[0] = to->index;
}
}

View File

@ -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<std::monostate, TileIndex, const Vehicle *, const Station *, const Industry *, const Town *, const Engine *>;
/**
* 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<NewsAllocatedData> data; ///< Custom data for the news item that will be deallocated (deleted) when the news item has reached its end.
std::vector<StringParameterData> 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<NewsAllocatedData> &&data, AdviceType advice_type);
NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReference ref1, NewsReference ref2, std::unique_ptr<NewsAllocatedData> &&data, AdviceType advice_type);
};
/**

View File

@ -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);
}
}

View File

@ -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));

View File

@ -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. */

View File

@ -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));

View File

@ -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;

View File

@ -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);
}
/**

View File

@ -51,13 +51,13 @@ void Subsidy::AwardTo(CompanyID company)
std::string company_name = GetString(STR_COMPANY_NAME);
/* Add a news item */
std::pair<NewsReferenceType, NewsReferenceType> reftype = SetupSubsidyDecodeParam(this, SubsidyDecodeParamType::NewsAwarded, 1);
std::pair<NewsReference, NewsReference> 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<NewsReferenceType, NewsReferenceType> SetupSubsidyDecodeParam(const Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset)
std::pair<NewsReference, NewsReference> 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<NewsReferenceType, NewsReferenceType> 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<NewsReferenceType, NewsReferenceType> 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<NewsReferenceType, NewsReferenceType> SetupSubsidyDecodeParam(const Su
SetDParam(parameter_offset + 7, _settings_game.difficulty.subsidy_duration);
}
return std::pair<NewsReferenceType, NewsReferenceType>(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<NewsReferenceType, NewsReferenceType> 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<NewsReference, NewsReference> 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<TimerGameEconomy> _economy_subsidies_monthly({TimerGameEcon
for (Subsidy *s : Subsidy::Iterate()) {
if (--s->remaining == 0) {
if (!s->IsAwarded()) {
std::pair<NewsReferenceType, NewsReferenceType> 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<NewsReference, NewsReference> 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<NewsReferenceType, NewsReferenceType> 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<NewsReference, NewsReference> 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));

View File

@ -17,7 +17,7 @@
#include "news_type.h"
#include "subsidy_base.h"
std::pair<NewsReferenceType, NewsReferenceType> SetupSubsidyDecodeParam(const struct Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset = 0);
std::pair<NewsReference, NewsReference> 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();

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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<TimerGameEconomy> _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));
}

View File

@ -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'