mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Use EncodedStrings for News messages. (#13654)
parent
0afae7c546
commit
6e10584b91
|
@ -1335,18 +1335,17 @@ static void CrashAirplane(Aircraft *v)
|
||||||
CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
|
CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
|
||||||
|
|
||||||
uint victims = v->Crash();
|
uint victims = v->Crash();
|
||||||
SetDParam(0, victims);
|
|
||||||
|
|
||||||
v->cargo.Truncate();
|
v->cargo.Truncate();
|
||||||
v->Next()->cargo.Truncate();
|
v->Next()->cargo.Truncate();
|
||||||
const Station *st = GetTargetAirportIfValid(v);
|
const Station *st = GetTargetAirportIfValid(v);
|
||||||
StringID newsitem;
|
|
||||||
TileIndex vt = TileVirtXY(v->x_pos, v->y_pos);
|
TileIndex vt = TileVirtXY(v->x_pos, v->y_pos);
|
||||||
|
|
||||||
|
EncodedString headline;
|
||||||
if (st == nullptr) {
|
if (st == nullptr) {
|
||||||
newsitem = STR_NEWS_PLANE_CRASH_OUT_OF_FUEL;
|
headline = GetEncodedString(STR_NEWS_PLANE_CRASH_OUT_OF_FUEL, victims);
|
||||||
} else {
|
} else {
|
||||||
SetDParam(1, st->index);
|
headline = GetEncodedString(STR_NEWS_AIRCRAFT_CRASH, victims, st->index);
|
||||||
newsitem = STR_NEWS_AIRCRAFT_CRASH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING, victims));
|
AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING, victims));
|
||||||
|
@ -1357,7 +1356,7 @@ static void CrashAirplane(Aircraft *v)
|
||||||
newstype = NewsType::AccidentOther;
|
newstype = NewsType::AccidentOther;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddTileNewsItem(newsitem, newstype, vt, st != nullptr ? st->index : StationID::Invalid());
|
AddTileNewsItem(std::move(headline), newstype, vt, st != nullptr ? st->index : StationID::Invalid());
|
||||||
|
|
||||||
ModifyStationRatingAround(vt, v->owner, -160, 30);
|
ModifyStationRatingAround(vt, v->owner, -160, 30);
|
||||||
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
||||||
|
@ -1408,10 +1407,9 @@ static void AircraftEntersTerminal(Aircraft *v)
|
||||||
/* Check if station was ever visited before */
|
/* Check if station was ever visited before */
|
||||||
if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
|
if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
|
||||||
st->had_vehicle_of_type |= HVOT_AIRCRAFT;
|
st->had_vehicle_of_type |= HVOT_AIRCRAFT;
|
||||||
SetDParam(0, st->index);
|
|
||||||
/* show newsitem of celebrating citizens */
|
/* show newsitem of celebrating citizens */
|
||||||
AddVehicleNewsItem(
|
AddVehicleNewsItem(
|
||||||
STR_NEWS_FIRST_AIRCRAFT_ARRIVAL,
|
GetEncodedString(STR_NEWS_FIRST_AIRCRAFT_ARRIVAL, st->index),
|
||||||
(v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
(v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
||||||
v->index,
|
v->index,
|
||||||
st->index
|
st->index
|
||||||
|
@ -2063,8 +2061,7 @@ static void AircraftHandleDestTooFar(Aircraft *v, bool too_far)
|
||||||
AI::NewEvent(v->owner, new ScriptEventAircraftDestTooFar(v->index));
|
AI::NewEvent(v->owner, new ScriptEventAircraftDestTooFar(v->index));
|
||||||
if (v->owner == _local_company) {
|
if (v->owner == _local_company) {
|
||||||
/* Post a news message. */
|
/* Post a news message. */
|
||||||
SetDParam(0, v->index);
|
AddVehicleAdviceNewsItem(AdviceType::AircraftDestinationTooFar, GetEncodedString(STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v->index), v->index);
|
||||||
AddVehicleAdviceNewsItem(AdviceType::AircraftDestinationTooFar, STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v->index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -335,20 +335,24 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic
|
||||||
if (!IsLocalCompany() || !flags.Test(DoCommandFlag::Execute)) return CommandCost();
|
if (!IsLocalCompany() || !flags.Test(DoCommandFlag::Execute)) return CommandCost();
|
||||||
|
|
||||||
VehicleID old_veh_id = (old_veh->type == VEH_TRAIN) ? Train::From(old_veh)->First()->index : old_veh->index;
|
VehicleID old_veh_id = (old_veh->type == VEH_TRAIN) ? Train::From(old_veh)->First()->index : old_veh->index;
|
||||||
SetDParam(0, old_veh_id);
|
EncodedString headline;
|
||||||
|
|
||||||
int order_id = GetIncompatibleRefitOrderIdForAutoreplace(old_veh, e);
|
int order_id = GetIncompatibleRefitOrderIdForAutoreplace(old_veh, e);
|
||||||
if (order_id != -1) {
|
if (order_id != -1) {
|
||||||
/* Orders contained a refit order that is incompatible with the new vehicle. */
|
/* Orders contained a refit order that is incompatible with the new vehicle. */
|
||||||
SetDParam(1, STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT);
|
headline = GetEncodedString(STR_NEWS_VEHICLE_AUTORENEW_FAILED,
|
||||||
SetDParam(2, order_id + 1); // 1-based indexing for display
|
old_veh_id,
|
||||||
|
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT,
|
||||||
|
order_id + 1); // 1-based indexing for display
|
||||||
} else {
|
} else {
|
||||||
/* Current cargo is incompatible with the new vehicle. */
|
/* Current cargo is incompatible with the new vehicle. */
|
||||||
SetDParam(1, STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO);
|
headline = GetEncodedString(STR_NEWS_VEHICLE_AUTORENEW_FAILED,
|
||||||
SetDParam(2, CargoSpec::Get(old_veh->cargo_type)->name);
|
old_veh_id,
|
||||||
|
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO,
|
||||||
|
CargoSpec::Get(old_veh->cargo_type)->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, STR_NEWS_VEHICLE_AUTORENEW_FAILED, old_veh_id);
|
AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, std::move(headline), old_veh_id);
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -419,12 +419,10 @@ set_name:;
|
||||||
Game::NewEvent(new ScriptEventCompanyRenamed(c->index, name));
|
Game::NewEvent(new ScriptEventCompanyRenamed(c->index, name));
|
||||||
|
|
||||||
if (c->is_ai) {
|
if (c->is_ai) {
|
||||||
auto cni = std::make_unique<CompanyNewsInformation>(c);
|
auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_LAUNCH_TITLE, c);
|
||||||
SetDParam(0, STR_NEWS_COMPANY_LAUNCH_TITLE);
|
EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_LAUNCH_DESCRIPTION, cni->company_name, t->index);
|
||||||
SetDParam(1, STR_NEWS_COMPANY_LAUNCH_DESCRIPTION);
|
AddNewsItem(std::move(headline),
|
||||||
SetDParamStr(2, cni->company_name);
|
NewsType::CompanyInfo, NewsStyle::Company, {}, c->last_build_coordinate, {}, std::move(cni));
|
||||||
SetDParam(3, t->index);
|
|
||||||
AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NewsType::CompanyInfo, NewsStyle::Company, {}, c->last_build_coordinate, {}, std::move(cni));
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -806,7 +804,7 @@ static IntervalTimer<TimerGameEconomy> _economy_companies_yearly({TimerGameEcono
|
||||||
* @param c the current company.
|
* @param c the current company.
|
||||||
* @param other the other company (use \c nullptr if not relevant).
|
* @param other the other company (use \c nullptr if not relevant).
|
||||||
*/
|
*/
|
||||||
CompanyNewsInformation::CompanyNewsInformation(const Company *c, const Company *other)
|
CompanyNewsInformation::CompanyNewsInformation(StringID title, const Company *c, const Company *other)
|
||||||
{
|
{
|
||||||
this->company_name = GetString(STR_COMPANY_NAME, c->index);
|
this->company_name = GetString(STR_COMPANY_NAME, c->index);
|
||||||
|
|
||||||
|
@ -817,6 +815,7 @@ CompanyNewsInformation::CompanyNewsInformation(const Company *c, const Company *
|
||||||
|
|
||||||
this->president_name = GetString(STR_PRESIDENT_NAME_MANAGER, c->index);
|
this->president_name = GetString(STR_PRESIDENT_NAME_MANAGER, c->index);
|
||||||
|
|
||||||
|
this->title = title;
|
||||||
this->colour = c->colour;
|
this->colour = c->colour;
|
||||||
this->face = c->face;
|
this->face = c->face;
|
||||||
|
|
||||||
|
@ -934,13 +933,10 @@ CommandCost CmdCompanyCtrl(DoCommandFlags flags, CompanyCtrlAction cca, CompanyI
|
||||||
|
|
||||||
if (!flags.Test(DoCommandFlag::Execute)) return CommandCost();
|
if (!flags.Test(DoCommandFlag::Execute)) return CommandCost();
|
||||||
|
|
||||||
auto cni = std::make_unique<CompanyNewsInformation>(c);
|
|
||||||
|
|
||||||
/* Show the bankrupt news */
|
/* Show the bankrupt news */
|
||||||
SetDParam(0, STR_NEWS_COMPANY_BANKRUPT_TITLE);
|
auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_BANKRUPT_TITLE, c);
|
||||||
SetDParam(1, STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION);
|
EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION, cni->company_name);
|
||||||
SetDParamStr(2, cni->company_name);
|
AddCompanyNewsItem(std::move(headline), std::move(cni));
|
||||||
AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, std::move(cni));
|
|
||||||
|
|
||||||
/* Remove the company */
|
/* Remove the company */
|
||||||
ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
|
ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
|
||||||
|
|
|
@ -59,8 +59,8 @@ static void SurveyRecentNews(nlohmann::json &json)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto &news : GetNews()) {
|
for (const auto &news : GetNews()) {
|
||||||
TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(news.date);
|
TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(news.date);
|
||||||
json.push_back(fmt::format("({}-{:02}-{:02}) StringID: {}, Type: {}, Ref1: {}, {}, Ref2: {}, {}",
|
json.push_back(fmt::format("({}-{:02}-{:02}) String: {}, Type: {}, Ref1: {}, {}, Ref2: {}, {}",
|
||||||
ymd.year, ymd.month + 1, ymd.day, news.string_id, news.type,
|
ymd.year, ymd.month + 1, ymd.day, news.GetStatusText(), news.type,
|
||||||
news.ref1.index(), SerialiseNewsReference(news.ref1),
|
news.ref1.index(), SerialiseNewsReference(news.ref1),
|
||||||
news.ref2.index(), SerialiseNewsReference(news.ref2)));
|
news.ref2.index(), SerialiseNewsReference(news.ref2)));
|
||||||
if (++i > 32) break;
|
if (++i > 32) break;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "news_func.h"
|
#include "news_func.h"
|
||||||
#include "settings_type.h"
|
#include "settings_type.h"
|
||||||
#include "string_type.h"
|
#include "string_type.h"
|
||||||
|
#include "strings_func.h"
|
||||||
#include "timer/timer.h"
|
#include "timer/timer.h"
|
||||||
#include "timer/timer_game_calendar.h"
|
#include "timer/timer_game_calendar.h"
|
||||||
|
|
||||||
|
@ -148,7 +149,7 @@ static IntervalTimer<TimerGameCalendar> _check_switch_to_euro({TimerGameCalendar
|
||||||
_currency_specs[_settings_game.locale.currency].to_euro != CF_ISEURO &&
|
_currency_specs[_settings_game.locale.currency].to_euro != CF_ISEURO &&
|
||||||
TimerGameCalendar::year >= _currency_specs[_settings_game.locale.currency].to_euro) {
|
TimerGameCalendar::year >= _currency_specs[_settings_game.locale.currency].to_euro) {
|
||||||
_settings_game.locale.currency = 2; // this is the index of euro above.
|
_settings_game.locale.currency = 2; // this is the index of euro above.
|
||||||
AddNewsItem(STR_NEWS_EURO_INTRODUCTION, NewsType::Economy, NewsStyle::Normal, {});
|
AddNewsItem(GetEncodedString(STR_NEWS_EURO_INTRODUCTION), NewsType::Economy, NewsStyle::Normal, {});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -245,8 +245,7 @@ static bool DisasterTick_Zeppeliner(DisasterVehicle *v)
|
||||||
v->state = 1;
|
v->state = 1;
|
||||||
v->age = CalendarTime::MIN_DATE;
|
v->age = CalendarTime::MIN_DATE;
|
||||||
|
|
||||||
SetDParam(0, GetStationIndex(v->tile));
|
AddTileNewsItem(GetEncodedString(STR_NEWS_DISASTER_ZEPPELIN, GetStationIndex(v->tile)), NewsType::Accident, v->tile);
|
||||||
AddTileNewsItem(STR_NEWS_DISASTER_ZEPPELIN, NewsType::Accident, v->tile);
|
|
||||||
AI::NewEvent(GetTileOwner(v->tile), new ScriptEventDisasterZeppelinerCrashed(GetStationIndex(v->tile)));
|
AI::NewEvent(GetTileOwner(v->tile), new ScriptEventDisasterZeppelinerCrashed(GetStationIndex(v->tile)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,7 +386,7 @@ static bool DisasterTick_Ufo(DisasterVehicle *v)
|
||||||
uint victims = u->Crash();
|
uint victims = u->Crash();
|
||||||
u->disaster_vehicle = VehicleID::Invalid();
|
u->disaster_vehicle = VehicleID::Invalid();
|
||||||
|
|
||||||
AddTileNewsItem(STR_NEWS_DISASTER_SMALL_UFO, NewsType::Accident, u->tile);
|
AddTileNewsItem(GetEncodedString(STR_NEWS_DISASTER_SMALL_UFO), NewsType::Accident, u->tile);
|
||||||
|
|
||||||
AI::NewEvent(u->owner, new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO, victims));
|
AI::NewEvent(u->owner, new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO, victims));
|
||||||
Game::NewEvent(new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO, victims));
|
Game::NewEvent(new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO, victims));
|
||||||
|
@ -465,8 +464,7 @@ static bool DisasterTick_Aircraft(DisasterVehicle *v, uint16_t image_override, b
|
||||||
Industry *i = Industry::Get(v->dest_tile.base()); // Industry destructor calls ReleaseDisastersTargetingIndustry, so this is valid
|
Industry *i = Industry::Get(v->dest_tile.base()); // Industry destructor calls ReleaseDisastersTargetingIndustry, so this is valid
|
||||||
DestructIndustry(i);
|
DestructIndustry(i);
|
||||||
|
|
||||||
SetDParam(0, i->town->index);
|
AddIndustryNewsItem(GetEncodedString(news_message, i->town->index), NewsType::Accident, i->index);
|
||||||
AddIndustryNewsItem(news_message, NewsType::Accident, i->index);
|
|
||||||
if (_settings_client.sound.disaster) SndPlayTileFx(SND_12_EXPLOSION, i->location.tile);
|
if (_settings_client.sound.disaster) SndPlayTileFx(SND_12_EXPLOSION, i->location.tile);
|
||||||
}
|
}
|
||||||
} else if (v->state == 0) {
|
} else if (v->state == 0) {
|
||||||
|
@ -561,8 +559,7 @@ static bool DisasterTick_Big_Ufo(DisasterVehicle *v)
|
||||||
}
|
}
|
||||||
|
|
||||||
Town *t = ClosestTownFromTile(v->dest_tile, UINT_MAX);
|
Town *t = ClosestTownFromTile(v->dest_tile, UINT_MAX);
|
||||||
SetDParam(0, t->index);
|
AddTileNewsItem(GetEncodedString(STR_NEWS_DISASTER_BIG_UFO, t->index), NewsType::Accident, v->tile);
|
||||||
AddTileNewsItem(STR_NEWS_DISASTER_BIG_UFO, NewsType::Accident, v->tile);
|
|
||||||
|
|
||||||
if (!Vehicle::CanAllocateItem(2)) {
|
if (!Vehicle::CanAllocateItem(2)) {
|
||||||
delete v;
|
delete v;
|
||||||
|
@ -887,8 +884,7 @@ static void Disaster_CoalMine_Init()
|
||||||
for (m = 0; m < 15; m++) {
|
for (m = 0; m < 15; m++) {
|
||||||
for (const Industry *i : Industry::Iterate()) {
|
for (const Industry *i : Industry::Iterate()) {
|
||||||
if (GetIndustrySpec(i->type)->behaviour.Test(IndustryBehaviour::CanSubsidence) && --index < 0) {
|
if (GetIndustrySpec(i->type)->behaviour.Test(IndustryBehaviour::CanSubsidence) && --index < 0) {
|
||||||
SetDParam(0, i->town->index);
|
AddTileNewsItem(GetEncodedString(STR_NEWS_DISASTER_COAL_MINE_SUBSIDENCE, i->town->index), NewsType::Accident, i->location.tile + TileDiffXY(1, 1)); // keep the news, even when the mine closes
|
||||||
AddTileNewsItem(STR_NEWS_DISASTER_COAL_MINE_SUBSIDENCE, NewsType::Accident, i->location.tile + TileDiffXY(1, 1)); // keep the news, even when the mine closes
|
|
||||||
|
|
||||||
{
|
{
|
||||||
TileIndex tile = i->location.tile;
|
TileIndex tile = i->location.tile;
|
||||||
|
|
|
@ -582,11 +582,9 @@ static void CompanyCheckBankrupt(Company *c)
|
||||||
|
|
||||||
/* Warn about bankruptcy after 3 months */
|
/* Warn about bankruptcy after 3 months */
|
||||||
case 4: {
|
case 4: {
|
||||||
auto cni = std::make_unique<CompanyNewsInformation>(c);
|
auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_IN_TROUBLE_TITLE, c);
|
||||||
SetDParam(0, STR_NEWS_COMPANY_IN_TROUBLE_TITLE);
|
EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION, cni->company_name);
|
||||||
SetDParam(1, STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION);
|
AddCompanyNewsItem(std::move(headline), std::move(cni));
|
||||||
SetDParamStr(2, cni->company_name);
|
|
||||||
AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, std::move(cni));
|
|
||||||
AI::BroadcastNewEvent(new ScriptEventCompanyInTrouble(c->index));
|
AI::BroadcastNewEvent(new ScriptEventCompanyInTrouble(c->index));
|
||||||
Game::NewEvent(new ScriptEventCompanyInTrouble(c->index));
|
Game::NewEvent(new ScriptEventCompanyInTrouble(c->index));
|
||||||
break;
|
break;
|
||||||
|
@ -861,10 +859,10 @@ static void HandleEconomyFluctuations()
|
||||||
|
|
||||||
if (_economy.fluct == 0) {
|
if (_economy.fluct == 0) {
|
||||||
_economy.fluct = -(int)GB(Random(), 0, 2);
|
_economy.fluct = -(int)GB(Random(), 0, 2);
|
||||||
AddNewsItem(STR_NEWS_BEGIN_OF_RECESSION, NewsType::Economy, NewsStyle::Normal, {});
|
AddNewsItem(GetEncodedString(STR_NEWS_BEGIN_OF_RECESSION), NewsType::Economy, NewsStyle::Normal, {});
|
||||||
} else if (_economy.fluct == -12) {
|
} else if (_economy.fluct == -12) {
|
||||||
_economy.fluct = GB(Random(), 0, 8) + 312;
|
_economy.fluct = GB(Random(), 0, 8) + 312;
|
||||||
AddNewsItem(STR_NEWS_END_OF_RECESSION, NewsType::Economy, NewsStyle::Normal, {});
|
AddNewsItem(GetEncodedString(STR_NEWS_END_OF_RECESSION), NewsType::Economy, NewsStyle::Normal, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1995,14 +1993,11 @@ static void DoAcquireCompany(Company *c, bool hostile_takeover)
|
||||||
{
|
{
|
||||||
CompanyID ci = c->index;
|
CompanyID ci = c->index;
|
||||||
|
|
||||||
auto cni = std::make_unique<CompanyNewsInformation>(c, Company::Get(_current_company));
|
auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_MERGER_TITLE, c, Company::Get(_current_company));
|
||||||
|
EncodedString headline = hostile_takeover
|
||||||
SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE);
|
? GetEncodedString(STR_NEWS_MERGER_TAKEOVER_TITLE, cni->company_name, cni->other_company_name)
|
||||||
SetDParam(1, hostile_takeover ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION);
|
: GetEncodedString(STR_NEWS_COMPANY_MERGER_DESCRIPTION, cni->company_name, cni->other_company_name, c->bankrupt_value);
|
||||||
SetDParamStr(2, cni->company_name);
|
AddCompanyNewsItem(std::move(headline), std::move(cni));
|
||||||
SetDParamStr(3, cni->other_company_name);
|
|
||||||
SetDParam(4, c->bankrupt_value);
|
|
||||||
AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, std::move(cni));
|
|
||||||
AI::BroadcastNewEvent(new ScriptEventCompanyMerger(ci, _current_company));
|
AI::BroadcastNewEvent(new ScriptEventCompanyMerger(ci, _current_company));
|
||||||
Game::NewEvent(new ScriptEventCompanyMerger(ci, _current_company));
|
Game::NewEvent(new ScriptEventCompanyMerger(ci, _current_company));
|
||||||
|
|
||||||
|
|
|
@ -1129,9 +1129,10 @@ static void NewVehicleAvailable(Engine *e)
|
||||||
|
|
||||||
/* Only provide the "New Vehicle available" news paper entry, if engine can be built. */
|
/* Only provide the "New Vehicle available" news paper entry, if engine can be built. */
|
||||||
if (!IsVehicleTypeDisabled(e->type, false) && !e->info.extra_flags.Test(ExtraEngineFlag::NoNews)) {
|
if (!IsVehicleTypeDisabled(e->type, false) && !e->info.extra_flags.Test(ExtraEngineFlag::NoNews)) {
|
||||||
SetDParam(0, GetEngineCategoryName(index));
|
AddNewsItem(GetEncodedString(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE,
|
||||||
SetDParam(1, PackEngineNameDParam(index, EngineNameContext::PreviewNews));
|
GetEngineCategoryName(index),
|
||||||
AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, NewsType::NewVehicles, NewsStyle::Vehicle, {}, index);
|
PackEngineNameDParam(index, EngineNameContext::PreviewNews)),
|
||||||
|
NewsType::NewVehicles, NewsStyle::Vehicle, {}, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the toolbar. */
|
/* Update the toolbar. */
|
||||||
|
|
|
@ -1719,14 +1719,13 @@ static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, Indus
|
||||||
static void AdvertiseIndustryOpening(const Industry *ind)
|
static void AdvertiseIndustryOpening(const Industry *ind)
|
||||||
{
|
{
|
||||||
const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
|
const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
|
||||||
SetDParam(0, ind_spc->name);
|
EncodedString headline;
|
||||||
if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
|
if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
|
||||||
SetDParam(1, STR_TOWN_NAME);
|
headline = GetEncodedString(ind_spc->new_industry_text, ind_spc->name, STR_TOWN_NAME, ind->town->index);
|
||||||
SetDParam(2, ind->town->index);
|
|
||||||
} else {
|
} else {
|
||||||
SetDParam(1, ind->town->index);
|
headline = GetEncodedString(ind_spc->new_industry_text, ind_spc->name, ind->town->index);
|
||||||
}
|
}
|
||||||
AddIndustryNewsItem(ind_spc->new_industry_text, NewsType::IndustryOpen, ind->index);
|
AddIndustryNewsItem(std::move(headline), NewsType::IndustryOpen, ind->index);
|
||||||
AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
|
AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
|
||||||
Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
|
Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
|
||||||
}
|
}
|
||||||
|
@ -2194,16 +2193,15 @@ CommandCost CmdIndustrySetProduction(DoCommandFlags flags, IndustryID ind_id, ui
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set parameters of news string */
|
/* Set parameters of news string */
|
||||||
|
EncodedString headline;
|
||||||
if (str == STR_NEWS_CUSTOM_ITEM) {
|
if (str == STR_NEWS_CUSTOM_ITEM) {
|
||||||
SetDParamStr(0, custom_news);
|
headline = GetEncodedString(str, custom_news);
|
||||||
} else if (str > STR_LAST_STRINGID) {
|
} else if (str > STR_LAST_STRINGID) {
|
||||||
SetDParam(0, STR_TOWN_NAME);
|
headline = GetEncodedString(str, STR_TOWN_NAME, ind->town->index, GetIndustrySpec(ind->type)->name);
|
||||||
SetDParam(1, ind->town->index);
|
|
||||||
SetDParam(2, GetIndustrySpec(ind->type)->name);
|
|
||||||
} else {
|
} else {
|
||||||
SetDParam(0, ind->index);
|
headline = GetEncodedString(str, ind->index);
|
||||||
}
|
}
|
||||||
AddIndustryNewsItem(str, nt, ind->index);
|
AddIndustryNewsItem(std::move(headline), nt, ind->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2778,11 +2776,10 @@ static void ReportNewsProductionChangeIndustry(Industry *ind, CargoType type, in
|
||||||
case 2: nt = NewsType::IndustryCompany; break;
|
case 2: nt = NewsType::IndustryCompany; break;
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
SetDParam(2, abs(percent));
|
|
||||||
SetDParam(0, CargoSpec::Get(type)->name);
|
|
||||||
SetDParam(1, ind->index);
|
|
||||||
AddIndustryNewsItem(
|
AddIndustryNewsItem(
|
||||||
percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
|
GetEncodedString(percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
|
||||||
|
CargoSpec::Get(type)->name, ind->index, abs(percent)
|
||||||
|
),
|
||||||
nt,
|
nt,
|
||||||
ind->index
|
ind->index
|
||||||
);
|
);
|
||||||
|
@ -2985,22 +2982,19 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Set parameters of news string */
|
/* Set parameters of news string */
|
||||||
|
EncodedString headline;
|
||||||
if (str > STR_LAST_STRINGID) {
|
if (str > STR_LAST_STRINGID) {
|
||||||
SetDParam(0, STR_TOWN_NAME);
|
headline = GetEncodedString(str, STR_TOWN_NAME, i->town->index, indspec->name);
|
||||||
SetDParam(1, i->town->index);
|
|
||||||
SetDParam(2, indspec->name);
|
|
||||||
} else if (closeit) {
|
} else if (closeit) {
|
||||||
SetDParam(0, STR_FORMAT_INDUSTRY_NAME);
|
headline = GetEncodedString(str, STR_FORMAT_INDUSTRY_NAME, i->town->index, indspec->name);
|
||||||
SetDParam(1, i->town->index);
|
|
||||||
SetDParam(2, indspec->name);
|
|
||||||
} else {
|
} else {
|
||||||
SetDParam(0, i->index);
|
headline = GetEncodedString(str, i->index);
|
||||||
}
|
}
|
||||||
/* and report the news to the user */
|
/* and report the news to the user */
|
||||||
if (closeit) {
|
if (closeit) {
|
||||||
AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1));
|
AddTileNewsItem(std::move(headline), nt, i->location.tile + TileDiffXY(1, 1));
|
||||||
} else {
|
} else {
|
||||||
AddIndustryNewsItem(str, nt, i->index);
|
AddIndustryNewsItem(std::move(headline), nt, i->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -838,7 +838,7 @@ STR_STATUSBAR_INFINITE_MONEY :{WHITE}(infinit
|
||||||
# News message history
|
# News message history
|
||||||
STR_MESSAGE_HISTORY :{WHITE}Message History
|
STR_MESSAGE_HISTORY :{WHITE}Message History
|
||||||
STR_MESSAGE_HISTORY_TOOLTIP :{BLACK}A list of the recent news messages
|
STR_MESSAGE_HISTORY_TOOLTIP :{BLACK}A list of the recent news messages
|
||||||
STR_MESSAGE_NEWS_FORMAT :{STRING} - {STRING5}
|
STR_MESSAGE_NEWS_FORMAT :{STRING} - {RAW_STRING}
|
||||||
|
|
||||||
STR_NEWS_MESSAGE_CAPTION :{WHITE}Message
|
STR_NEWS_MESSAGE_CAPTION :{WHITE}Message
|
||||||
STR_NEWS_CUSTOM_ITEM :{BIG_FONT}{BLACK}{RAW_STRING}
|
STR_NEWS_CUSTOM_ITEM :{BIG_FONT}{BLACK}{RAW_STRING}
|
||||||
|
@ -934,14 +934,14 @@ STR_NEWS_SHOW_VEHICLE_GROUP_TOOLTIP :{BLACK}Open the
|
||||||
STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_LIST :{WHITE}{STATION} no longer accepts: {CARGO_LIST}
|
STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_LIST :{WHITE}{STATION} no longer accepts: {CARGO_LIST}
|
||||||
STR_NEWS_STATION_NOW_ACCEPTS_CARGO_LIST :{WHITE}{STATION} now accepts: {CARGO_LIST}
|
STR_NEWS_STATION_NOW_ACCEPTS_CARGO_LIST :{WHITE}{STATION} now accepts: {CARGO_LIST}
|
||||||
|
|
||||||
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offer of subsidy expired:{}{}{STRING} from {STRING2} to {STRING2} will now not attract a subsidy
|
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offer of subsidy expired:{}{}{STRING} from {STRING1} to {STRING1} will now not attract a subsidy
|
||||||
STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STRING2} to {STRING2} is no longer subsidised
|
STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STRING1} to {STRING1} is no longer subsidised
|
||||||
STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Service subsidy offered:{}{}First {STRING} from {STRING2} to {STRING2} will attract a {UNITS_YEARS_OR_MINUTES} subsidy from the local authority!
|
STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Service subsidy offered:{}{}First {STRING} from {STRING1} to {STRING1} will attract a {UNITS_YEARS_OR_MINUTES} subsidy from the local authority!
|
||||||
###length 4
|
###length 4
|
||||||
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay 50% extra for the next {UNITS_YEARS_OR_MINUTES}!
|
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING1} to {STRING1} will pay 50% extra for the next {UNITS_YEARS_OR_MINUTES}!
|
||||||
STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay double rates for the next {UNITS_YEARS_OR_MINUTES}!
|
STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING1} to {STRING1} will pay double rates for the next {UNITS_YEARS_OR_MINUTES}!
|
||||||
STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay triple rates for the next {UNITS_YEARS_OR_MINUTES}!
|
STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING1} to {STRING1} will pay triple rates for the next {UNITS_YEARS_OR_MINUTES}!
|
||||||
STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay quadruple rates for the next {UNITS_YEARS_OR_MINUTES}!
|
STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING1} to {STRING1} will pay quadruple rates for the next {UNITS_YEARS_OR_MINUTES}!
|
||||||
|
|
||||||
STR_NEWS_ROAD_REBUILDING_MONTHS :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {RAW_STRING} brings 6 months of misery to motorists!
|
STR_NEWS_ROAD_REBUILDING_MONTHS :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {RAW_STRING} brings 6 months of misery to motorists!
|
||||||
STR_NEWS_ROAD_REBUILDING_MINUTES :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {RAW_STRING} brings 6 minutes of misery to motorists!
|
STR_NEWS_ROAD_REBUILDING_MINUTES :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {RAW_STRING} brings 6 minutes of misery to motorists!
|
||||||
|
@ -3784,10 +3784,10 @@ STR_GOAL_QUESTION_BUTTON_CLOSE :Close
|
||||||
# Subsidies window
|
# Subsidies window
|
||||||
STR_SUBSIDIES_CAPTION :{WHITE}Subsidies
|
STR_SUBSIDIES_CAPTION :{WHITE}Subsidies
|
||||||
STR_SUBSIDIES_OFFERED_TITLE :{BLACK}Subsidies on offer for services taking:
|
STR_SUBSIDIES_OFFERED_TITLE :{BLACK}Subsidies on offer for services taking:
|
||||||
STR_SUBSIDIES_OFFERED_FROM_TO :{ORANGE}{STRING} from {STRING2} to {STRING2}{YELLOW} ({STRING1})
|
STR_SUBSIDIES_OFFERED_FROM_TO :{ORANGE}{STRING} from {STRING1} to {STRING1}{YELLOW} ({STRING1})
|
||||||
STR_SUBSIDIES_NONE :{ORANGE}- None -
|
STR_SUBSIDIES_NONE :{ORANGE}- None -
|
||||||
STR_SUBSIDIES_SUBSIDISED_TITLE :{BLACK}Services already subsidised:
|
STR_SUBSIDIES_SUBSIDISED_TITLE :{BLACK}Services already subsidised:
|
||||||
STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{STRING} from {STRING2} to {STRING2}{YELLOW} ({COMPANY}{YELLOW}, {STRING1})
|
STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{STRING} from {STRING1} to {STRING1}{YELLOW} ({COMPANY}{YELLOW}, {STRING1})
|
||||||
STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Click on service to centre main view on industry/town. Ctrl+Click to open a new viewport on industry/town location
|
STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Click on service to centre main view on industry/town. Ctrl+Click to open a new viewport on industry/town location
|
||||||
STR_SUBSIDIES_OFFERED_EXPIRY_DATE :by {DATE_SHORT}
|
STR_SUBSIDIES_OFFERED_EXPIRY_DATE :by {DATE_SHORT}
|
||||||
STR_SUBSIDIES_OFFERED_EXPIRY_TIME :within {UNITS_MONTHS_OR_MINUTES}
|
STR_SUBSIDIES_OFFERED_EXPIRY_TIME :within {UNITS_MONTHS_OR_MINUTES}
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
#include "station_type.h"
|
#include "station_type.h"
|
||||||
#include "industry_type.h"
|
#include "industry_type.h"
|
||||||
|
|
||||||
void AddNewsItem(StringID string, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1 = {}, NewsReference ref2 = {}, std::unique_ptr<NewsAllocatedData> &&data = nullptr, AdviceType advice_type = AdviceType::Invalid);
|
void AddNewsItem(EncodedString &&headline, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1 = {}, NewsReference ref2 = {}, std::unique_ptr<NewsAllocatedData> &&data = nullptr, AdviceType advice_type = AdviceType::Invalid);
|
||||||
|
|
||||||
inline void AddCompanyNewsItem(StringID string, std::unique_ptr<CompanyNewsInformation> cni)
|
inline void AddCompanyNewsItem(EncodedString &&headline, std::unique_ptr<CompanyNewsInformation> cni)
|
||||||
{
|
{
|
||||||
AddNewsItem(string, NewsType::CompanyInfo, NewsStyle::Company, {}, {}, {}, std::move(cni));
|
AddNewsItem(std::move(headline), NewsType::CompanyInfo, NewsStyle::Company, {}, {}, {}, std::move(cni));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,9 +27,9 @@ inline void AddCompanyNewsItem(StringID string, std::unique_ptr<CompanyNewsInfor
|
||||||
*
|
*
|
||||||
* @warning The DParams may not reference the vehicle due to autoreplace stuff. See AddVehicleAdviceNewsItem for how that can be done.
|
* @warning The DParams may not reference the vehicle due to autoreplace stuff. See AddVehicleAdviceNewsItem for how that can be done.
|
||||||
*/
|
*/
|
||||||
inline void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle, StationID station = StationID::Invalid())
|
inline void AddVehicleNewsItem(EncodedString &&headline, NewsType type, VehicleID vehicle, StationID station = StationID::Invalid())
|
||||||
{
|
{
|
||||||
AddNewsItem(string, type, NewsStyle::Thin, {NewsFlag::NoTransparency, NewsFlag::Shaded}, vehicle, station == StationID::Invalid() ? NewsReference{} : station);
|
AddNewsItem(std::move(headline), type, NewsStyle::Thin, {NewsFlag::NoTransparency, NewsFlag::Shaded}, vehicle, station == StationID::Invalid() ? NewsReference{} : station);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,19 +37,19 @@ inline void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle
|
||||||
*
|
*
|
||||||
* @warning DParam 0 must reference the vehicle!
|
* @warning DParam 0 must reference the vehicle!
|
||||||
*/
|
*/
|
||||||
inline void AddVehicleAdviceNewsItem(AdviceType advice_type, StringID string, VehicleID vehicle)
|
inline void AddVehicleAdviceNewsItem(AdviceType advice_type, EncodedString &&headline, VehicleID vehicle)
|
||||||
{
|
{
|
||||||
AddNewsItem(string, NewsType::Advice, NewsStyle::Small, {NewsFlag::InColour, NewsFlag::VehicleParam0}, vehicle, {}, nullptr, advice_type);
|
AddNewsItem(std::move(headline), NewsType::Advice, NewsStyle::Small, {NewsFlag::InColour, NewsFlag::VehicleParam0}, vehicle, {}, nullptr, advice_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AddTileNewsItem(StringID string, NewsType type, TileIndex tile, StationID station = StationID::Invalid())
|
inline void AddTileNewsItem(EncodedString &&headline, NewsType type, TileIndex tile, StationID station = StationID::Invalid())
|
||||||
{
|
{
|
||||||
AddNewsItem(string, type, NewsStyle::Thin, {NewsFlag::NoTransparency, NewsFlag::Shaded}, tile, station == StationID::Invalid() ? NewsReference{} : station);
|
AddNewsItem(std::move(headline), type, NewsStyle::Thin, {NewsFlag::NoTransparency, NewsFlag::Shaded}, tile, station == StationID::Invalid() ? NewsReference{} : station);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AddIndustryNewsItem(StringID string, NewsType type, IndustryID industry)
|
inline void AddIndustryNewsItem(EncodedString &&headline, NewsType type, IndustryID industry)
|
||||||
{
|
{
|
||||||
AddNewsItem(string, type, NewsStyle::Thin, {NewsFlag::NoTransparency, NewsFlag::Shaded}, industry, {});
|
AddNewsItem(std::move(headline), type, NewsStyle::Thin, {NewsFlag::NoTransparency, NewsFlag::Shaded}, industry, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewsLoop();
|
void NewsLoop();
|
||||||
|
|
|
@ -365,9 +365,6 @@ struct NewsWindow : Window {
|
||||||
|
|
||||||
this->CreateNestedTree();
|
this->CreateNestedTree();
|
||||||
|
|
||||||
/* For company news with a face we have a separate headline in param[0] */
|
|
||||||
if (&desc == &_company_news_desc) this->GetWidget<NWidgetCore>(WID_N_TITLE)->SetString(static_cast<StringID>(std::get<uint64_t>(this->ni->params[0])));
|
|
||||||
|
|
||||||
NWidgetCore *nwid = this->GetWidget<NWidgetCore>(WID_N_SHOW_GROUP);
|
NWidgetCore *nwid = this->GetWidget<NWidgetCore>(WID_N_SHOW_GROUP);
|
||||||
if (std::holds_alternative<VehicleID>(ni->ref1) && nwid != nullptr) {
|
if (std::holds_alternative<VehicleID>(ni->ref1) && nwid != nullptr) {
|
||||||
const Vehicle *v = Vehicle::Get(std::get<VehicleID>(ni->ref1));
|
const Vehicle *v = Vehicle::Get(std::get<VehicleID>(ni->ref1));
|
||||||
|
@ -446,12 +443,8 @@ struct NewsWindow : Window {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_N_MESSAGE:
|
case WID_N_MESSAGE:
|
||||||
CopyInDParam(this->ni->params);
|
|
||||||
str = GetString(this->ni->string_id);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WID_N_COMPANY_MSG:
|
case WID_N_COMPANY_MSG:
|
||||||
str = GetString(this->GetCompanyMessageString());
|
str = this->ni->headline.GetDecodedString();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_N_VEH_NAME:
|
case WID_N_VEH_NAME:
|
||||||
|
@ -499,7 +492,12 @@ struct NewsWindow : Window {
|
||||||
|
|
||||||
void SetStringParameters(WidgetID widget) const override
|
void SetStringParameters(WidgetID widget) const override
|
||||||
{
|
{
|
||||||
if (widget == WID_N_DATE) SetDParam(0, this->ni->date);
|
if (widget == WID_N_DATE) {
|
||||||
|
SetDParam(0, this->ni->date);
|
||||||
|
} else if (widget == WID_N_TITLE) {
|
||||||
|
const CompanyNewsInformation *cni = static_cast<const CompanyNewsInformation*>(this->ni->data.get());
|
||||||
|
SetDParam(0, cni->title);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawWidget(const Rect &r, WidgetID widget) const override
|
void DrawWidget(const Rect &r, WidgetID widget) const override
|
||||||
|
@ -514,8 +512,8 @@ struct NewsWindow : Window {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_N_MESSAGE:
|
case WID_N_MESSAGE:
|
||||||
CopyInDParam(this->ni->params);
|
case WID_N_COMPANY_MSG:
|
||||||
DrawStringMultiLine(r.left, r.right, r.top, r.bottom, this->ni->string_id, TC_FROMSTRING, SA_CENTER);
|
DrawStringMultiLine(r.left, r.right, r.top, r.bottom, this->ni->headline.GetDecodedString(), TC_FROMSTRING, SA_CENTER);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_N_MGR_FACE: {
|
case WID_N_MGR_FACE: {
|
||||||
|
@ -530,9 +528,6 @@ struct NewsWindow : Window {
|
||||||
DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_JUST_RAW_STRING, TC_FROMSTRING, SA_CENTER);
|
DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_JUST_RAW_STRING, TC_FROMSTRING, SA_CENTER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WID_N_COMPANY_MSG:
|
|
||||||
DrawStringMultiLine(r.left, r.right, r.top, r.bottom, this->GetCompanyMessageString(), TC_FROMSTRING, SA_CENTER);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WID_N_VEH_BKGND:
|
case WID_N_VEH_BKGND:
|
||||||
GfxFillRect(r.left, r.top, r.right, r.bottom, PC_GREY);
|
GfxFillRect(r.left, r.top, r.right, r.bottom, PC_GREY);
|
||||||
|
@ -671,13 +666,6 @@ private:
|
||||||
AddDirtyBlock(this->left, mintop, this->left + this->width, maxtop + this->height);
|
AddDirtyBlock(this->left, mintop, this->left + this->width, maxtop + this->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringID GetCompanyMessageString() const
|
|
||||||
{
|
|
||||||
/* Company news with a face have a separate headline, so the normal message is shifted by two params */
|
|
||||||
CopyInDParam(std::span(this->ni->params.data() + 2, this->ni->params.size() - 2));
|
|
||||||
return std::get<uint64_t>(this->ni->params[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringID GetNewVehicleMessageString(WidgetID widget) const
|
StringID GetNewVehicleMessageString(WidgetID widget) const
|
||||||
{
|
{
|
||||||
assert(std::holds_alternative<EngineID>(ni->ref1));
|
assert(std::holds_alternative<EngineID>(ni->ref1));
|
||||||
|
@ -875,12 +863,22 @@ static std::list<NewsItem>::iterator DeleteNewsItem(std::list<NewsItem>::iterato
|
||||||
*
|
*
|
||||||
* @see NewsSubtype
|
* @see NewsSubtype
|
||||||
*/
|
*/
|
||||||
NewsItem::NewsItem(StringID string_id, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1, NewsReference ref2, std::unique_ptr<NewsAllocatedData> &&data, AdviceType advice_type) :
|
NewsItem::NewsItem(EncodedString &&headline, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1, NewsReference 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), style(style), flags(flags), ref1(ref1), ref2(ref2), data(std::move(data))
|
headline(std::move(headline)), date(TimerGameCalendar::date), economy_date(TimerGameEconomy::date), type(type), advice_type(advice_type), style(style), flags(flags), ref1(ref1), ref2(ref2), data(std::move(data))
|
||||||
{
|
{
|
||||||
/* show this news message in colour? */
|
/* show this news message in colour? */
|
||||||
if (TimerGameCalendar::year >= _settings_client.gui.coloured_news_year) this->flags.Set(NewsFlag::InColour);
|
if (TimerGameCalendar::year >= _settings_client.gui.coloured_news_year) this->flags.Set(NewsFlag::InColour);
|
||||||
CopyOutDParam(this->params, 10);
|
}
|
||||||
|
|
||||||
|
std::string NewsItem::GetStatusText() const
|
||||||
|
{
|
||||||
|
if (this->data != nullptr) {
|
||||||
|
/* CompanyNewsInformation is the only type of additional data used. */
|
||||||
|
const CompanyNewsInformation &cni = *static_cast<const CompanyNewsInformation*>(this->data.get());
|
||||||
|
return GetString(STR_MESSAGE_NEWS_FORMAT, cni.title, this->headline.GetDecodedString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->headline.GetDecodedString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -895,12 +893,12 @@ NewsItem::NewsItem(StringID string_id, NewsType type, NewsStyle style, NewsFlags
|
||||||
*
|
*
|
||||||
* @see NewsSubtype
|
* @see NewsSubtype
|
||||||
*/
|
*/
|
||||||
void AddNewsItem(StringID string, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1, NewsReference ref2, std::unique_ptr<NewsAllocatedData> &&data, AdviceType advice_type)
|
void AddNewsItem(EncodedString &&headline, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1, NewsReference ref2, std::unique_ptr<NewsAllocatedData> &&data, AdviceType advice_type)
|
||||||
{
|
{
|
||||||
if (_game_mode == GM_MENU) return;
|
if (_game_mode == GM_MENU) return;
|
||||||
|
|
||||||
/* Create new news item node */
|
/* Create new news item node */
|
||||||
_news.emplace_front(string, type, style, flags, ref1, ref2, std::move(data), advice_type);
|
_news.emplace_front(std::move(headline), type, style, flags, ref1, ref2, std::move(data), advice_type);
|
||||||
|
|
||||||
/* Keep the number of stored news items to a manageable number */
|
/* Keep the number of stored news items to a manageable number */
|
||||||
if (std::size(_news) > MAX_NEWS_AMOUNT) {
|
if (std::size(_news) > MAX_NEWS_AMOUNT) {
|
||||||
|
@ -963,8 +961,7 @@ CommandCost CmdCustomNewsItem(DoCommandFlags flags, NewsType type, CompanyID com
|
||||||
if (company != INVALID_OWNER && company != _local_company) return CommandCost();
|
if (company != INVALID_OWNER && company != _local_company) return CommandCost();
|
||||||
|
|
||||||
if (flags.Test(DoCommandFlag::Execute)) {
|
if (flags.Test(DoCommandFlag::Execute)) {
|
||||||
SetDParamStr(0, text);
|
AddNewsItem(GetEncodedString(STR_NEWS_CUSTOM_ITEM, text), type, NewsStyle::Normal, {}, reference, {});
|
||||||
AddNewsItem(STR_NEWS_CUSTOM_ITEM, type, NewsStyle::Normal, {}, reference, {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
|
@ -1084,7 +1081,7 @@ void ChangeVehicleNews(VehicleID from_index, VehicleID to_index)
|
||||||
for (auto &ni : _news) {
|
for (auto &ni : _news) {
|
||||||
ChangeObject(ni.ref1, from_index, to_index);
|
ChangeObject(ni.ref1, from_index, to_index);
|
||||||
ChangeObject(ni.ref2, from_index, to_index);
|
ChangeObject(ni.ref2, from_index, to_index);
|
||||||
if (ni.flags.Test(NewsFlag::VehicleParam0) && std::get<uint64_t>(ni.params[0]) == from_index) ni.params[0] = to_index.base();
|
if (ni.flags.Test(NewsFlag::VehicleParam0) && IsReferenceObject(ni.ref1, to_index)) ni.headline = ni.headline.ReplaceParam(0, to_index.base());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1186,10 +1183,8 @@ void ShowLastNewsMessage()
|
||||||
*/
|
*/
|
||||||
static void DrawNewsString(uint left, uint right, int y, TextColour colour, const NewsItem *ni)
|
static void DrawNewsString(uint left, uint right, int y, TextColour colour, const NewsItem *ni)
|
||||||
{
|
{
|
||||||
CopyInDParam(ni->params);
|
|
||||||
|
|
||||||
/* Get the string, replaces newlines with spaces and remove control codes from the string. */
|
/* Get the string, replaces newlines with spaces and remove control codes from the string. */
|
||||||
std::string message = StrMakeValid(GetString(ni->string_id), SVS_REPLACE_TAB_CR_NL_WITH_SPACE);
|
std::string message = StrMakeValid(ni->GetStatusText(), SVS_REPLACE_TAB_CR_NL_WITH_SPACE);
|
||||||
|
|
||||||
/* Truncate and show string; postfixed by '...' if necessary */
|
/* Truncate and show string; postfixed by '...' if necessary */
|
||||||
DrawString(left, right, y, message, colour);
|
DrawString(left, right, y, message, colour);
|
||||||
|
|
|
@ -134,7 +134,7 @@ struct NewsAllocatedData {
|
||||||
|
|
||||||
/** Information about a single item of news. */
|
/** Information about a single item of news. */
|
||||||
struct NewsItem {
|
struct NewsItem {
|
||||||
StringID string_id; ///< Message text
|
EncodedString headline; ///< Headline of news.
|
||||||
TimerGameCalendar::Date date; ///< Calendar date to show for the news
|
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
|
TimerGameEconomy::Date economy_date; ///< Economy date of the news item, never shown but used to calculate age
|
||||||
NewsType type; ///< Type of the news
|
NewsType type; ///< Type of the news
|
||||||
|
@ -147,9 +147,9 @@ struct NewsItem {
|
||||||
|
|
||||||
std::unique_ptr<NewsAllocatedData> data; ///< Custom data for the news item that will be deallocated (deleted) when the news item has reached its end.
|
std::unique_ptr<NewsAllocatedData> data; ///< Custom data for the news item that will be deallocated (deleted) when the news item has reached its end.
|
||||||
|
|
||||||
std::vector<StringParameterData> params; ///< Parameters for string resolving.
|
NewsItem(EncodedString &&headline, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1, NewsReference ref2, std::unique_ptr<NewsAllocatedData> &&data, AdviceType advice_type);
|
||||||
|
|
||||||
NewsItem(StringID string_id, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1, NewsReference ref2, std::unique_ptr<NewsAllocatedData> &&data, AdviceType advice_type);
|
std::string GetStatusText() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,10 +163,11 @@ struct CompanyNewsInformation : NewsAllocatedData {
|
||||||
std::string president_name; ///< The name of the president
|
std::string president_name; ///< The name of the president
|
||||||
std::string other_company_name; ///< The name of the company taking over this one
|
std::string other_company_name; ///< The name of the company taking over this one
|
||||||
|
|
||||||
|
StringID title;
|
||||||
uint32_t face; ///< The face of the president
|
uint32_t face; ///< The face of the president
|
||||||
Colours colour; ///< The colour related to the company
|
Colours colour; ///< The colour related to the company
|
||||||
|
|
||||||
CompanyNewsInformation(const struct Company *c, const struct Company *other = nullptr);
|
CompanyNewsInformation(StringID title, const struct Company *c, const struct Company *other = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
using NewsContainer = std::list<NewsItem>; ///< Container type for storing news items.
|
using NewsContainer = std::list<NewsItem>; ///< Container type for storing news items.
|
||||||
|
|
|
@ -1756,8 +1756,7 @@ void CheckOrders(const Vehicle *v)
|
||||||
/* We don't have a problem */
|
/* We don't have a problem */
|
||||||
if (message == INVALID_STRING_ID) return;
|
if (message == INVALID_STRING_ID) return;
|
||||||
|
|
||||||
SetDParam(0, v->index);
|
AddVehicleAdviceNewsItem(AdviceType::Order, GetEncodedString(message, v->index), v->index);
|
||||||
AddVehicleAdviceNewsItem(AdviceType::Order, message, v->index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -548,15 +548,12 @@ static void RoadVehCrash(RoadVehicle *v)
|
||||||
AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING, victims));
|
AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING, victims));
|
||||||
Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING, victims));
|
Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING, victims));
|
||||||
|
|
||||||
SetDParam(0, victims);
|
EncodedString headline = (victims == 1)
|
||||||
StringID newsitem = (victims == 1) ? STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH;
|
? GetEncodedString(STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER)
|
||||||
NewsType newstype = NewsType::Accident;
|
: GetEncodedString(STR_NEWS_ROAD_VEHICLE_CRASH, victims);
|
||||||
|
NewsType newstype = v->owner == _local_company ? NewsType::Accident : NewsType::AccidentOther;
|
||||||
|
|
||||||
if (v->owner != _local_company) {
|
AddTileNewsItem(std::move(headline), newstype, v->tile);
|
||||||
newstype = NewsType::AccidentOther;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddTileNewsItem(newsitem, newstype, v->tile);
|
|
||||||
|
|
||||||
ModifyStationRatingAround(v->tile, v->owner, -160, 22);
|
ModifyStationRatingAround(v->tile, v->owner, -160, 22);
|
||||||
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
||||||
|
@ -689,9 +686,8 @@ static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
|
||||||
/* Check if station was ever visited before */
|
/* Check if station was ever visited before */
|
||||||
if (!(st->had_vehicle_of_type & HVOT_BUS)) {
|
if (!(st->had_vehicle_of_type & HVOT_BUS)) {
|
||||||
st->had_vehicle_of_type |= HVOT_BUS;
|
st->had_vehicle_of_type |= HVOT_BUS;
|
||||||
SetDParam(0, st->index);
|
|
||||||
AddVehicleNewsItem(
|
AddVehicleNewsItem(
|
||||||
RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL,
|
GetEncodedString(RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL, st->index),
|
||||||
(v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
(v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
||||||
v->index,
|
v->index,
|
||||||
st->index
|
st->index
|
||||||
|
@ -703,9 +699,8 @@ static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
|
||||||
/* Check if station was ever visited before */
|
/* Check if station was ever visited before */
|
||||||
if (!(st->had_vehicle_of_type & HVOT_TRUCK)) {
|
if (!(st->had_vehicle_of_type & HVOT_TRUCK)) {
|
||||||
st->had_vehicle_of_type |= HVOT_TRUCK;
|
st->had_vehicle_of_type |= HVOT_TRUCK;
|
||||||
SetDParam(0, st->index);
|
|
||||||
AddVehicleNewsItem(
|
AddVehicleNewsItem(
|
||||||
RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL,
|
GetEncodedString(RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL, st->index),
|
||||||
(v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
(v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
||||||
v->index,
|
v->index,
|
||||||
st->index
|
st->index
|
||||||
|
|
|
@ -471,9 +471,8 @@ static void ShipArrivesAt(const Vehicle *v, Station *st)
|
||||||
if (!(st->had_vehicle_of_type & HVOT_SHIP)) {
|
if (!(st->had_vehicle_of_type & HVOT_SHIP)) {
|
||||||
st->had_vehicle_of_type |= HVOT_SHIP;
|
st->had_vehicle_of_type |= HVOT_SHIP;
|
||||||
|
|
||||||
SetDParam(0, st->index);
|
|
||||||
AddVehicleNewsItem(
|
AddVehicleNewsItem(
|
||||||
STR_NEWS_FIRST_SHIP_ARRIVAL,
|
GetEncodedString(STR_NEWS_FIRST_SHIP_ARRIVAL, st->index),
|
||||||
(v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
(v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
||||||
v->index,
|
v->index,
|
||||||
st->index
|
st->index
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include "company_type.h"
|
#include "company_type.h"
|
||||||
#include "industry_type.h"
|
#include "industry_type.h"
|
||||||
|
#include "news_type.h"
|
||||||
|
#include "strings_type.h"
|
||||||
#include "town_type.h"
|
#include "town_type.h"
|
||||||
|
|
||||||
/** Types of cargo source and destination */
|
/** Types of cargo source and destination */
|
||||||
|
@ -48,6 +50,9 @@ public:
|
||||||
|
|
||||||
constexpr bool IsValid() const noexcept { return this->id != Source::Invalid; }
|
constexpr bool IsValid() const noexcept { return this->id != Source::Invalid; }
|
||||||
auto operator<=>(const Source &source) const = default;
|
auto operator<=>(const Source &source) const = default;
|
||||||
|
|
||||||
|
NewsReference GetNewsReference() const;
|
||||||
|
StringID GetFormat() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SOURCE_TYPE_H */
|
#endif /* SOURCE_TYPE_H */
|
||||||
|
|
|
@ -529,10 +529,8 @@ CargoTypes GetEmptyMask(const Station *st)
|
||||||
*/
|
*/
|
||||||
static void ShowRejectOrAcceptNews(const Station *st, CargoTypes cargoes, bool reject)
|
static void ShowRejectOrAcceptNews(const Station *st, CargoTypes cargoes, bool reject)
|
||||||
{
|
{
|
||||||
SetDParam(0, st->index);
|
|
||||||
SetDParam(1, cargoes);
|
|
||||||
StringID msg = reject ? STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_LIST : STR_NEWS_STATION_NOW_ACCEPTS_CARGO_LIST;
|
StringID msg = reject ? STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_LIST : STR_NEWS_STATION_NOW_ACCEPTS_CARGO_LIST;
|
||||||
AddNewsItem(msg, NewsType::Acceptance, NewsStyle::Small, NewsFlag::InColour, st->index);
|
AddNewsItem(GetEncodedString(msg, st->index, cargoes), NewsType::Acceptance, NewsStyle::Small, NewsFlag::InColour, st->index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -38,10 +38,8 @@
|
||||||
|
|
||||||
static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left, int right, int top, int bottom)
|
static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left, int right, int top, int bottom)
|
||||||
{
|
{
|
||||||
CopyInDParam(ni->params);
|
|
||||||
|
|
||||||
/* Replace newlines and the likes with spaces. */
|
/* Replace newlines and the likes with spaces. */
|
||||||
std::string message = StrMakeValid(GetString(ni->string_id), SVS_REPLACE_TAB_CR_NL_WITH_SPACE);
|
std::string message = StrMakeValid(ni->GetStatusText(), SVS_REPLACE_TAB_CR_NL_WITH_SPACE);
|
||||||
|
|
||||||
DrawPixelInfo tmp_dpi;
|
DrawPixelInfo tmp_dpi;
|
||||||
if (!FillDrawPixelInfo(&tmp_dpi, left, top, right - left, bottom)) return true;
|
if (!FillDrawPixelInfo(&tmp_dpi, left, top, right - left, bottom)) return true;
|
||||||
|
@ -145,7 +143,7 @@ struct StatusBarWindow : Window {
|
||||||
} else if (_pause_mode.Any()) {
|
} else if (_pause_mode.Any()) {
|
||||||
StringID msg = _pause_mode.Test(PauseMode::LinkGraph) ? STR_STATUSBAR_PAUSED_LINK_GRAPH : STR_STATUSBAR_PAUSED;
|
StringID msg = _pause_mode.Test(PauseMode::LinkGraph) ? STR_STATUSBAR_PAUSED_LINK_GRAPH : STR_STATUSBAR_PAUSED;
|
||||||
DrawString(tr, msg, TC_FROMSTRING, SA_HOR_CENTER);
|
DrawString(tr, msg, TC_FROMSTRING, SA_HOR_CENTER);
|
||||||
} else if (this->ticker_scroll < TICKER_STOP && GetStatusbarNews() != nullptr && GetStatusbarNews()->string_id != 0) {
|
} else if (this->ticker_scroll < TICKER_STOP && GetStatusbarNews() != nullptr && !GetStatusbarNews()->headline.empty()) {
|
||||||
/* Draw the scrolling news text */
|
/* Draw the scrolling news text */
|
||||||
if (!DrawScrollingStatusText(GetStatusbarNews(), ScaleGUITrad(this->ticker_scroll), tr.left, tr.right, tr.top, tr.bottom)) {
|
if (!DrawScrollingStatusText(GetStatusbarNews(), ScaleGUITrad(this->ticker_scroll), tr.left, tr.right, tr.top, tr.bottom)) {
|
||||||
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED);
|
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED);
|
||||||
|
|
|
@ -146,6 +146,75 @@ EncodedString GetEncodedStringWithArgs(StringID str, std::span<const StringParam
|
||||||
return EncodedString{std::move(result)};
|
return EncodedString{std::move(result)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace a parameter of this EncodedString.
|
||||||
|
* @note If the string cannot be decoded for some reason, an empty EncodedString will be returned instead.
|
||||||
|
* @param param Index of parameter to replace.
|
||||||
|
* @param data New data for parameter.
|
||||||
|
* @returns a new EncodedString with the parameter replaced.
|
||||||
|
*/
|
||||||
|
EncodedString EncodedString::ReplaceParam(size_t param, StringParameter &&data) const
|
||||||
|
{
|
||||||
|
if (this->empty()) return {};
|
||||||
|
|
||||||
|
std::vector<StringParameter> params;
|
||||||
|
|
||||||
|
/* We need char * for std::from_chars. Iterate the underlying data, as string's own iterators may interfere. */
|
||||||
|
const char *p = this->string.data();
|
||||||
|
const char *e = this->string.data() + this->string.length();
|
||||||
|
|
||||||
|
char32_t c = Utf8Consume(p);
|
||||||
|
if (c != SCC_ENCODED_INTERNAL) return {};
|
||||||
|
|
||||||
|
StringID str;
|
||||||
|
auto result = std::from_chars(p, e, str, 16);
|
||||||
|
if (result.ec != std::errc()) return {};
|
||||||
|
if (result.ptr != e && *result.ptr != SCC_RECORD_SEPARATOR) return {};
|
||||||
|
p = result.ptr;
|
||||||
|
|
||||||
|
while (p != e) {
|
||||||
|
auto s = ++p;
|
||||||
|
|
||||||
|
/* Find end of the parameter. */
|
||||||
|
for (; p != e && *p != SCC_RECORD_SEPARATOR; ++p) {}
|
||||||
|
|
||||||
|
if (s == p) {
|
||||||
|
/* This is an empty parameter. */
|
||||||
|
params.emplace_back(std::monostate{});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the parameter type. */
|
||||||
|
char32_t parameter_type;
|
||||||
|
size_t len = Utf8Decode(¶meter_type, s);
|
||||||
|
s += len;
|
||||||
|
|
||||||
|
switch (parameter_type) {
|
||||||
|
case SCC_ENCODED_NUMERIC: {
|
||||||
|
uint64_t value;
|
||||||
|
result = std::from_chars(s, p, value, 16);
|
||||||
|
if (result.ec != std::errc() || result.ptr != p) return {};
|
||||||
|
params.emplace_back(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SCC_ENCODED_STRING: {
|
||||||
|
params.emplace_back(std::string(s, p));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Unknown parameter, make it blank. */
|
||||||
|
params.emplace_back(std::monostate{});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param >= std::size(params)) return {};
|
||||||
|
params[param] = data;
|
||||||
|
return GetEncodedStringWithArgs(str, params);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode the encoded string.
|
* Decode the encoded string.
|
||||||
* @returns Decoded raw string.
|
* @returns Decoded raw string.
|
||||||
|
|
|
@ -102,6 +102,7 @@ public:
|
||||||
auto operator<=>(const EncodedString &) const = default;
|
auto operator<=>(const EncodedString &) const = default;
|
||||||
|
|
||||||
std::string GetDecodedString() const;
|
std::string GetDecodedString() const;
|
||||||
|
EncodedString ReplaceParam(size_t param, StringParameter &&value) const;
|
||||||
|
|
||||||
inline void clear() { this->string.clear(); }
|
inline void clear() { this->string.clear(); }
|
||||||
inline bool empty() const { return this->string.empty(); }
|
inline bool empty() const { return this->string.empty(); }
|
||||||
|
|
102
src/subsidy.cpp
102
src/subsidy.cpp
|
@ -36,6 +36,32 @@
|
||||||
SubsidyPool _subsidy_pool("Subsidy"); ///< Pool for the subsidies.
|
SubsidyPool _subsidy_pool("Subsidy"); ///< Pool for the subsidies.
|
||||||
INSTANTIATE_POOL_METHODS(Subsidy)
|
INSTANTIATE_POOL_METHODS(Subsidy)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the NewsReference for a subsidy Source.
|
||||||
|
* @returns NewsReference.
|
||||||
|
*/
|
||||||
|
NewsReference Source::GetNewsReference() const
|
||||||
|
{
|
||||||
|
switch (this->type) {
|
||||||
|
case SourceType::Industry: return static_cast<IndustryID>(this->id);
|
||||||
|
case SourceType::Town: return static_cast<TownID>(this->id);
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the format string for a subsidy Source.
|
||||||
|
* @returns The format string.
|
||||||
|
*/
|
||||||
|
StringID Source::GetFormat() const
|
||||||
|
{
|
||||||
|
switch (this->type) {
|
||||||
|
case SourceType::Industry: return STR_INDUSTRY_NAME;
|
||||||
|
case SourceType::Town: return STR_TOWN_NAME;
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks subsidy as awarded, creates news and AI event
|
* Marks subsidy as awarded, creates news and AI event
|
||||||
* @param company awarded company
|
* @param company awarded company
|
||||||
|
@ -50,70 +76,15 @@ void Subsidy::AwardTo(CompanyID company)
|
||||||
std::string company_name = GetString(STR_COMPANY_NAME, company);
|
std::string company_name = GetString(STR_COMPANY_NAME, company);
|
||||||
|
|
||||||
/* Add a news item */
|
/* Add a news item */
|
||||||
std::pair<NewsReference, NewsReference> references = SetupSubsidyDecodeParam(this, SubsidyDecodeParamType::NewsAwarded, 1);
|
const CargoSpec *cs = CargoSpec::Get(this->cargo_type);
|
||||||
|
EncodedString headline = GetEncodedString(STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier, std::move(company_name), cs->name, this->src.GetFormat(), this->src.id, this->dst.GetFormat(), this->dst.id, _settings_game.difficulty.subsidy_duration);
|
||||||
SetDParamStr(0, company_name);
|
AddNewsItem(std::move(headline), NewsType::Subsidies, NewsStyle::Normal, {}, this->src.GetNewsReference(), this->dst.GetNewsReference());
|
||||||
AddNewsItem(
|
|
||||||
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier,
|
|
||||||
NewsType::Subsidies, NewsStyle::Normal, {},
|
|
||||||
references.first, references.second
|
|
||||||
);
|
|
||||||
AI::BroadcastNewEvent(new ScriptEventSubsidyAwarded(this->index));
|
AI::BroadcastNewEvent(new ScriptEventSubsidyAwarded(this->index));
|
||||||
Game::NewEvent(new ScriptEventSubsidyAwarded(this->index));
|
Game::NewEvent(new ScriptEventSubsidyAwarded(this->index));
|
||||||
|
|
||||||
InvalidateWindowData(WC_SUBSIDIES_LIST, 0);
|
InvalidateWindowData(WC_SUBSIDIES_LIST, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup the string parameters for printing the subsidy at the screen, and compute the news reference for the subsidy.
|
|
||||||
* @param s %Subsidy being printed.
|
|
||||||
* @param mode Type of subsidy news message to decide on parameter format.
|
|
||||||
* @param parameter_offset The location/index in the String DParams to start decoding the subsidy's parameters. Defaults to 0.
|
|
||||||
* @return Reference of the subsidy in the news system.
|
|
||||||
*/
|
|
||||||
std::pair<NewsReference, NewsReference> SetupSubsidyDecodeParam(const Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset)
|
|
||||||
{
|
|
||||||
NewsReference reference1{};
|
|
||||||
NewsReference reference2{};
|
|
||||||
|
|
||||||
/* Always use the plural form of the cargo name - trying to decide between plural or singular causes issues for translations */
|
|
||||||
const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
|
|
||||||
SetDParam(parameter_offset, cs->name);
|
|
||||||
|
|
||||||
switch (s->src.type) {
|
|
||||||
case SourceType::Industry:
|
|
||||||
reference1 = static_cast<IndustryID>(s->src.id);
|
|
||||||
SetDParam(parameter_offset + 1, STR_INDUSTRY_NAME);
|
|
||||||
break;
|
|
||||||
case SourceType::Town:
|
|
||||||
reference1 = static_cast<TownID>(s->src.id);
|
|
||||||
SetDParam(parameter_offset + 1, STR_TOWN_NAME);
|
|
||||||
break;
|
|
||||||
default: NOT_REACHED();
|
|
||||||
}
|
|
||||||
SetDParam(parameter_offset + 2, s->src.id);
|
|
||||||
|
|
||||||
switch (s->dst.type) {
|
|
||||||
case SourceType::Industry:
|
|
||||||
reference2 = static_cast<IndustryID>(s->dst.id);
|
|
||||||
SetDParam(parameter_offset + 4, STR_INDUSTRY_NAME);
|
|
||||||
break;
|
|
||||||
case SourceType::Town:
|
|
||||||
reference2 = static_cast<TownID>(s->dst.id);
|
|
||||||
SetDParam(parameter_offset + 4, STR_TOWN_NAME);
|
|
||||||
break;
|
|
||||||
default: NOT_REACHED();
|
|
||||||
}
|
|
||||||
SetDParam(parameter_offset + 5, s->dst.id);
|
|
||||||
|
|
||||||
/* If the subsidy is being offered or awarded, the news item mentions the subsidy duration. */
|
|
||||||
if (mode == SubsidyDecodeParamType::NewsOffered || mode == SubsidyDecodeParamType::NewsAwarded) {
|
|
||||||
SetDParam(parameter_offset + 7, _settings_game.difficulty.subsidy_duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {reference1, reference2};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a flag indicating that given town/industry is part of subsidised route.
|
* Sets a flag indicating that given town/industry is part of subsidised route.
|
||||||
* @param source actual source
|
* @param source actual source
|
||||||
|
@ -203,8 +174,9 @@ void CreateSubsidy(CargoType cargo_type, Source src, Source dst)
|
||||||
{
|
{
|
||||||
Subsidy *s = new Subsidy(cargo_type, src, dst, SUBSIDY_OFFER_MONTHS);
|
Subsidy *s = new Subsidy(cargo_type, src, dst, SUBSIDY_OFFER_MONTHS);
|
||||||
|
|
||||||
std::pair<NewsReference, NewsReference> references = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsOffered);
|
const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
|
||||||
AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NewsType::Subsidies, NewsStyle::Normal, {}, references.first, references.second);
|
EncodedString headline = GetEncodedString(STR_NEWS_SERVICE_SUBSIDY_OFFERED, cs->name, s->src.GetFormat(), s->src.id, s->dst.GetFormat(), s->dst.id, _settings_game.difficulty.subsidy_duration);
|
||||||
|
AddNewsItem(std::move(headline), NewsType::Subsidies, NewsStyle::Normal, {}, s->src.GetNewsReference(), s->dst.GetNewsReference());
|
||||||
SetPartOfSubsidyFlag(s->src, POS_SRC);
|
SetPartOfSubsidyFlag(s->src, POS_SRC);
|
||||||
SetPartOfSubsidyFlag(s->dst, POS_DST);
|
SetPartOfSubsidyFlag(s->dst, POS_DST);
|
||||||
AI::BroadcastNewEvent(new ScriptEventSubsidyOffer(s->index));
|
AI::BroadcastNewEvent(new ScriptEventSubsidyOffer(s->index));
|
||||||
|
@ -457,14 +429,16 @@ static IntervalTimer<TimerGameEconomy> _economy_subsidies_monthly({TimerGameEcon
|
||||||
for (Subsidy *s : Subsidy::Iterate()) {
|
for (Subsidy *s : Subsidy::Iterate()) {
|
||||||
if (--s->remaining == 0) {
|
if (--s->remaining == 0) {
|
||||||
if (!s->IsAwarded()) {
|
if (!s->IsAwarded()) {
|
||||||
std::pair<NewsReference, NewsReference> references = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn);
|
const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
|
||||||
AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NewsType::Subsidies, NewsStyle::Normal, {}, references.first, references.second);
|
EncodedString headline = GetEncodedString(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, cs->name, s->src.GetFormat(), s->src.id, s->dst.GetFormat(), s->dst.id);
|
||||||
|
AddNewsItem(std::move(headline), NewsType::Subsidies, NewsStyle::Normal, {}, s->src.GetNewsReference(), s->dst.GetNewsReference());
|
||||||
AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index));
|
AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index));
|
||||||
Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index));
|
Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index));
|
||||||
} else {
|
} else {
|
||||||
if (s->awarded == _local_company) {
|
if (s->awarded == _local_company) {
|
||||||
std::pair<NewsReference, NewsReference> references = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn);
|
const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
|
||||||
AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NewsType::Subsidies, NewsStyle::Normal, {}, references.first, references.second);
|
EncodedString headline = GetEncodedString(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, cs->name, s->src.GetFormat(), s->src.id, s->dst.GetFormat(), s->dst.id);
|
||||||
|
AddNewsItem(std::move(headline), NewsType::Subsidies, NewsStyle::Normal, {}, s->src.GetNewsReference(), s->dst.GetNewsReference());
|
||||||
}
|
}
|
||||||
AI::BroadcastNewEvent(new ScriptEventSubsidyExpired(s->index));
|
AI::BroadcastNewEvent(new ScriptEventSubsidyExpired(s->index));
|
||||||
Game::NewEvent(new ScriptEventSubsidyExpired(s->index));
|
Game::NewEvent(new ScriptEventSubsidyExpired(s->index));
|
||||||
|
|
|
@ -58,12 +58,4 @@ static const uint SUBSIDY_MAX_PCT_TRANSPORTED = 42; ///< Subsidy will be creat
|
||||||
static const uint SUBSIDY_MAX_DISTANCE = 70; ///< Max. length of subsidised route (DistanceManhattan)
|
static const uint SUBSIDY_MAX_DISTANCE = 70; ///< Max. length of subsidised route (DistanceManhattan)
|
||||||
static const uint SUBSIDY_TOWN_CARGO_RADIUS = 6; ///< Extent of a tile area around town center when scanning for town cargo acceptance and production (6 ~= min catchmement + min station / 2)
|
static const uint SUBSIDY_TOWN_CARGO_RADIUS = 6; ///< Extent of a tile area around town center when scanning for town cargo acceptance and production (6 ~= min catchmement + min station / 2)
|
||||||
|
|
||||||
/** Types of subsidy news messages, which determine how the date is printed and whether to use singular or plural cargo names */
|
|
||||||
enum class SubsidyDecodeParamType : uint8_t {
|
|
||||||
NewsOffered = 0, ///< News item for an offered subsidy
|
|
||||||
NewsAwarded = 1, ///< News item for an awarded subsidy
|
|
||||||
NewsWithdrawn = 2, ///< News item for a subsidy offer withdrawn, or expired subsidy
|
|
||||||
Gui = 3, ///< Subsidies listed in the Subsidy GUI
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* SUBSIDY_BASE_H */
|
#endif /* SUBSIDY_BASE_H */
|
||||||
|
|
|
@ -10,14 +10,10 @@
|
||||||
#ifndef SUBSIDY_FUNC_H
|
#ifndef SUBSIDY_FUNC_H
|
||||||
#define SUBSIDY_FUNC_H
|
#define SUBSIDY_FUNC_H
|
||||||
|
|
||||||
#include "core/geometry_type.hpp"
|
|
||||||
#include "station_type.h"
|
#include "station_type.h"
|
||||||
#include "company_type.h"
|
#include "company_type.h"
|
||||||
#include "cargo_type.h"
|
#include "cargo_type.h"
|
||||||
#include "news_type.h"
|
|
||||||
#include "subsidy_base.h"
|
|
||||||
|
|
||||||
std::pair<NewsReference, NewsReference> SetupSubsidyDecodeParam(const struct Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset = 0);
|
|
||||||
void DeleteSubsidyWith(Source src);
|
void DeleteSubsidyWith(Source src);
|
||||||
bool CheckSubsidised(CargoType cargo_type, CompanyID company, Source src, const Station *st);
|
bool CheckSubsidised(CargoType cargo_type, CompanyID company, Source src, const Station *st);
|
||||||
void RebuildSubsidisedSourceAndDestinationCache();
|
void RebuildSubsidisedSourceAndDestinationCache();
|
||||||
|
|
|
@ -174,18 +174,24 @@ struct SubsidyListWindow : Window {
|
||||||
if (!s->IsAwarded()) {
|
if (!s->IsAwarded()) {
|
||||||
if (IsInsideMM(pos, 0, cap)) {
|
if (IsInsideMM(pos, 0, cap)) {
|
||||||
/* Displays the two offered towns */
|
/* Displays the two offered towns */
|
||||||
SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui);
|
const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
|
||||||
|
std::string text;
|
||||||
|
|
||||||
/* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
|
/* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
|
||||||
if (TimerGameEconomy::UsingWallclockUnits()) {
|
if (TimerGameEconomy::UsingWallclockUnits()) {
|
||||||
SetDParam(7, STR_SUBSIDIES_OFFERED_EXPIRY_TIME);
|
text = GetString(STR_SUBSIDIES_OFFERED_FROM_TO,
|
||||||
SetDParam(8, s->remaining + 1); // We get the rest of the current economy month for free, since the expiration is checked on each new month.
|
cs->name, s->src.GetFormat(), s->src.id, s->dst.GetFormat(), s->dst.id,
|
||||||
|
STR_SUBSIDIES_OFFERED_EXPIRY_TIME,
|
||||||
|
s->remaining + 1); // We get the rest of the current economy month for free, since the expiration is checked on each new month.
|
||||||
} else {
|
} else {
|
||||||
SetDParam(7, STR_SUBSIDIES_OFFERED_EXPIRY_DATE);
|
text = GetString(STR_SUBSIDIES_OFFERED_FROM_TO,
|
||||||
SetDParam(8, TimerGameEconomy::date - ymd.day + s->remaining * 32);
|
cs->name, s->src.GetFormat(), s->src.id, s->dst.GetFormat(), s->dst.id,
|
||||||
|
STR_SUBSIDIES_OFFERED_EXPIRY_DATE,
|
||||||
|
TimerGameEconomy::date.base() - ymd.day + s->remaining * 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawCargoIcon(tr, pos * GetCharacterHeight(FS_NORMAL), s->cargo_type);
|
DrawCargoIcon(tr, pos * GetCharacterHeight(FS_NORMAL), s->cargo_type);
|
||||||
DrawString(sr.left, sr.right, sr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_OFFERED_FROM_TO);
|
DrawString(sr.left, sr.right, sr.top + pos * GetCharacterHeight(FS_NORMAL), text);
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
num++;
|
num++;
|
||||||
|
@ -206,21 +212,27 @@ struct SubsidyListWindow : Window {
|
||||||
for (const Subsidy *s : Subsidy::Iterate()) {
|
for (const Subsidy *s : Subsidy::Iterate()) {
|
||||||
if (s->IsAwarded()) {
|
if (s->IsAwarded()) {
|
||||||
if (IsInsideMM(pos, 0, cap)) {
|
if (IsInsideMM(pos, 0, cap)) {
|
||||||
SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui);
|
const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
|
||||||
SetDParam(7, s->awarded);
|
std::string text;
|
||||||
|
|
||||||
/* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
|
/* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
|
||||||
if (TimerGameEconomy::UsingWallclockUnits()) {
|
if (TimerGameEconomy::UsingWallclockUnits()) {
|
||||||
SetDParam(8, STR_SUBSIDIES_SUBSIDISED_EXPIRY_TIME);
|
text = GetString(STR_SUBSIDIES_SUBSIDISED_FROM_TO,
|
||||||
SetDParam(9, s->remaining);
|
cs->name, s->src.GetFormat(), s->src.id, s->dst.GetFormat(), s->dst.id,
|
||||||
}
|
GetString(STR_COMPANY_NAME, s->awarded),
|
||||||
else {
|
STR_SUBSIDIES_SUBSIDISED_EXPIRY_TIME,
|
||||||
SetDParam(8, STR_SUBSIDIES_SUBSIDISED_EXPIRY_DATE);
|
s->remaining + 1); // We get the rest of the current economy month for free, since the expiration is checked on each new month.
|
||||||
SetDParam(9, TimerGameEconomy::date - ymd.day + s->remaining * 32);
|
} else {
|
||||||
|
text = GetString(STR_SUBSIDIES_SUBSIDISED_FROM_TO,
|
||||||
|
cs->name, s->src.GetFormat(), s->src.id, s->dst.GetFormat(), s->dst.id,
|
||||||
|
GetString(STR_COMPANY_NAME, s->awarded),
|
||||||
|
STR_SUBSIDIES_SUBSIDISED_EXPIRY_DATE,
|
||||||
|
TimerGameEconomy::date.base() - ymd.day + s->remaining * 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Displays the two connected stations */
|
/* Displays the two connected stations */
|
||||||
DrawCargoIcon(tr, pos * GetCharacterHeight(FS_NORMAL), s->cargo_type);
|
DrawCargoIcon(tr, pos * GetCharacterHeight(FS_NORMAL), s->cargo_type);
|
||||||
DrawString(sr.left, sr.right, sr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_SUBSIDISED_FROM_TO);
|
DrawString(sr.left, sr.right, sr.top + pos * GetCharacterHeight(FS_NORMAL), text);
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
num++;
|
num++;
|
||||||
|
|
|
@ -12,8 +12,11 @@
|
||||||
#include "../3rdparty/catch2/catch.hpp"
|
#include "../3rdparty/catch2/catch.hpp"
|
||||||
|
|
||||||
#include "../string_func.h"
|
#include "../string_func.h"
|
||||||
|
#include "../strings_func.h"
|
||||||
#include "../table/control_codes.h"
|
#include "../table/control_codes.h"
|
||||||
|
|
||||||
|
#include "table/strings.h"
|
||||||
|
|
||||||
/**** String compare/equals *****/
|
/**** String compare/equals *****/
|
||||||
|
|
||||||
TEST_CASE("StrCompareIgnoreCase - std::string")
|
TEST_CASE("StrCompareIgnoreCase - std::string")
|
||||||
|
@ -473,3 +476,15 @@ TEST_CASE("FixSCCEncoded")
|
||||||
/* Test conversion with one sub-string and two string parameters. */
|
/* Test conversion with one sub-string and two string parameters. */
|
||||||
CHECK(FixSCCEncodedWrapper("\uE000777:\uE0008888:\"Foo\":\"BarBaz\"", false) == Compose(SCC_ENCODED, "777", SCC_RECORD_SEPARATOR, SCC_ENCODED, "8888", SCC_RECORD_SEPARATOR, SCC_ENCODED_STRING, "Foo", SCC_RECORD_SEPARATOR, SCC_ENCODED_STRING, "BarBaz"));
|
CHECK(FixSCCEncodedWrapper("\uE000777:\uE0008888:\"Foo\":\"BarBaz\"", false) == Compose(SCC_ENCODED, "777", SCC_RECORD_SEPARATOR, SCC_ENCODED, "8888", SCC_RECORD_SEPARATOR, SCC_ENCODED_STRING, "Foo", SCC_RECORD_SEPARATOR, SCC_ENCODED_STRING, "BarBaz"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("EncodedString::ReplaceParam")
|
||||||
|
{
|
||||||
|
/* Test that two encoded strings with different parameters are not the same. */
|
||||||
|
EncodedString string1 = GetEncodedString(STR_NULL, "Foo", 10, "Bar");
|
||||||
|
EncodedString string2 = GetEncodedString(STR_NULL, "Foo", 15, "Bar");
|
||||||
|
CHECK(string1 != string2);
|
||||||
|
|
||||||
|
/* Test that replacing parameter results in the same string. */
|
||||||
|
EncodedString string3 = string1.ReplaceParam(1, 15);
|
||||||
|
CHECK(string2 == string3);
|
||||||
|
}
|
||||||
|
|
|
@ -2232,15 +2232,10 @@ std::tuple<CommandCost, Money, TownID> CmdFoundTown(DoCommandFlags flags, TileIn
|
||||||
assert(!random_location);
|
assert(!random_location);
|
||||||
|
|
||||||
if (_current_company == OWNER_DEITY) {
|
if (_current_company == OWNER_DEITY) {
|
||||||
SetDParam(0, t->index);
|
AddTileNewsItem(GetEncodedString(STR_NEWS_NEW_TOWN_UNSPONSORED, t->index), NewsType::IndustryOpen, tile);
|
||||||
AddTileNewsItem(STR_NEWS_NEW_TOWN_UNSPONSORED, NewsType::IndustryOpen, tile);
|
|
||||||
} else {
|
} else {
|
||||||
std::string company_name = GetString(STR_COMPANY_NAME, _current_company);
|
std::string company_name = GetString(STR_COMPANY_NAME, _current_company);
|
||||||
|
AddTileNewsItem(GetEncodedString(STR_NEWS_NEW_TOWN, company_name, t->index), NewsType::IndustryOpen, tile);
|
||||||
SetDParamStr(0, company_name);
|
|
||||||
SetDParam(1, t->index);
|
|
||||||
|
|
||||||
AddTileNewsItem(STR_NEWS_NEW_TOWN, NewsType::IndustryOpen, tile);
|
|
||||||
}
|
}
|
||||||
AI::BroadcastNewEvent(new ScriptEventTownFounded(t->index));
|
AI::BroadcastNewEvent(new ScriptEventTownFounded(t->index));
|
||||||
Game::NewEvent(new ScriptEventTownFounded(t->index));
|
Game::NewEvent(new ScriptEventTownFounded(t->index));
|
||||||
|
@ -3411,11 +3406,8 @@ static CommandCost TownActionRoadRebuild(Town *t, DoCommandFlags flags)
|
||||||
|
|
||||||
std::string company_name = GetString(STR_COMPANY_NAME, _current_company);
|
std::string company_name = GetString(STR_COMPANY_NAME, _current_company);
|
||||||
|
|
||||||
SetDParam(0, t->index);
|
|
||||||
SetDParamStr(1, company_name);
|
|
||||||
|
|
||||||
AddNewsItem(
|
AddNewsItem(
|
||||||
TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_ROAD_REBUILDING_MINUTES : STR_NEWS_ROAD_REBUILDING_MONTHS,
|
GetEncodedString(TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_ROAD_REBUILDING_MINUTES : STR_NEWS_ROAD_REBUILDING_MONTHS, t->index, company_name),
|
||||||
NewsType::General, NewsStyle::Normal, {}, t->index);
|
NewsType::General, NewsStyle::Normal, {}, t->index);
|
||||||
AI::BroadcastNewEvent(new ScriptEventRoadReconstruction(_current_company, t->index));
|
AI::BroadcastNewEvent(new ScriptEventRoadReconstruction(_current_company, t->index));
|
||||||
Game::NewEvent(new ScriptEventRoadReconstruction(_current_company, t->index));
|
Game::NewEvent(new ScriptEventRoadReconstruction(_current_company, t->index));
|
||||||
|
@ -3566,12 +3558,10 @@ static CommandCost TownActionBuyRights(Town *t, DoCommandFlags flags)
|
||||||
SetWindowClassesDirty(WC_STATION_VIEW);
|
SetWindowClassesDirty(WC_STATION_VIEW);
|
||||||
|
|
||||||
/* Spawn news message */
|
/* Spawn news message */
|
||||||
auto cni = std::make_unique<CompanyNewsInformation>(Company::Get(_current_company));
|
auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_EXCLUSIVE_RIGHTS_TITLE, Company::Get(_current_company));
|
||||||
SetDParam(0, STR_NEWS_EXCLUSIVE_RIGHTS_TITLE);
|
EncodedString message = GetEncodedString(TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MINUTES : STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MONTHS, t->index, cni->company_name);
|
||||||
SetDParam(1, TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MINUTES : STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION_MONTHS);
|
AddNewsItem(std::move(message),
|
||||||
SetDParam(2, t->index);
|
NewsType::General, NewsStyle::Company, {}, t->index, {}, std::move(cni));
|
||||||
SetDParamStr(3, cni->company_name);
|
|
||||||
AddNewsItem(STR_MESSAGE_NEWS_FORMAT, NewsType::General, NewsStyle::Company, {}, t->index, {}, std::move(cni));
|
|
||||||
AI::BroadcastNewEvent(new ScriptEventExclusiveTransportRights(_current_company, t->index));
|
AI::BroadcastNewEvent(new ScriptEventExclusiveTransportRights(_current_company, t->index));
|
||||||
Game::NewEvent(new ScriptEventExclusiveTransportRights(_current_company, t->index));
|
Game::NewEvent(new ScriptEventExclusiveTransportRights(_current_company, t->index));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3006,9 +3006,8 @@ static void TrainEnterStation(Train *v, StationID station)
|
||||||
Station *st = Station::Get(station);
|
Station *st = Station::Get(station);
|
||||||
if (!(st->had_vehicle_of_type & HVOT_TRAIN)) {
|
if (!(st->had_vehicle_of_type & HVOT_TRAIN)) {
|
||||||
st->had_vehicle_of_type |= HVOT_TRAIN;
|
st->had_vehicle_of_type |= HVOT_TRAIN;
|
||||||
SetDParam(0, st->index);
|
|
||||||
AddVehicleNewsItem(
|
AddVehicleNewsItem(
|
||||||
STR_NEWS_FIRST_TRAIN_ARRIVAL,
|
GetEncodedString(STR_NEWS_FIRST_TRAIN_ARRIVAL, st->index),
|
||||||
v->owner == _local_company ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
v->owner == _local_company ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
|
||||||
v->index,
|
v->index,
|
||||||
st->index
|
st->index
|
||||||
|
@ -3243,8 +3242,7 @@ static bool CheckTrainCollision(Train *v)
|
||||||
/* any dead -> no crash */
|
/* any dead -> no crash */
|
||||||
if (tcc.num == 0) return false;
|
if (tcc.num == 0) return false;
|
||||||
|
|
||||||
SetDParam(0, tcc.num);
|
AddTileNewsItem(GetEncodedString(STR_NEWS_TRAIN_CRASH, tcc.num), NewsType::Accident, v->tile);
|
||||||
AddTileNewsItem(STR_NEWS_TRAIN_CRASH, NewsType::Accident, v->tile);
|
|
||||||
|
|
||||||
ModifyStationRatingAround(v->tile, v->owner, -160, 30);
|
ModifyStationRatingAround(v->tile, v->owner, -160, 30);
|
||||||
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_13_TRAIN_COLLISION, v);
|
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_13_TRAIN_COLLISION, v);
|
||||||
|
@ -4006,8 +4004,7 @@ static bool TrainLocoHandler(Train *v, bool mode)
|
||||||
if (HasBit(v->flags, VRF_TRAIN_STUCK) && v->wait_counter > 2 * _settings_game.pf.wait_for_pbs_path * Ticks::DAY_TICKS) {
|
if (HasBit(v->flags, VRF_TRAIN_STUCK) && v->wait_counter > 2 * _settings_game.pf.wait_for_pbs_path * Ticks::DAY_TICKS) {
|
||||||
/* Show message to player. */
|
/* Show message to player. */
|
||||||
if (_settings_client.gui.lost_vehicle_warn && v->owner == _local_company) {
|
if (_settings_client.gui.lost_vehicle_warn && v->owner == _local_company) {
|
||||||
SetDParam(0, v->index);
|
AddVehicleAdviceNewsItem(AdviceType::TrainStuck, GetEncodedString(STR_NEWS_TRAIN_IS_STUCK, v->index), v->index);
|
||||||
AddVehicleAdviceNewsItem(AdviceType::TrainStuck, STR_NEWS_TRAIN_IS_STUCK, v->index);
|
|
||||||
}
|
}
|
||||||
v->wait_counter = 0;
|
v->wait_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -814,8 +814,7 @@ void Vehicle::HandlePathfindingResult(bool path_found)
|
||||||
/* Notify user about the event. */
|
/* Notify user about the event. */
|
||||||
AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index));
|
AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index));
|
||||||
if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) {
|
if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) {
|
||||||
SetDParam(0, this->index);
|
AddVehicleAdviceNewsItem(AdviceType::VehicleLost, GetEncodedString(STR_NEWS_VEHICLE_IS_LOST, this->index), this->index);
|
||||||
AddVehicleAdviceNewsItem(AdviceType::VehicleLost, STR_NEWS_VEHICLE_IS_LOST, this->index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1106,9 +1105,7 @@ void CallVehicleTicks()
|
||||||
message = STR_NEWS_VEHICLE_AUTORENEW_FAILED;
|
message = STR_NEWS_VEHICLE_AUTORENEW_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDParam(0, v->index);
|
AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, GetEncodedString(message, v->index, error_message), v->index);
|
||||||
SetDParam(1, error_message);
|
|
||||||
AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, message, v->index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_company.Restore();
|
cur_company.Restore();
|
||||||
|
@ -1474,8 +1471,7 @@ void AgeVehicle(Vehicle *v)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDParam(0, v->index);
|
AddVehicleAdviceNewsItem(AdviceType::VehicleOld, GetEncodedString(str, v->index), v->index);
|
||||||
AddVehicleAdviceNewsItem(AdviceType::VehicleOld, str, v->index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1630,8 +1626,7 @@ void VehicleEnterDepot(Vehicle *v)
|
||||||
_vehicles_to_autoreplace[v->index] = false;
|
_vehicles_to_autoreplace[v->index] = false;
|
||||||
if (v->owner == _local_company) {
|
if (v->owner == _local_company) {
|
||||||
/* Notify the user that we stopped the vehicle */
|
/* Notify the user that we stopped the vehicle */
|
||||||
SetDParam(0, v->index);
|
AddVehicleAdviceNewsItem(AdviceType::RefitFailed, GetEncodedString(STR_NEWS_ORDER_REFIT_FAILED, v->index), v->index);
|
||||||
AddVehicleAdviceNewsItem(AdviceType::RefitFailed, STR_NEWS_ORDER_REFIT_FAILED, v->index);
|
|
||||||
}
|
}
|
||||||
} else if (cost.GetCost() != 0) {
|
} else if (cost.GetCost() != 0) {
|
||||||
v->profit_this_year -= cost.GetCost() << 8;
|
v->profit_this_year -= cost.GetCost() << 8;
|
||||||
|
@ -1660,8 +1655,7 @@ void VehicleEnterDepot(Vehicle *v)
|
||||||
|
|
||||||
/* Announce that the vehicle is waiting to players and AIs. */
|
/* Announce that the vehicle is waiting to players and AIs. */
|
||||||
if (v->owner == _local_company) {
|
if (v->owner == _local_company) {
|
||||||
SetDParam(0, v->index);
|
AddVehicleAdviceNewsItem(AdviceType::VehicleWaiting, GetEncodedString(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index), v->index);
|
||||||
AddVehicleAdviceNewsItem(AdviceType::VehicleWaiting, STR_NEWS_TRAIN_IS_WAITING + v->type, v->index);
|
|
||||||
}
|
}
|
||||||
AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index));
|
AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index));
|
||||||
}
|
}
|
||||||
|
@ -3022,10 +3016,8 @@ static IntervalTimer<TimerGameEconomy> _economy_vehicles_yearly({TimerGameEconom
|
||||||
Money profit = v->GetDisplayProfitThisYear();
|
Money profit = v->GetDisplayProfitThisYear();
|
||||||
if (v->economy_age >= VEHICLE_PROFIT_MIN_AGE && profit < 0) {
|
if (v->economy_age >= VEHICLE_PROFIT_MIN_AGE && profit < 0) {
|
||||||
if (_settings_client.gui.vehicle_income_warn && v->owner == _local_company) {
|
if (_settings_client.gui.vehicle_income_warn && v->owner == _local_company) {
|
||||||
SetDParam(0, v->index);
|
|
||||||
SetDParam(1, profit);
|
|
||||||
AddVehicleAdviceNewsItem(AdviceType::VehicleUnprofitable,
|
AddVehicleAdviceNewsItem(AdviceType::VehicleUnprofitable,
|
||||||
TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD : STR_NEWS_VEHICLE_UNPROFITABLE_YEAR,
|
GetEncodedString(TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD : STR_NEWS_VEHICLE_UNPROFITABLE_YEAR, v->index, profit),
|
||||||
v->index);
|
v->index);
|
||||||
}
|
}
|
||||||
AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index));
|
AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index));
|
||||||
|
|
|
@ -1007,8 +1007,7 @@ static void FloodVehicle(Vehicle *v)
|
||||||
|
|
||||||
AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims));
|
AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims));
|
||||||
Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims));
|
Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims));
|
||||||
SetDParam(0, victims);
|
AddTileNewsItem(GetEncodedString(STR_NEWS_DISASTER_FLOOD_VEHICLE, victims), NewsType::Accident, v->tile);
|
||||||
AddTileNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, NewsType::Accident, v->tile);
|
|
||||||
CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
|
CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
|
||||||
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue