1
0
Fork 0

Add: [NewGRF] All callbacks returning D0xx strings, have now the option to return any string id via register 0x100.

pull/14242/head
frosch 2025-05-06 17:28:51 +02:00 committed by frosch
parent 84bc78fd8f
commit c6fa5022cb
11 changed files with 114 additions and 54 deletions

View File

@ -801,6 +801,9 @@ static std::optional<std::string> GetNewGRFAdditionalText(EngineID engine)
if (callback == CALLBACK_FAILED || callback == 0x400) return std::nullopt; if (callback == CALLBACK_FAILED || callback == 0x400) return std::nullopt;
const GRFFile *grffile = Engine::Get(engine)->GetGRF(); const GRFFile *grffile = Engine::Get(engine)->GetGRF();
assert(grffile != nullptr); assert(grffile != nullptr);
if (callback == 0x40F) {
return GetGRFStringWithTextStack(grffile, static_cast<GRFStringID>(regs100[0]), std::span{regs100}.subspan(1));
}
if (callback > 0x400) { if (callback > 0x400) {
ErrorUnknownCallbackResult(grffile->grfid, CBID_VEHICLE_ADDITIONAL_TEXT, callback); ErrorUnknownCallbackResult(grffile->grfid, CBID_VEHICLE_ADDITIONAL_TEXT, callback);
return std::nullopt; return std::nullopt;

View File

@ -116,10 +116,22 @@ static void GetCargoSuffix(uint cargo, CargoSuffixType cst, const Industry *ind,
return; return;
} else { // GRF version 8 or higher. } else { // GRF version 8 or higher.
if (callback == 0x400) return; switch (callback) {
if (callback == 0x401) { case 0x400:
return;
case 0x401:
suffix.display = CSD_CARGO; suffix.display = CSD_CARGO;
return; return;
case 0x40E:
suffix.display = CSD_CARGO_TEXT;
suffix.text = GetGRFStringWithTextStack(indspec->grf_prop.grffile, static_cast<GRFStringID>(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<GRFStringID>(regs100[0]), std::span{regs100}.subspan(1));
return;
default:
break;
} }
if (callback < 0x400) { if (callback < 0x400) {
suffix.text = GetGRFStringWithTextStack(indspec->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback, regs100); suffix.text = GetGRFStringWithTextStack(indspec->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback, regs100);
@ -594,16 +606,19 @@ public:
std::array<int32_t, 6> regs100; std::array<int32_t, 6> regs100;
uint16_t callback_res = GetIndustryCallback(CBID_INDUSTRY_FUND_MORE_TEXT, 0, 0, nullptr, this->selected_type, INVALID_TILE, 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 != CALLBACK_FAILED && callback_res != 0x400) {
if (callback_res > 0x400) { std::string str;
if (callback_res == 0x40F) {
str = GetGRFStringWithTextStack(indsp->grf_prop.grffile, static_cast<GRFStringID>(regs100[0]), std::span{regs100}.subspan(1));
} else if (callback_res > 0x400) {
ErrorUnknownCallbackResult(indsp->grf_prop.grfid, CBID_INDUSTRY_FUND_MORE_TEXT, callback_res); ErrorUnknownCallbackResult(indsp->grf_prop.grfid, CBID_INDUSTRY_FUND_MORE_TEXT, callback_res);
} else { } else {
std::string str = GetGRFStringWithTextStack(indsp->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100); str = GetGRFStringWithTextStack(indsp->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100);
}
if (!str.empty()) { if (!str.empty()) {
DrawStringMultiLine(ir, str, TC_YELLOW); DrawStringMultiLine(ir, str, TC_YELLOW);
} }
} }
} }
}
break; break;
} }
} }
@ -977,17 +992,20 @@ public:
std::array<int32_t, 6> regs100; std::array<int32_t, 6> regs100;
uint16_t callback_res = GetIndustryCallback(CBID_INDUSTRY_WINDOW_MORE_TEXT, 0, 0, i, i->type, i->location.tile, 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 != CALLBACK_FAILED && callback_res != 0x400) {
if (callback_res > 0x400) { std::string str;
if (callback_res == 0x40F) {
str = GetGRFStringWithTextStack(ind->grf_prop.grffile, static_cast<GRFStringID>(regs100[0]), std::span{regs100}.subspan(1));
} else if (callback_res > 0x400) {
ErrorUnknownCallbackResult(ind->grf_prop.grfid, CBID_INDUSTRY_WINDOW_MORE_TEXT, callback_res); ErrorUnknownCallbackResult(ind->grf_prop.grfid, CBID_INDUSTRY_WINDOW_MORE_TEXT, callback_res);
} else { } else {
std::string str = GetGRFStringWithTextStack(ind->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100); str = GetGRFStringWithTextStack(ind->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100);
}
if (!str.empty()) { if (!str.empty()) {
ir.top += WidgetDimensions::scaled.vsep_wide; ir.top += WidgetDimensions::scaled.vsep_wide;
ir.top = DrawStringMultiLine(ir, str, TC_YELLOW); ir.top = DrawStringMultiLine(ir, str, TC_YELLOW);
} }
} }
} }
}
if (!i->text.empty()) { if (!i->text.empty()) {
ir.top += WidgetDimensions::scaled.vsep_wide; ir.top += WidgetDimensions::scaled.vsep_wide;

View File

@ -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) StringID GetAirportTextCallback(const AirportSpec *as, uint8_t layout, uint16_t callback)
{ {
AirportResolverObject object(INVALID_TILE, nullptr, as, layout, (CallbackID)callback); AirportResolverObject object(INVALID_TILE, nullptr, as, layout, (CallbackID)callback);
uint16_t cb_res = object.ResolveCallback({}); std::array<int32_t, 1> regs100;
uint16_t cb_res = object.ResolveCallback(regs100);
if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED; if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED;
if (cb_res == 0x40F) {
return GetGRFStringID(as->grf_prop.grfid, static_cast<GRFStringID>(regs100[0]));
}
if (cb_res > 0x400) { if (cb_res > 0x400) {
ErrorUnknownCallbackResult(as->grf_prop.grfid, callback, cb_res); ErrorUnknownCallbackResult(as->grf_prop.grfid, callback, cb_res);
return STR_UNDEFINED; return STR_UNDEFINED;

View File

@ -470,17 +470,22 @@ uint32_t GetCompanyInfo(CompanyID owner, const Livery *l)
*/ */
CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, std::span<const int32_t> textstack, const GRFFile *grffile, StringID default_error) CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, std::span<const int32_t> textstack, const GRFFile *grffile, StringID default_error)
{ {
CommandCost res; auto get_newgrf_text = [&grffile](GRFStringID text_id, std::span<const int32_t> textstack) {
CommandCost res = CommandCost(GetGRFStringID(grffile->grfid, text_id));
if (cb_res < 0x400) {
res = CommandCost(GetGRFStringID(grffile->grfid, GRFSTR_MISC_GRF_TEXT + cb_res));
/* If this error isn't for the local player then it won't be seen, so don't bother encoding anything. */ /* 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);
StringID stringid = GetGRFStringID(grffile->grfid, GRFSTR_MISC_GRF_TEXT + cb_res);
auto params = GetGRFSringTextStackParameters(grffile, stringid, textstack); auto params = GetGRFSringTextStackParameters(grffile, stringid, textstack);
res.SetEncodedMessage(GetEncodedStringWithArgs(stringid, params)); 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 { } else {
switch (cb_res) { switch (cb_res) {
case 0x400: return res; // No error. 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 0x406: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_SEA); break;
case 0x407: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_CANAL); 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 0x408: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_RIVER); break;
case 0x40F: res = get_newgrf_text(static_cast<GRFStringID>(textstack[0]), textstack.subspan(1)); break;
} }
} }

View File

@ -240,16 +240,19 @@ public:
std::array<int32_t, 6> regs100; std::array<int32_t, 6> regs100;
uint16_t callback_res = GetObjectCallback(CBID_OBJECT_FUND_MORE_TEXT, 0, 0, spec, nullptr, INVALID_TILE, regs100, _object_gui.sel_view); 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 != CALLBACK_FAILED && callback_res != 0x400) {
if (callback_res > 0x400) { std::string str;
if (callback_res == 0x40F) {
str = GetGRFStringWithTextStack(spec->grf_prop.grffile, static_cast<GRFStringID>(regs100[0]), std::span{regs100}.subspan(1));
} else if (callback_res > 0x400) {
ErrorUnknownCallbackResult(spec->grf_prop.grfid, CBID_OBJECT_FUND_MORE_TEXT, callback_res); ErrorUnknownCallbackResult(spec->grf_prop.grfid, CBID_OBJECT_FUND_MORE_TEXT, callback_res);
} else { } else {
std::string str = GetGRFStringWithTextStack(spec->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100); str = GetGRFStringWithTextStack(spec->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback_res, regs100);
}
if (!str.empty()) { if (!str.empty()) {
tr.top = DrawStringMultiLine(tr, str, TC_ORANGE); tr.top = DrawStringMultiLine(tr, str, TC_ORANGE);
} }
} }
} }
}
if (tr.top > bottom) { if (tr.top > bottom) {
BuildObjectWindow *bow = const_cast<BuildObjectWindow *>(this); BuildObjectWindow *bow = const_cast<BuildObjectWindow *>(this);

View File

@ -1613,7 +1613,13 @@ static void FormatString(StringBuilder &builder, std::string_view str_arg, Strin
std::array<int32_t, 6> regs100; std::array<int32_t, 6> regs100;
uint16_t callback = GetVehicleCallback(CBID_VEHICLE_NAME, static_cast<uint32_t>(arg >> 32), 0, e->index, nullptr, regs100); uint16_t callback = GetVehicleCallback(CBID_VEHICLE_NAME, static_cast<uint32_t>(arg >> 32), 0, e->index, nullptr, regs100);
/* Not calling ErrorUnknownCallbackResult due to being inside string processing. */ /* 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<GRFStringID>(regs100[0]), std::span{regs100}.subspan(1));
break;
} else if (callback < 0x400) {
const GRFFile *grffile = e->GetGRF(); const GRFFile *grffile = e->GetGRF();
assert(grffile != nullptr); assert(grffile != nullptr);

View File

@ -862,17 +862,21 @@ static void GetTileDesc_Town(TileIndex tile, TileDesc &td)
td.str = hs->building_name; td.str = hs->building_name;
td.town_can_upgrade = !IsHouseProtected(tile); 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<int32_t, 1> 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 != 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<GRFStringID>(regs100[0]));
} else if (callback_res > 0x400) {
ErrorUnknownCallbackResult(hs->grf_prop.grfid, CBID_HOUSE_CUSTOM_NAME, callback_res); ErrorUnknownCallbackResult(hs->grf_prop.grfid, CBID_HOUSE_CUSTOM_NAME, callback_res);
} else { } else {
StringID new_name = GetGRFStringID(hs->grf_prop.grfid, GRFSTR_MISC_GRF_TEXT + callback_res); new_name = GetGRFStringID(hs->grf_prop.grfid, GRFSTR_MISC_GRF_TEXT + callback_res);
}
if (new_name != STR_NULL && new_name != STR_UNDEFINED) { if (new_name != STR_NULL && new_name != STR_UNDEFINED) {
td.str = new_name; td.str = new_name;
} }
} }
}
if (!house_completed) { if (!house_completed) {
td.dparam = td.str; td.dparam = td.str;

View File

@ -1410,17 +1410,21 @@ void DrawHouseInGUI(int x, int y, HouseID house_id, int view)
*/ */
static StringID GetHouseName(const HouseSpec *hs) 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<int32_t, 1> 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 != 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<GRFStringID>(regs100[0]));
} else if (callback_res > 0x400) {
ErrorUnknownCallbackResult(hs->grf_prop.grffile->grfid, CBID_HOUSE_CUSTOM_NAME, callback_res); ErrorUnknownCallbackResult(hs->grf_prop.grffile->grfid, CBID_HOUSE_CUSTOM_NAME, callback_res);
} else { } else {
StringID new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, GRFSTR_MISC_GRF_TEXT + callback_res); new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, GRFSTR_MISC_GRF_TEXT + callback_res);
}
if (new_name != STR_NULL && new_name != STR_UNDEFINED) { if (new_name != STR_NULL && new_name != STR_UNDEFINED) {
return new_name; return new_name;
} }
} }
}
return hs->building_name; return hs->building_name;
} }

