From 05ed9f56fd6c24b58914962827e537071e24cdd4 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 22 Jan 2023 22:06:48 +0100 Subject: [PATCH] Feature: [NewGRF] Engine name callback. --- src/aircraft_gui.cpp | 2 +- src/autoreplace_gui.cpp | 2 +- src/build_vehicle_gui.cpp | 9 +++++---- src/engine.cpp | 2 +- src/engine_gui.cpp | 2 +- src/engine_type.h | 16 ++++++++++++++++ src/newgrf_callbacks.h | 4 ++++ src/news_gui.cpp | 2 +- src/roadveh_gui.cpp | 2 +- src/ship_gui.cpp | 2 +- src/strings.cpp | 30 ++++++++++++++++++++++++++---- src/train_gui.cpp | 4 ++-- 12 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/aircraft_gui.cpp b/src/aircraft_gui.cpp index 421ddaf33b..4192fd2473 100644 --- a/src/aircraft_gui.cpp +++ b/src/aircraft_gui.cpp @@ -34,7 +34,7 @@ void DrawAircraftDetails(const Aircraft *v, const Rect &r) int y = r.top; for (const Aircraft *u = v; u != nullptr; u = u->Next()) { if (u->IsNormalAircraft()) { - SetDParam(0, u->engine_type); + SetDParam(0, PackEngineNameDParam(u->engine_type, EngineNameContext::VehicleDetails)); SetDParam(1, u->build_year); SetDParam(2, u->value); DrawString(r.left, r.right, y, STR_VEHICLE_INFO_BUILT_VALUE); diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index d53496ca8d..be339cc4a7 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -458,7 +458,7 @@ public: bool when_old = false; EngineID e = EngineReplacementForCompany(c, this->sel_engine[0], this->sel_group, &when_old); str = when_old ? STR_REPLACE_REPLACING_WHEN_OLD : STR_ENGINE_NAME; - SetDParam(0, e); + SetDParam(0, PackEngineNameDParam(e, EngineNameContext::PurchaseList)); } } else { str = STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED; diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index a4d425783b..b0d5d62e55 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -145,13 +145,14 @@ static bool EngineNameSorter(const GUIEngineListItem &a, const GUIEngineListItem if (a.engine_id != _last_engine[0]) { _last_engine[0] = a.engine_id; - SetDParam(0, a.engine_id); + SetDParam(0, PackEngineNameDParam(a.engine_id, EngineNameContext::PurchaseList)); + GetString(last_name[0], STR_ENGINE_NAME, lastof(last_name[0])); } if (b.engine_id != _last_engine[1]) { _last_engine[1] = b.engine_id; - SetDParam(0, b.engine_id); + SetDParam(0, PackEngineNameDParam(b.engine_id, EngineNameContext::PurchaseList)); GetString(last_name[1], STR_ENGINE_NAME, lastof(last_name[1])); } @@ -1037,7 +1038,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li StringID str = hidden ? STR_HIDDEN_ENGINE_NAME : STR_ENGINE_NAME; TextColour tc = (item.engine_id == selected_id) ? TC_WHITE : (TC_NO_SHADE | ((hidden | shaded) ? TC_GREY : TC_BLACK)); - SetDParam(0, item.engine_id); + SetDParam(0, PackEngineNameDParam(item.engine_id, EngineNameContext::PurchaseList, item.indent)); Rect itr = tr.Indent(indent, rtl); DrawString(itr.left, itr.right, y + normal_text_y_offset, str, tc); int sprite_x = ir.Indent(indent + circle_width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(sprite_width, rtl).left + sprite_left; @@ -1599,7 +1600,7 @@ struct BuildVehicleWindow : Window { EngineID sel_eng = this->sel_engine; if (sel_eng != INVALID_ENGINE) { this->rename_engine = sel_eng; - SetDParam(0, sel_eng); + SetDParam(0, PackEngineNameDParam(sel_eng, EngineNameContext::Generic)); ShowQueryString(STR_ENGINE_NAME, STR_QUERY_RENAME_TRAIN_TYPE_CAPTION + this->vehicle_type, MAX_LENGTH_ENGINE_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS); } break; diff --git a/src/engine.cpp b/src/engine.cpp index 26259066c3..649c49804d 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1049,7 +1049,7 @@ static void NewVehicleAvailable(Engine *e) /* Only provide the "New Vehicle available" news paper entry, if engine can be built. */ if (!IsVehicleTypeDisabled(e->type, false) && (e->info.extra_flags & ExtraEngineFlags::NoNews) == ExtraEngineFlags::None) { SetDParam(0, GetEngineCategoryName(index)); - SetDParam(1, index); + SetDParam(1, PackEngineNameDParam(index, EngineNameContext::PreviewNews)); AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, NT_NEW_VEHICLES, NF_VEHICLE, NR_ENGINE, index); } diff --git a/src/engine_gui.cpp b/src/engine_gui.cpp index 6bad2fb331..11a1cd7f3e 100644 --- a/src/engine_gui.cpp +++ b/src/engine_gui.cpp @@ -112,7 +112,7 @@ struct EnginePreviewWindow : Window { SetDParam(0, GetEngineCategoryName(engine)); int y = DrawStringMultiLine(r, STR_ENGINE_PREVIEW_MESSAGE, TC_FROMSTRING, SA_HOR_CENTER | SA_TOP) + WidgetDimensions::scaled.vsep_wide; - SetDParam(0, engine); + SetDParam(0, PackEngineNameDParam(engine, EngineNameContext::PreviewNews)); DrawString(r.left, r.right, y, STR_ENGINE_NAME, TC_BLACK, SA_HOR_CENTER); y += FONT_HEIGHT_NORMAL; diff --git a/src/engine_type.h b/src/engine_type.h index f3cd5aacfd..789ddbbca0 100644 --- a/src/engine_type.h +++ b/src/engine_type.h @@ -182,6 +182,22 @@ enum EngineFlags { ENGINE_EXCLUSIVE_PREVIEW = 2, ///< This vehicle is in the exclusive preview stage, either being used or being offered to a company. }; +/** + * Contexts an engine name can be shown in. + */ +enum EngineNameContext : uint8 { + Generic = 0x00, ///< No specific context available. + VehicleDetails = 0x11, ///< Name is shown in the vehicle details GUI. + PurchaseList = 0x20, ///< Name is shown in the purchase list (including autoreplace window). + PreviewNews = 0x21, ///< Name is shown in exclusive preview or newspaper. +}; + +/** Combine an engine ID and a name context to an engine name dparam. */ +inline uint64 PackEngineNameDParam(EngineID engine_id, EngineNameContext context, uint32 extra_data = 0) +{ + return engine_id | (static_cast(context) << 32) | (static_cast(extra_data) << 40); +} + static const uint MAX_LENGTH_ENGINE_NAME_CHARS = 32; ///< The maximum length of an engine name in characters including '\0' static const EngineID INVALID_ENGINE = 0xFFFF; ///< Constant denoting an invalid engine. diff --git a/src/newgrf_callbacks.h b/src/newgrf_callbacks.h index ed32a3abf1..ea20105cb8 100644 --- a/src/newgrf_callbacks.h +++ b/src/newgrf_callbacks.h @@ -279,6 +279,9 @@ enum CallbackID { /** Called to spawn visual effects for vehicles. */ CBID_VEHICLE_SPAWN_VISUAL_EFFECT = 0x160, // 15 bit callback + + /** Called to determine the engine name to show. */ + CBID_VEHICLE_NAME = 0x161, // 15 bit callback }; /** @@ -294,6 +297,7 @@ enum VehicleCallbackMask { CBM_VEHICLE_CARGO_SUFFIX = 5, ///< Show suffix after cargo name CBM_VEHICLE_COLOUR_REMAP = 6, ///< Change colour mapping of vehicle CBM_VEHICLE_SOUND_EFFECT = 7, ///< Vehicle uses custom sound effects + CBM_VEHICLE_NAME = 8, ///< Engine name }; /** diff --git a/src/news_gui.cpp b/src/news_gui.cpp index cd53aaf7d9..ab3bfadb92 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -601,7 +601,7 @@ private: return STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE; case WID_N_VEH_NAME: - SetDParam(0, engine); + SetDParam(0, PackEngineNameDParam(engine, EngineNameContext::PreviewNews)); return STR_NEWS_NEW_VEHICLE_TYPE; default: diff --git a/src/roadveh_gui.cpp b/src/roadveh_gui.cpp index da9200954e..37e43b506b 100644 --- a/src/roadveh_gui.cpp +++ b/src/roadveh_gui.cpp @@ -32,7 +32,7 @@ void DrawRoadVehDetails(const Vehicle *v, const Rect &r) StringID str; Money feeder_share = 0; - SetDParam(0, v->engine_type); + SetDParam(0, PackEngineNameDParam(v->engine_type, EngineNameContext::VehicleDetails)); SetDParam(1, v->build_year); SetDParam(2, v->value); DrawString(r.left, r.right, y, STR_VEHICLE_INFO_BUILT_VALUE); diff --git a/src/ship_gui.cpp b/src/ship_gui.cpp index 93c4a4a9c5..d5991c9b93 100644 --- a/src/ship_gui.cpp +++ b/src/ship_gui.cpp @@ -63,7 +63,7 @@ void DrawShipDetails(const Vehicle *v, const Rect &r) { int y = r.top; - SetDParam(0, v->engine_type); + SetDParam(0, PackEngineNameDParam(v->engine_type, EngineNameContext::VehicleDetails)); SetDParam(1, v->build_year); SetDParam(2, v->value); DrawString(r.left, r.right, y, STR_VEHICLE_INFO_BUILT_VALUE); diff --git a/src/strings.cpp b/src/strings.cpp index 27a8639550..f888770714 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -34,6 +34,7 @@ #include "debug.h" #include "game/game_text.hpp" #include "network/network_content_gui.h" +#include "newgrf_engine.h" #include #include "table/strings.h" @@ -1371,17 +1372,38 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg } case SCC_ENGINE_NAME: { // {ENGINE} - const Engine *e = Engine::GetIfValid(args->GetInt32(SCC_ENGINE_NAME)); + int64 arg = args->GetInt64(SCC_ENGINE_NAME); + const Engine *e = Engine::GetIfValid(static_cast(arg)); if (e == nullptr) break; if (!e->name.empty() && e->IsEnabled()) { int64 args_array[] = {(int64)(size_t)e->name.c_str()}; StringParameters tmp_params(args_array); buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last); - } else { - StringParameters tmp_params(nullptr, 0, nullptr); - buff = GetStringWithArgs(buff, e->info.string_id, &tmp_params, last); + + break; } + + if (HasBit(e->info.callback_mask, CBM_VEHICLE_NAME)) { + uint16 callback = GetVehicleCallback(CBID_VEHICLE_NAME, static_cast(arg >> 32), 0, e->index, nullptr); + /* Not calling ErrorUnknownCallbackResult due to being inside string processing. */ + if (callback != CALLBACK_FAILED && callback < 0x400) { + const GRFFile *grffile = e->GetGRF(); + assert(grffile != nullptr); + + StartTextRefStackUsage(grffile, 6); + uint64 tmp_dparam[6] = { 0 }; + WChar tmp_type[6] = { 0 }; + StringParameters tmp_params(tmp_dparam, 6, tmp_type); + buff = GetStringWithArgs(buff, GetGRFStringID(grffile->grfid, 0xD000 + callback), &tmp_params, last); + StopTextRefStackUsage(); + + break; + } + } + + StringParameters tmp_params(nullptr, 0, nullptr); + buff = GetStringWithArgs(buff, e->info.string_id, &tmp_params, last); break; } diff --git a/src/train_gui.cpp b/src/train_gui.cpp index 835fa24356..0745a08b2d 100644 --- a/src/train_gui.cpp +++ b/src/train_gui.cpp @@ -227,11 +227,11 @@ static void TrainDetailsCargoTab(const CargoSummaryItem *item, int left, int rig static void TrainDetailsInfoTab(const Vehicle *v, int left, int right, int y) { if (RailVehInfo(v->engine_type)->railveh_type == RAILVEH_WAGON) { - SetDParam(0, v->engine_type); + SetDParam(0, PackEngineNameDParam(v->engine_type, EngineNameContext::VehicleDetails)); SetDParam(1, v->value); DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE); } else { - SetDParam(0, v->engine_type); + SetDParam(0, PackEngineNameDParam(v->engine_type, EngineNameContext::VehicleDetails)); SetDParam(1, v->build_year); SetDParam(2, v->value); DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE);