diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index aea3630010..470f6d7632 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -801,6 +801,9 @@ static std::optional GetNewGRFAdditionalText(EngineID engine) if (callback == CALLBACK_FAILED || callback == 0x400) return std::nullopt; const GRFFile *grffile = Engine::Get(engine)->GetGRF(); assert(grffile != nullptr); + if (callback == 0x40F) { + return GetGRFStringWithTextStack(grffile, static_cast(regs100[0]), std::span{regs100}.subspan(1)); + } if (callback > 0x400) { ErrorUnknownCallbackResult(grffile->grfid, CBID_VEHICLE_ADDITIONAL_TEXT, callback); return std::nullopt; diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 188f11ffc0..5b89a22f6d 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -116,10 +116,22 @@ static void GetCargoSuffix(uint cargo, CargoSuffixType cst, const Industry *ind, return; } else { // GRF version 8 or higher. - if (callback == 0x400) return; - if (callback == 0x401) { - suffix.display = CSD_CARGO; - return; + switch (callback) { + case 0x400: + return; + case 0x401: + suffix.display = CSD_CARGO; + return; + case 0x40E: + suffix.display = CSD_CARGO_TEXT; + suffix.text = GetGRFStringWithTextStack(indspec->grf_prop.grffile, static_cast(regs100[0]), std::span{regs100}.subspan(1)); + return; + case 0x40F: + suffix.display = CSD_CARGO_AMOUNT_TEXT; + suffix.text = GetGRFStringWithTextStack(indspec->grf_prop.grffile, static_cast(regs100[0]), std::span{regs100}.subspan(1)); + return; + default: + break; } if (callback < 0x400) { suffix.text = GetGRFStringWithTextStack(indspec->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback, regs100); @@ -594,13 +606,16 @@ public: std::array regs100; uint16_t callback_res = GetIndustryCallback(CBID_INDUSTRY_FUND_MORE_TEXT, 0, 0, nullptr, this->selected_type, INVALID_TILE, regs100); if (callback_res != CALLBACK_FAILED && callback_res != 0x400) { - if (callback_res > 0x400) { + std::string str; + if (callback_res == 0x40F) { + str = GetGRFStringWithTextStack(indsp->grf_prop.grffile, static_cast(regs100[0]), std::span{regs100}.subspan(1)); + } else if (callback_res > 0x400) { ErrorUnknownCallbackResult(indsp->grf_prop.grfid, CBID_INDUSTRY_FUND_MORE_TEXT, callback_res); } else { - std::string str = GetGRFStringWithTextStack(indsp->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100); - if (!str.empty()) { - DrawStringMultiLine(ir, str, TC_YELLOW); - } + str = GetGRFStringWithTextStack(indsp->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100); + } + if (!str.empty()) { + DrawStringMultiLine(ir, str, TC_YELLOW); } } } @@ -977,14 +992,17 @@ public: std::array regs100; uint16_t callback_res = GetIndustryCallback(CBID_INDUSTRY_WINDOW_MORE_TEXT, 0, 0, i, i->type, i->location.tile, regs100); if (callback_res != CALLBACK_FAILED && callback_res != 0x400) { - if (callback_res > 0x400) { + std::string str; + if (callback_res == 0x40F) { + str = GetGRFStringWithTextStack(ind->grf_prop.grffile, static_cast(regs100[0]), std::span{regs100}.subspan(1)); + } else if (callback_res > 0x400) { ErrorUnknownCallbackResult(ind->grf_prop.grfid, CBID_INDUSTRY_WINDOW_MORE_TEXT, callback_res); } else { - std::string str = GetGRFStringWithTextStack(ind->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100); - if (!str.empty()) { - ir.top += WidgetDimensions::scaled.vsep_wide; - ir.top = DrawStringMultiLine(ir, str, TC_YELLOW); - } + str = GetGRFStringWithTextStack(ind->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100); + } + if (!str.empty()) { + ir.top += WidgetDimensions::scaled.vsep_wide; + ir.top = DrawStringMultiLine(ir, str, TC_YELLOW); } } } diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp index 14bca60531..3a47007a20 100644 --- a/src/newgrf_airport.cpp +++ b/src/newgrf_airport.cpp @@ -280,8 +280,12 @@ uint16_t GetAirportCallback(CallbackID callback, uint32_t param1, uint32_t param StringID GetAirportTextCallback(const AirportSpec *as, uint8_t layout, uint16_t callback) { AirportResolverObject object(INVALID_TILE, nullptr, as, layout, (CallbackID)callback); - uint16_t cb_res = object.ResolveCallback({}); + std::array regs100; + uint16_t cb_res = object.ResolveCallback(regs100); if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED; + if (cb_res == 0x40F) { + return GetGRFStringID(as->grf_prop.grfid, static_cast(regs100[0])); + } if (cb_res > 0x400) { ErrorUnknownCallbackResult(as->grf_prop.grfid, callback, cb_res); return STR_UNDEFINED; diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp index aee170bdb0..98c9d434f1 100644 --- a/src/newgrf_commons.cpp +++ b/src/newgrf_commons.cpp @@ -470,17 +470,22 @@ uint32_t GetCompanyInfo(CompanyID owner, const Livery *l) */ CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, std::span textstack, const GRFFile *grffile, StringID default_error) { - CommandCost res; - - if (cb_res < 0x400) { - res = CommandCost(GetGRFStringID(grffile->grfid, GRFSTR_MISC_GRF_TEXT + cb_res)); + auto get_newgrf_text = [&grffile](GRFStringID text_id, std::span textstack) { + CommandCost res = CommandCost(GetGRFStringID(grffile->grfid, text_id)); /* If this error isn't for the local player then it won't be seen, so don't bother encoding anything. */ - if (!IsLocalCompany()) return res; + if (IsLocalCompany()) { + StringID stringid = GetGRFStringID(grffile->grfid, text_id); + auto params = GetGRFSringTextStackParameters(grffile, stringid, textstack); + res.SetEncodedMessage(GetEncodedStringWithArgs(stringid, params)); + } - StringID stringid = GetGRFStringID(grffile->grfid, GRFSTR_MISC_GRF_TEXT + cb_res); - auto params = GetGRFSringTextStackParameters(grffile, stringid, textstack); - res.SetEncodedMessage(GetEncodedStringWithArgs(stringid, params)); + return res; + }; + + CommandCost res; + if (cb_res < 0x400) { + res = get_newgrf_text(GRFSTR_MISC_GRF_TEXT + cb_res, textstack); } else { switch (cb_res) { case 0x400: return res; // No error. @@ -495,6 +500,7 @@ CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, std::span case 0x406: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_SEA); break; case 0x407: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_CANAL); break; case 0x408: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_RIVER); break; + case 0x40F: res = get_newgrf_text(static_cast(textstack[0]), textstack.subspan(1)); break; } } diff --git a/src/object_gui.cpp b/src/object_gui.cpp index a65fad163b..ed5701d4f0 100644 --- a/src/object_gui.cpp +++ b/src/object_gui.cpp @@ -240,13 +240,16 @@ public: std::array regs100; uint16_t callback_res = GetObjectCallback(CBID_OBJECT_FUND_MORE_TEXT, 0, 0, spec, nullptr, INVALID_TILE, regs100, _object_gui.sel_view); if (callback_res != CALLBACK_FAILED && callback_res != 0x400) { - if (callback_res > 0x400) { + std::string str; + if (callback_res == 0x40F) { + str = GetGRFStringWithTextStack(spec->grf_prop.grffile, static_cast(regs100[0]), std::span{regs100}.subspan(1)); + } else if (callback_res > 0x400) { ErrorUnknownCallbackResult(spec->grf_prop.grfid, CBID_OBJECT_FUND_MORE_TEXT, callback_res); } else { - std::string str = GetGRFStringWithTextStack(spec->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100); - if (!str.empty()) { - tr.top = DrawStringMultiLine(tr, str, TC_ORANGE); - } + str = GetGRFStringWithTextStack(spec->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100); + } + if (!str.empty()) { + tr.top = DrawStringMultiLine(tr, str, TC_ORANGE); } } } diff --git a/src/strings.cpp b/src/strings.cpp index 2057964664..c6b3d2e923 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1613,7 +1613,13 @@ static void FormatString(StringBuilder &builder, std::string_view str_arg, Strin std::array regs100; uint16_t callback = GetVehicleCallback(CBID_VEHICLE_NAME, static_cast(arg >> 32), 0, e->index, nullptr, regs100); /* Not calling ErrorUnknownCallbackResult due to being inside string processing. */ - if (callback != CALLBACK_FAILED && callback < 0x400) { + if (callback == 0x40F) { + const GRFFile *grffile = e->GetGRF(); + assert(grffile != nullptr); + + builder += GetGRFStringWithTextStack(grffile, static_cast(regs100[0]), std::span{regs100}.subspan(1)); + break; + } else if (callback < 0x400) { const GRFFile *grffile = e->GetGRF(); assert(grffile != nullptr); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index f90386d378..8022e1e0d3 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -862,15 +862,19 @@ static void GetTileDesc_Town(TileIndex tile, TileDesc &td) td.str = hs->building_name; td.town_can_upgrade = !IsHouseProtected(tile); - uint16_t callback_res = GetHouseCallback(CBID_HOUSE_CUSTOM_NAME, house_completed ? 1 : 0, 0, house, Town::GetByTile(tile), tile); + std::array regs100; + uint16_t callback_res = GetHouseCallback(CBID_HOUSE_CUSTOM_NAME, house_completed ? 1 : 0, 0, house, Town::GetByTile(tile), tile, regs100); if (callback_res != CALLBACK_FAILED && callback_res != 0x400) { - if (callback_res > 0x400) { + StringID new_name = STR_NULL; + if (callback_res == 0x40F) { + new_name = GetGRFStringID(hs->grf_prop.grfid, static_cast(regs100[0])); + } else if (callback_res > 0x400) { ErrorUnknownCallbackResult(hs->grf_prop.grfid, CBID_HOUSE_CUSTOM_NAME, callback_res); } else { - StringID new_name = GetGRFStringID(hs->grf_prop.grfid, GRFSTR_MISC_GRF_TEXT + callback_res); - if (new_name != STR_NULL && new_name != STR_UNDEFINED) { - td.str = new_name; - } + new_name = GetGRFStringID(hs->grf_prop.grfid, GRFSTR_MISC_GRF_TEXT + callback_res); + } + if (new_name != STR_NULL && new_name != STR_UNDEFINED) { + td.str = new_name; } } diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 7e6b532b3c..503db6b687 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -1410,15 +1410,19 @@ void DrawHouseInGUI(int x, int y, HouseID house_id, int view) */ static StringID GetHouseName(const HouseSpec *hs) { - uint16_t callback_res = GetHouseCallback(CBID_HOUSE_CUSTOM_NAME, 1, 0, hs->Index(), nullptr, INVALID_TILE, {}, true); + std::array regs100; + uint16_t callback_res = GetHouseCallback(CBID_HOUSE_CUSTOM_NAME, 1, 0, hs->Index(), nullptr, INVALID_TILE, regs100, true); if (callback_res != CALLBACK_FAILED && callback_res != 0x400) { - if (callback_res > 0x400) { + StringID new_name = STR_NULL; + if (callback_res == 0x40F) { + new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, static_cast(regs100[0])); + } else if (callback_res > 0x400) { ErrorUnknownCallbackResult(hs->grf_prop.grffile->grfid, CBID_HOUSE_CUSTOM_NAME, callback_res); } else { - StringID new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, GRFSTR_MISC_GRF_TEXT + callback_res); - if (new_name != STR_NULL && new_name != STR_UNDEFINED) { - return new_name; - } + new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, GRFSTR_MISC_GRF_TEXT + callback_res); + } + if (new_name != STR_NULL && new_name != STR_UNDEFINED) { + return new_name; } } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index afab930bee..cacc922ddf 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1041,7 +1041,8 @@ static CommandCost CheckTrainAttachment(Train *t) * the loop and after each callback does not need to be cleared here. */ t->InvalidateNewGRFCache(); - uint16_t callback = GetVehicleCallbackParent(CBID_TRAIN_ALLOW_WAGON_ATTACH, 0, 0, head->engine_type, t, head); + std::array regs100; + uint16_t callback = GetVehicleCallbackParent(CBID_TRAIN_ALLOW_WAGON_ATTACH, 0, 0, head->engine_type, t, head, regs100); /* Restore original first_engine data */ t->gcache.first_engine = first_engine; @@ -1067,6 +1068,10 @@ static CommandCost CheckTrainAttachment(Train *t) case 0x401: // allow break; + case 0x40F: + error = GetGRFStringID(head->GetGRFID(), static_cast(regs100[0])); + break; + default: // unknown reason -> disallow case 0x402: // disallow attaching error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES; diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index ad41d7f17c..be4b273603 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -617,7 +617,8 @@ CommandCost CmdStartStopVehicle(DoCommandFlags flags, VehicleID veh_id, bool eva if (evaluate_startstop_cb) { /* Check if this vehicle can be started/stopped. Failure means 'allow'. */ - uint16_t callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v); + std::array regs100; + uint16_t callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v, regs100); StringID error = STR_NULL; if (callback != CALLBACK_FAILED) { if (v->GetGRF()->grf_version < 8) { @@ -631,6 +632,10 @@ CommandCost CmdStartStopVehicle(DoCommandFlags flags, VehicleID veh_id, bool eva case 0x400: // allow break; + case 0x40F: + error = GetGRFStringID(v->GetGRFID(), static_cast(regs100[0])); + break; + default: // unknown reason -> disallow error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES; break; diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 4c1f6f39e8..2b108b9185 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -1387,17 +1387,19 @@ uint ShowRefitOptionsList(int left, int right, int y, EngineID engine) /** Get the cargo subtype text from NewGRF for the vehicle details window. */ StringID GetCargoSubtypeText(const Vehicle *v) { - if (EngInfo(v->engine_type)->callback_mask.Test(VehicleCallbackMask::CargoSuffix)) { - uint16_t cb = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v); - if (cb != CALLBACK_FAILED) { - if (cb > 0x400) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_CARGO_SUFFIX, cb); - if (cb >= 0x400 || (v->GetGRF()->grf_version < 8 && cb == 0xFF)) cb = CALLBACK_FAILED; - } - if (cb != CALLBACK_FAILED) { - return GetGRFStringID(v->GetGRFID(), GRFSTR_MISC_GRF_TEXT + cb); - } + if (!EngInfo(v->engine_type)->callback_mask.Test(VehicleCallbackMask::CargoSuffix)) return STR_EMPTY; + std::array regs100; + uint16_t cb = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v, regs100); + if (v->GetGRF()->grf_version < 8 && cb == 0xFF) return STR_EMPTY; + if (cb == CALLBACK_FAILED || cb == 0x400) return STR_EMPTY; + if (cb == 0x40F) { + return GetGRFStringID(v->GetGRFID(), static_cast(regs100[0])); } - return STR_EMPTY; + if (cb > 0x400) { + ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_CARGO_SUFFIX, cb); + return STR_EMPTY; + } + return GetGRFStringID(v->GetGRFID(), GRFSTR_MISC_GRF_TEXT + cb); } /** Sort vehicle groups by the number of vehicles in the group */