View File

@ -1041,7 +1041,8 @@ static CommandCost CheckTrainAttachment(Train *t)
* the loop and after each callback does not need to be cleared here. */ * the loop and after each callback does not need to be cleared here. */
t->InvalidateNewGRFCache(); t->InvalidateNewGRFCache();
uint16_t callback = GetVehicleCallbackParent(CBID_TRAIN_ALLOW_WAGON_ATTACH, 0, 0, head->engine_type, t, head); std::array<int32_t, 1> regs100;
uint16_t callback = GetVehicleCallbackParent(CBID_TRAIN_ALLOW_WAGON_ATTACH, 0, 0, head->engine_type, t, head, regs100);
/* Restore original first_engine data */ /* Restore original first_engine data */
t->gcache.first_engine = first_engine; t->gcache.first_engine = first_engine;
@ -1067,6 +1068,10 @@ static CommandCost CheckTrainAttachment(Train *t)
case 0x401: // allow case 0x401: // allow
break; break;
case 0x40F:
error = GetGRFStringID(head->GetGRFID(), static_cast<GRFStringID>(regs100[0]));
break;
default: // unknown reason -> disallow default: // unknown reason -> disallow
case 0x402: // disallow attaching case 0x402: // disallow attaching
error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES; error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;

View File

@ -617,7 +617,8 @@ CommandCost CmdStartStopVehicle(DoCommandFlags flags, VehicleID veh_id, bool eva
if (evaluate_startstop_cb) { if (evaluate_startstop_cb) {
/* Check if this vehicle can be started/stopped. Failure means 'allow'. */ /* 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<int32_t, 1> regs100;
uint16_t callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v, regs100);
StringID error = STR_NULL; StringID error = STR_NULL;
if (callback != CALLBACK_FAILED) { if (callback != CALLBACK_FAILED) {
if (v->GetGRF()->grf_version < 8) { if (v->GetGRF()->grf_version < 8) {
@ -631,6 +632,10 @@ CommandCost CmdStartStopVehicle(DoCommandFlags flags, VehicleID veh_id, bool eva
case 0x400: // allow case 0x400: // allow
break; break;
case 0x40F:
error = GetGRFStringID(v->GetGRFID(), static_cast<GRFStringID>(regs100[0]));
break;
default: // unknown reason -> disallow default: // unknown reason -> disallow
error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES; error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
break; break;

View File

@ -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. */ /** Get the cargo subtype text from NewGRF for the vehicle details window. */
StringID GetCargoSubtypeText(const Vehicle *v) StringID GetCargoSubtypeText(const Vehicle *v)
{ {
if (EngInfo(v->engine_type)->callback_mask.Test(VehicleCallbackMask::CargoSuffix)) { if (!EngInfo(v->engine_type)->callback_mask.Test(VehicleCallbackMask::CargoSuffix)) return STR_EMPTY;
uint16_t cb = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v); std::array<int32_t, 1> regs100;
if (cb != CALLBACK_FAILED) { uint16_t cb = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v, regs100);
if (cb > 0x400) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_CARGO_SUFFIX, cb); if (v->GetGRF()->grf_version < 8 && cb == 0xFF) return STR_EMPTY;
if (cb >= 0x400 || (v->GetGRF()->grf_version < 8 && cb == 0xFF)) cb = CALLBACK_FAILED; if (cb == CALLBACK_FAILED || cb == 0x400) return STR_EMPTY;
} if (cb == 0x40F) {
if (cb != CALLBACK_FAILED) { return GetGRFStringID(v->GetGRFID(), static_cast<GRFStringID>(regs100[0]));
return GetGRFStringID(v->GetGRFID(), GRFSTR_MISC_GRF_TEXT + cb);
}
} }
if (cb > 0x400) {
ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_CARGO_SUFFIX, cb);
return STR_EMPTY; return STR_EMPTY;
}
return GetGRFStringID(v->GetGRFID(), GRFSTR_MISC_GRF_TEXT + cb);
} }
/** Sort vehicle groups by the number of vehicles in the group */ /** Sort vehicle groups by the number of vehicles in the group */