1
0
Fork 0

Codechange: use AdviceType over StringID to remove vehicle advice news

pull/13292/head
Rubidium 2025-01-07 21:34:19 +01:00 committed by rubidium42
parent 0437701ebe
commit 08d84b2f4a
9 changed files with 48 additions and 34 deletions

View File

@ -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(STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v->index);
AddVehicleAdviceNewsItem(AdviceType::AircraftDestinationTooFar, STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v->index);
}
}
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, STR_NEWS_AIRCRAFT_DEST_TOO_FAR);
DeleteVehicleNews(v->index, AdviceType::AircraftDestinationTooFar);
}
}

View File

@ -348,7 +348,7 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic
SetDParam(2, CargoSpec::Get(old_veh->cargo_type)->name);
}
AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_AUTORENEW_FAILED, old_veh_id);
AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, STR_NEWS_VEHICLE_AUTORENEW_FAILED, old_veh_id);
return CommandCost();
}

View File

@ -15,7 +15,7 @@
#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);
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);
inline void AddCompanyNewsItem(StringID string, std::unique_ptr<CompanyNewsInformation> cni)
{
@ -37,9 +37,9 @@ inline void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle
*
* @warning DParam 0 must reference the vehicle!
*/
inline void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle)
inline void AddVehicleAdviceNewsItem(AdviceType advice_type, StringID string, VehicleID vehicle)
{
AddNewsItem(string, NT_ADVICE, NF_INCOLOUR | NF_SMALL | NF_VEHICLE_PARAM0, NR_VEHICLE, vehicle);
AddNewsItem(string, NT_ADVICE, NF_INCOLOUR | NF_SMALL | NF_VEHICLE_PARAM0, NR_VEHICLE, vehicle, NR_NONE, {}, nullptr, advice_type);
}
inline void AddTileNewsItem(StringID string, NewsType type, TileIndex tile, std::unique_ptr<NewsAllocatedData> &&data = nullptr, StationID station = INVALID_STATION)
@ -58,7 +58,7 @@ void InitNewsItemStructs();
const NewsItem *GetStatusbarNews();
void DeleteInvalidEngineNews();
void DeleteVehicleNews(VehicleID vid, StringID news);
void DeleteVehicleNews(VehicleID vid, AdviceType advice_type = AdviceType::Invalid);
void DeleteStationNews(StationID sid);
void DeleteIndustryNews(IndustryID iid);

View File

