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;
const GRFFile *grffile = Engine::Get(engine)->GetGRF();
assert(grffile != nullptr);
if (callback == 0x40F) {
return GetGRFStringWithTextStack(grffile, static_cast<GRFStringID>(regs100[0]), std::span{regs100}.subspan(1));
}
if (callback > 0x400) {
ErrorUnknownCallbackResult(grffile->grfid, CBID_VEHICLE_ADDITIONAL_TEXT, callback);
return std::nullopt;

View File

@ -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<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) {
suffix.text = GetGRFStringWithTextStack(indspec->grf_prop.grffile, GRFSTR_MISC_GRF_TEXT + callback, regs100);
@ -594,13 +606,16 @@ public:
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);
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);
} 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<int32_t, 6> 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<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);
} 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);
}
}
}

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)
{
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 == 0x40F) {
return GetGRFStringID(as->grf_prop.grfid, static_cast<GRFStringID>(regs100[0]));
}
if (cb_res > 0x400) {
ErrorUnknownCallbackResult(as->grf_prop.grfid, callback, cb_res);
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 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<const int32_t> 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<GRFStringID>(textstack[0]), textstack.subspan(1)); break;
}
}

View File

@ -240,13 +240,16 @@ public:
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);
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);
} 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);
}
}
}

View File

@ -1613,7 +1613,13 @@ static void FormatString(StringBuilder &builder, std::string_view str_arg, Strin
std::array<int32_t, 6> 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. */
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();
assert(grffile != nullptr);

View File

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

View File

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

View File

@ -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<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 */
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<GRFStringID>(regs100[0]));
break;
default: // unknown reason -> disallow
case 0x402: // disallow attaching
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) {
/* 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;
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<GRFStringID>(regs100[0]));
break;
default: // unknown reason -> disallow
error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
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. */
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<int32_t, 1> 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<GRFStringID>(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 */