@ -870,11 +870,12 @@ static std::list<NewsItem>::iterator DeleteNewsItem(std::list<NewsItem>::iterato
* @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) :
string_id(string_id), date(TimerGameCalendar::date), economy_date(TimerGameEconomy::date), type(type), flags(flags), reftype1(reftype1), reftype2(reftype2), ref1(ref1), ref2(ref2), data(std::move(data))
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))
{
/* show this news message in colour? */
if (TimerGameCalendar::year >= _settings_client.gui.coloured_news_year) this->flags |= NF_INCOLOUR;
@ -891,15 +892,16 @@ NewsItem::NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsRefere
* @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)
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)
{
if (_game_mode == GM_MENU) return;
/* Create new news item node */
_news.emplace_front(string, type, flags, reftype1, ref1, reftype2, ref2, std::move(data));
_news.emplace_front(string, type, flags, reftype1, ref1, reftype2, ref2, std::move(data), advice_type);
/* Keep the number of stored news items to a managable number */
if (std::size(_news) > MAX_NEWS_AMOUNT) {
@ -990,15 +992,15 @@ void DeleteNews(Tpredicate predicate)
}
/**
* Delete a news item type about a vehicle.
* When the news item type is INVALID_STRING_ID all news about the vehicle gets deleted.
* 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 news The news type to remove.
* @param advice_type The advice type to remove for.
*/
void DeleteVehicleNews(VehicleID vid, StringID news)
void DeleteVehicleNews(VehicleID vid, AdviceType advice_type)
{
DeleteNews([&](const auto &ni) {
return ((ni.reftype1 == NR_VEHICLE && ni.ref1 == vid) || (ni.reftype2 == NR_VEHICLE && ni.ref2 == vid)) && (news == INVALID_STRING_ID || ni.string_id == news);
return ((ni.reftype1 == NR_VEHICLE && ni.ref1 == vid) || (ni.reftype2 == NR_VEHICLE && ni.ref2 == vid)) && (advice_type == AdviceType::Invalid || ni.advice_type == advice_type);
});
}

View File

@ -40,6 +40,21 @@ enum NewsType : uint8_t {
NT_END, ///< end-of-array marker
};
/** Sub type of the #NT_ADVICE to be able to remove specific news items. */
enum class AdviceType : uint8_t {
AircraftDestinationTooFar, ///< Next (order) destination is too far for the aircraft type.
AutorenewFailed, ///< Autorenew or autoreplace failed.
Order, ///< Something wrong with the order, e.g. invalid or duplicate entries, too few entries
RefitFailed, ///< The refit order failed to execute.
TrainStuck, ///< The train got stuck and needs to be unstuck manually.
VehicleLost, ///< The vehicle has become lost.
VehicleOld, ///< The vehicle is starting to get old.
VehicleUnprofitable, ///< The vehicle is costing you money.
VehicleWaiting, ///< The vehicle is waiting in the depot.
Invalid
};
/**
* References to objects in news.
*
@ -63,7 +78,7 @@ enum NewsReferenceType : uint8_t {
* Various OR-able news-item flags.
* @note #NF_INCOLOUR is set automatically if needed.
*/
enum NewsFlag {
enum NewsFlag : uint8_t {
NFB_INCOLOUR = 0, ///< News item is shown in colour (otherwise it is shown in black & white).
NFB_NO_TRANSPARENT = 1, ///< News item disables transparency in the viewport.
NFB_SHADE = 2, ///< News item uses shaded colours.
@ -130,6 +145,7 @@ struct NewsItem {
TimerGameCalendar::Date date; ///< Calendar date to show for the news
TimerGameEconomy::Date economy_date; ///< Economy date of the news item, never shown but used to calculate age
NewsType type; ///< Type of the news
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
@ -141,7 +157,7 @@ struct NewsItem {
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);
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);
};
/**

View File

@ -626,11 +626,7 @@ static inline bool OrderGoesToStation(const Vehicle *v, const Order *o)
*/
static void DeleteOrderWarnings(const Vehicle *v)
{
DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS);
DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_VOID_ORDER);
DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY);
DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_INVALID_ENTRY);
DeleteVehicleNews(v->index, STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY);
DeleteVehicleNews(v->index, AdviceType::Order);
}
/**
@ -1772,7 +1768,7 @@ void CheckOrders(const Vehicle *v)
if (message == INVALID_STRING_ID) return;
SetDParam(0, v->index);
AddVehicleAdviceNewsItem(message, v->index);
AddVehicleAdviceNewsItem(AdviceType::Order, message, v->index);
}
}

View File

@ -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(STR_NEWS_TRAIN_IS_STUCK, v->index);
AddVehicleAdviceNewsItem(AdviceType::TrainStuck, STR_NEWS_TRAIN_IS_STUCK, v->index);
}
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, STR_NEWS_VEHICLE_IS_LOST);
DeleteVehicleNews(this->index, 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(STR_NEWS_VEHICLE_IS_LOST, this->index);
AddVehicleAdviceNewsItem(AdviceType::VehicleLost, STR_NEWS_VEHICLE_IS_LOST, this->index);
}
}
@ -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, INVALID_STRING_ID);
DeleteVehicleNews(this->index);
DeleteNewGRFInspectWindow(GetGrfSpecFeature(this->type), this->index);
}
}
@ -1111,7 +1111,7 @@ void CallVehicleTicks()
SetDParam(0, v->index);
SetDParam(1, error_message);
AddVehicleAdviceNewsItem(message, v->index);
AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, message, v->index);
}
cur_company.Restore();
@ -1478,7 +1478,7 @@ void AgeVehicle(Vehicle *v)
}
SetDParam(0, v->index);
AddVehicleAdviceNewsItem(str, v->index);
AddVehicleAdviceNewsItem(AdviceType::VehicleOld, str, v->index);
}
/**
@ -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(STR_NEWS_ORDER_REFIT_FAILED, v->index);
AddVehicleAdviceNewsItem(AdviceType::RefitFailed, STR_NEWS_ORDER_REFIT_FAILED, v->index);
}
} 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(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index);
AddVehicleAdviceNewsItem(AdviceType::VehicleWaiting, STR_NEWS_TRAIN_IS_WAITING + v->type, v->index);
}
AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index));
}
@ -3027,7 +3027,7 @@ static IntervalTimer<TimerGameEconomy> _economy_vehicles_yearly({TimerGameEconom
if (_settings_client.gui.vehicle_income_warn && v->owner == _local_company) {
SetDParam(0, v->index);
SetDParam(1, profit);
AddVehicleAdviceNewsItem(
AddVehicleAdviceNewsItem(AdviceType::VehicleUnprofitable,
TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD : STR_NEWS_VEHICLE_UNPROFITABLE_YEAR,
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, STR_NEWS_TRAIN_IS_WAITING + v->type);
if (v->IsStoppedInDepot() && (flags & DC_AUTOREPLACE) == 0) DeleteVehicleNews(veh_id, AdviceType::VehicleWaiting);
v->vehstatus ^= VS_STOPPED;
if (v->type != VEH_TRAIN) v->cur_speed = 0; // trains can stop 'slowly'