Codechange: put SourceType and SourceID into Source struct

This commit is contained in:
Rubidium 2025-02-05 20:15:11 +01:00 committed by rubidium42
parent 95bfd68341
commit 5f41bc0279
20 changed files with 180 additions and 199 deletions

View File

@ -141,4 +141,12 @@ enum class SourceType : uint8_t {
typedef uint16_t SourceID; ///< Contains either industry ID, town ID or company ID (or INVALID_SOURCE)
static const SourceID INVALID_SOURCE = 0xFFFF; ///< Invalid/unknown index of source
/** A location from where cargo can come from (or go to). Specifically industries, towns and headquarters. */
struct Source {
SourceID id; ///< Index of industry/town/HQ, INVALID_SOURCE if unknown/invalid.
SourceType type; ///< Type of \c source_id.
auto operator<=>(const Source &source) const = default;
};
#endif /* CARGO_TYPE_H */

View File

@ -110,26 +110,25 @@ int32_t GetPickupAmount(CargoMonitorID monitor, bool keep_monitoring)
* @param cargo_type type of cargo.
* @param company company delivering the cargo.
* @param amount Amount of cargo delivered.
* @param src_type type of \a src.
* @param src index of source.
* @param src source of cargo.
* @param st station where the cargo is delivered to.
* @param dest industry index where the cargo is delivered to.
*/
void AddCargoDelivery(CargoType cargo_type, CompanyID company, uint32_t amount, SourceType src_type, SourceID src, const Station *st, IndustryID dest)
void AddCargoDelivery(CargoType cargo_type, CompanyID company, uint32_t amount, Source src, const Station *st, IndustryID dest)
{
if (amount == 0) return;
if (src != INVALID_SOURCE) {
if (src.id != INVALID_SOURCE) {
/* Handle pickup update. */
switch (src_type) {
switch (src.type) {
case SourceType::Industry: {
CargoMonitorID num = EncodeCargoIndustryMonitor(company, cargo_type, src);
CargoMonitorID num = EncodeCargoIndustryMonitor(company, cargo_type, src.id);
CargoMonitorMap::iterator iter = _cargo_pickups.find(num);
if (iter != _cargo_pickups.end()) iter->second += amount;
break;
}
case SourceType::Town: {
CargoMonitorID num = EncodeCargoTownMonitor(company, cargo_type, src);
CargoMonitorID num = EncodeCargoTownMonitor(company, cargo_type, src.id);
CargoMonitorMap::iterator iter = _cargo_pickups.find(num);
if (iter != _cargo_pickups.end()) iter->second += amount;
break;

View File

@ -143,6 +143,6 @@ void ClearCargoPickupMonitoring(CompanyID company = INVALID_OWNER);
void ClearCargoDeliveryMonitoring(CompanyID company = INVALID_OWNER);
int32_t GetDeliveryAmount(CargoMonitorID monitor, bool keep_monitoring);
int32_t GetPickupAmount(CargoMonitorID monitor, bool keep_monitoring);
void AddCargoDelivery(CargoType cargo_type, CompanyID company, uint32_t amount, SourceType src_type, SourceID src, const Station *st, IndustryID dest = INVALID_INDUSTRY);
void AddCargoDelivery(CargoType cargo_type, CompanyID company, uint32_t amount, Source src, const Station *st, IndustryID dest = INVALID_INDUSTRY);
#endif /* CARGOMONITOR_H */

View File

@ -26,8 +26,6 @@ INSTANTIATE_POOL_METHODS(CargoPacket)
*/
CargoPacket::CargoPacket()
{
this->source_type = SourceType::Industry;
this->source_id = INVALID_SOURCE;
}
/**
@ -35,14 +33,12 @@ CargoPacket::CargoPacket()
*
* @param first_station Source station of the packet.
* @param count Number of cargo entities to put in this packet.
* @param source_type 'Type' of source the packet comes from (for subsidies).
* @param source_id Actual source of the packet (for subsidies).
* @param source Source of the packet (for subsidies).
* @pre count != 0
*/
CargoPacket::CargoPacket(StationID first_station,uint16_t count, SourceType source_type, SourceID source_id) :
CargoPacket::CargoPacket(StationID first_station,uint16_t count, Source source) :
count(count),
source_id(source_id),
source_type(source_type),
source(source),
first_station(first_station)
{
assert(count != 0);
@ -80,8 +76,7 @@ CargoPacket::CargoPacket(uint16_t count, Money feeder_share, CargoPacket &origin
feeder_share(feeder_share),
source_xy(original.source_xy),
travelled(original.travelled),
source_id(original.source_id),
source_type(original.source_type),
source(original.source),
#ifdef WITH_ASSERT
in_vehicle(original.in_vehicle),
#endif /* WITH_ASSERT */
@ -134,10 +129,10 @@ void CargoPacket::Reduce(uint count)
* @param src_type Type of source.
* @param src Index of source.
*/
/* static */ void CargoPacket::InvalidateAllFrom(SourceType src_type, SourceID src)
/* static */ void CargoPacket::InvalidateAllFrom(Source src)
{
for (CargoPacket *cp : CargoPacket::Iterate()) {
if (cp->source_type == src_type && cp->source_id == src) cp->source_id = INVALID_SOURCE;
if (cp->source == src) cp->source.id = INVALID_SOURCE;
}
}

View File

@ -53,8 +53,7 @@ private:
TileIndex source_xy = INVALID_TILE; ///< The origin of the cargo.
Vector travelled{0, 0}; ///< If cargo is in station: the vector from the unload tile to the source tile. If in vehicle: an intermediate value.
SourceID source_id = INVALID_SOURCE; ///< Index of industry/town/HQ, INVALID_SOURCE if unknown/invalid.
SourceType source_type = SourceType::Industry; ///< Type of \c source_id.
Source source{INVALID_SOURCE, SourceType::Industry}; ///< Source of the cargo
#ifdef WITH_ASSERT
bool in_vehicle = false; ///< NOSAVE: Whether this cargo is in a vehicle or not.
@ -74,7 +73,7 @@ public:
static const uint16_t MAX_COUNT = UINT16_MAX;
CargoPacket();
CargoPacket(StationID first_station, uint16_t count, SourceType source_type, SourceID source_id);
CargoPacket(StationID first_station, uint16_t count, Source source);
CargoPacket(uint16_t count, uint16_t periods_in_transit, StationID first_station, TileIndex source_xy, Money feeder_share);
CargoPacket(uint16_t count, Money feeder_share, CargoPacket &original);
@ -194,21 +193,12 @@ public:
}
/**
* Gets the type of the cargo's source. industry, town or head quarter.
* @return Source type.
* Gets the source of the packet for subsidy purposes.
* @return The source.
*/
inline SourceType GetSourceType() const
inline Source GetSource() const
{
return this->source_type;
}
/**
* Gets the ID of the cargo's source. An IndustryID, TownID or CompanyID.
* @return Source ID.
*/
inline SourceID GetSourceID() const
{
return this->source_id;
return this->source;
}
/**
@ -270,7 +260,7 @@ public:
return this->next_hop;
}
static void InvalidateAllFrom(SourceType src_type, SourceID src);
static void InvalidateAllFrom(Source src);
static void InvalidateAllFrom(StationID sid);
static void AfterLoad();
};
@ -514,9 +504,9 @@ public:
{
return cp1->source_xy == cp2->source_xy &&
cp1->periods_in_transit == cp2->periods_in_transit &&
cp1->source_type == cp2->source_type &&
cp1->source.type == cp2->source.type &&
cp1->first_station == cp2->first_station &&
cp1->source_id == cp2->source_id;
cp1->source.id == cp2->source.id;
}
};
@ -547,7 +537,7 @@ public:
friend class CargoReturn;
friend class StationCargoReroute;
static void InvalidateAllFrom(SourceType src_type, SourceID src);
static void InvalidateAllFrom(Source src);
template <class Taction>
bool ShiftCargo(Taction &action, StationID next);
@ -629,9 +619,8 @@ public:
{
return cp1->source_xy == cp2->source_xy &&
cp1->periods_in_transit == cp2->periods_in_transit &&
cp1->source_type == cp2->source_type &&
cp1->first_station == cp2->first_station &&
cp1->source_id == cp2->source_id;
cp1->source == cp2->source;
}
};

View File

@ -1089,7 +1089,7 @@ static uint DeliverGoodsToIndustry(const Station *st, CargoType cargo_type, uint
accepted += amount;
/* Update the cargo monitor. */
AddCargoDelivery(cargo_type, company, amount, SourceType::Industry, source, st, ind->index);
AddCargoDelivery(cargo_type, company, amount, {source, SourceType::Industry}, st, ind->index);
}
return accepted;
@ -1103,19 +1103,18 @@ static uint DeliverGoodsToIndustry(const Station *st, CargoType cargo_type, uint
* @param distance The distance the cargo has traveled.
* @param periods_in_transit Travel time in cargo aging periods
* @param company The company delivering the cargo
* @param src_type Type of source of cargo (industry, town, headquarters)
* @param src Index of source of cargo
* @param src Source of cargo
* @return Revenue for delivering cargo
* @note The cargo is just added to the stockpile of the industry. It is due to the caller to trigger the industry's production machinery
*/
static Money DeliverGoods(int num_pieces, CargoType cargo_type, StationID dest, uint distance, uint16_t periods_in_transit, Company *company, SourceType src_type, SourceID src)
static Money DeliverGoods(int num_pieces, CargoType cargo_type, StationID dest, uint distance, uint16_t periods_in_transit, Company *company, Source src)
{
assert(num_pieces > 0);
Station *st = Station::Get(dest);
/* Give the goods to the industry. */
uint accepted_ind = DeliverGoodsToIndustry(st, cargo_type, num_pieces, src_type == SourceType::Industry ? src : INVALID_INDUSTRY, company->index);
uint accepted_ind = DeliverGoodsToIndustry(st, cargo_type, num_pieces, src.type == SourceType::Industry ? src.id : INVALID_INDUSTRY, company->index);
/* If this cargo type is always accepted, accept all */
uint accepted_total = HasBit(st->always_accepted, cargo_type) ? num_pieces : accepted_ind;
@ -1138,10 +1137,10 @@ static Money DeliverGoods(int num_pieces, CargoType cargo_type, StationID dest,
Money profit = GetTransportedGoodsIncome(accepted_total, distance, periods_in_transit, cargo_type);
/* Update the cargo monitor. */
AddCargoDelivery(cargo_type, company->index, accepted_total - accepted_ind, src_type, src, st);
AddCargoDelivery(cargo_type, company->index, accepted_total - accepted_ind, src, st);
/* Modify profit if a subsidy is in effect */
if (CheckSubsidised(cargo_type, company->index, src_type, src, st)) {
if (CheckSubsidised(cargo_type, company->index, src, st)) {
switch (_settings_game.difficulty.subsidy_multiplier) {
case 0: profit += profit >> 1; break;
case 1: profit *= 2; break;
@ -1240,7 +1239,7 @@ void CargoPayment::PayFinalDelivery(CargoType cargo, const CargoPacket *cp, uint
}
/* Handle end of route payment */
Money profit = DeliverGoods(count, cargo, this->current_station, cp->GetDistance(current_tile), cp->GetPeriodsInTransit(), this->owner, cp->GetSourceType(), cp->GetSourceID());
Money profit = DeliverGoods(count, cargo, this->current_station, cp->GetDistance(current_tile), cp->GetPeriodsInTransit(), this->owner, cp->GetSource());
this->route_profit += profit;
/* The vehicle's profit is whatever route profit there is minus feeder shares. */

View File

@ -31,7 +31,7 @@ int UpdateCompanyRatingAndValue(Company *c, bool update);
void StartupIndustryDailyChanges(bool init_counter);
Money GetTransportedGoodsIncome(uint num_pieces, uint dist, uint16_t transit_periods, CargoType cargo_type);
uint MoveGoodsToStation(CargoType type, uint amount, SourceType source_type, SourceID source_id, const StationList &all_stations, Owner exclusivity = INVALID_OWNER);
uint MoveGoodsToStation(CargoType type, uint amount, Source source, const StationList &all_stations, Owner exclusivity = INVALID_OWNER);
void PrepareUnload(Vehicle *front_v);
void LoadUnloadStation(Station *st);

View File

@ -197,8 +197,9 @@ Industry::~Industry()
CloseWindowById(WC_INDUSTRY_VIEW, this->index);
DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index);
DeleteSubsidyWith(SourceType::Industry, this->index);
CargoPacket::InvalidateAllFrom(SourceType::Industry, this->index);
Source src{this->index, SourceType::Industry};
DeleteSubsidyWith(src);
CargoPacket::InvalidateAllFrom(src);
for (Station *st : this->stations_near) {
st->RemoveIndustryToDeliver(this);
@ -537,7 +538,7 @@ static bool TransportIndustryGoods(TileIndex tile)
p.history[THIS_MONTH].production += cw;
uint am = MoveGoodsToStation(p.cargo, cw, SourceType::Industry, i->index, i->stations_near, i->exclusive_consumer);
uint am = MoveGoodsToStation(p.cargo, cw, {i->index, SourceType::Industry}, i->stations_near, i->exclusive_consumer);
p.history[THIS_MONTH].transported += am;
moved_cargo |= (am != 0);

View File

@ -591,7 +591,7 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags)
if (flags & DC_EXEC) {
c->location_of_HQ = INVALID_TILE; // reset HQ position
SetWindowDirty(WC_COMPANY, c->index);
CargoPacket::InvalidateAllFrom(SourceType::Headquarters, c->index);
CargoPacket::InvalidateAllFrom({c->index, SourceType::Headquarters});
}
/* cost of relocating company is 1% of company value */
@ -704,13 +704,13 @@ static void TileLoop_Object(TileIndex tile)
/* Scale by cargo scale setting. */
amt = ScaleByCargoScale(amt, true);
MoveGoodsToStation(pass, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
MoveGoodsToStation(pass, amt, {GetTileOwner(tile), SourceType::Headquarters}, stations.GetStations());
}
/* Top town building generates 90, HQ can make up to 196. The
* proportion passengers:mail is about the same as in the acceptance
* equations. */
CargoType mail = GetCargoTypeByLabel(CT_MAIL);
CargoType mail = GetCargoTypeByLabel(CT_MAIL);
if (IsValidCargoType(mail) && GB(r, 8, 8) < (196 / 4 / (6 - level))) {
uint amt = GB(r, 8, 8) / 8 / 4 + 1;
@ -720,7 +720,7 @@ static void TileLoop_Object(TileIndex tile)
/* Scale by cargo scale setting. */
amt = ScaleByCargoScale(amt, true);
MoveGoodsToStation(mail, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
MoveGoodsToStation(mail, amt, {GetTileOwner(tile), SourceType::Headquarters}, stations.GetStations());
}
}

View File

@ -2279,20 +2279,20 @@ bool AfterLoadGame()
case TAE_PASSENGERS:
case TAE_MAIL:
/* Town -> Town */
s->src_type = s->dst_type = SourceType::Town;
if (Town::IsValidID(s->src) && Town::IsValidID(s->dst)) continue;
s->src.type = s->dst.type = SourceType::Town;
if (Town::IsValidID(s->src.id) && Town::IsValidID(s->dst.id)) continue;
break;
case TAE_GOODS:
case TAE_FOOD:
/* Industry -> Town */
s->src_type = SourceType::Industry;
s->dst_type = SourceType::Town;
if (Industry::IsValidID(s->src) && Town::IsValidID(s->dst)) continue;
s->src.type = SourceType::Industry;
s->dst.type = SourceType::Town;
if (Industry::IsValidID(s->src.id) && Town::IsValidID(s->dst.id)) continue;
break;
default:
/* Industry -> Industry */
s->src_type = s->dst_type = SourceType::Industry;
if (Industry::IsValidID(s->src) && Industry::IsValidID(s->dst)) continue;
s->src.type = s->dst.type = SourceType::Industry;
if (Industry::IsValidID(s->src.id) && Industry::IsValidID(s->dst.id)) continue;
break;
}
} else {
@ -2305,13 +2305,13 @@ bool AfterLoadGame()
case TAE_PASSENGERS:
case TAE_MAIL: {
/* Town -> Town */
const Station *ss = Station::GetIfValid(s->src);
const Station *sd = Station::GetIfValid(s->dst);
const Station *ss = Station::GetIfValid(s->src.id);
const Station *sd = Station::GetIfValid(s->dst.id);
if (ss != nullptr && sd != nullptr && ss->owner == sd->owner &&
Company::IsValidID(ss->owner)) {
s->src_type = s->dst_type = SourceType::Town;
s->src = ss->town->index;
s->dst = sd->town->index;
s->src.type = s->dst.type = SourceType::Town;
s->src.id = ss->town->index;
s->dst.id = sd->town->index;
s->awarded = ss->owner;
continue;
}

View File

@ -134,8 +134,8 @@ SaveLoadTable GetCargoPacketDesc()
SLE_CONDVARNAME(CargoPacket, periods_in_transit, "days_in_transit", SLE_UINT16, SLV_MORE_CARGO_AGE, SLV_PERIODS_IN_TRANSIT_RENAME),
SLE_CONDVAR(CargoPacket, periods_in_transit, SLE_UINT16, SLV_PERIODS_IN_TRANSIT_RENAME, SL_MAX_VERSION),
SLE_VAR(CargoPacket, feeder_share, SLE_INT64),
SLE_CONDVAR(CargoPacket, source_type, SLE_UINT8, SLV_125, SL_MAX_VERSION),
SLE_CONDVAR(CargoPacket, source_id, SLE_UINT16, SLV_125, SL_MAX_VERSION),
SLE_CONDVARNAME(CargoPacket, source.type, "source_type", SLE_UINT8, SLV_125, SL_MAX_VERSION),
SLE_CONDVARNAME(CargoPacket, source.id, "source_id", SLE_UINT16, SLV_125, SL_MAX_VERSION),
SLE_CONDVAR(CargoPacket, travelled.x, SLE_INT16, SLV_CARGO_TRAVELLED, SL_MAX_VERSION),
SLE_CONDVAR(CargoPacket, travelled.y, SLE_INT16, SLV_CARGO_TRAVELLED, SL_MAX_VERSION),
};

View File

@ -21,12 +21,12 @@ static const SaveLoad _subsidies_desc[] = {
SLE_CONDVAR(Subsidy, remaining, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_CUSTOM_SUBSIDY_DURATION),
SLE_CONDVAR(Subsidy, remaining, SLE_UINT16, SLV_CUSTOM_SUBSIDY_DURATION, SL_MAX_VERSION),
SLE_CONDVAR(Subsidy, awarded, SLE_UINT8, SLV_125, SL_MAX_VERSION),
SLE_CONDVAR(Subsidy, src_type, SLE_UINT8, SLV_125, SL_MAX_VERSION),
SLE_CONDVAR(Subsidy, dst_type, SLE_UINT8, SLV_125, SL_MAX_VERSION),
SLE_CONDVAR(Subsidy, src, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
SLE_CONDVAR(Subsidy, src, SLE_UINT16, SLV_5, SL_MAX_VERSION),
SLE_CONDVAR(Subsidy, dst, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
SLE_CONDVAR(Subsidy, dst, SLE_UINT16, SLV_5, SL_MAX_VERSION),
SLE_CONDVARNAME(Subsidy, src.type, "src_type", SLE_UINT8, SLV_125, SL_MAX_VERSION),
SLE_CONDVARNAME(Subsidy, dst.type, "dst_type", SLE_UINT8, SLV_125, SL_MAX_VERSION),
SLE_CONDVARNAME(Subsidy, src.id, "src", SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
SLE_CONDVARNAME(Subsidy, src.id, "src", SLE_UINT16, SLV_5, SL_MAX_VERSION),
SLE_CONDVARNAME(Subsidy, dst.id, "dst", SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
SLE_CONDVARNAME(Subsidy, dst.id, "dst", SLE_UINT16, SLV_5, SL_MAX_VERSION),
};
struct SUBSChunkHandler : ChunkHandler {

View File

@ -40,7 +40,10 @@
EnforcePrecondition(false, (from_type == SPT_INDUSTRY && ScriptIndustry::IsValidIndustry(from_id)) || (from_type == SPT_TOWN && ScriptTown::IsValidTown(from_id)));
EnforcePrecondition(false, (to_type == SPT_INDUSTRY && ScriptIndustry::IsValidIndustry(to_id)) || (to_type == SPT_TOWN && ScriptTown::IsValidTown(to_id)));
return ScriptObject::Command<CMD_CREATE_SUBSIDY>::Do(cargo_type, (::SourceType)from_type, from_id, (::SourceType)to_type, to_id);
Source from{static_cast<SourceID>(from_id), static_cast<SourceType>(from_type)};
Source to{static_cast<SourceID>(to_id), static_cast<SourceType>(to_type)};
return ScriptObject::Command<CMD_CREATE_SUBSIDY>::Do(cargo_type, from, to);
}
/* static */ ScriptCompany::CompanyID ScriptSubsidy::GetAwardedTo(SubsidyID subsidy_id)
@ -74,26 +77,26 @@
{
if (!IsValidSubsidy(subsidy_id)) return SPT_INVALID;
return (SubsidyParticipantType)(uint)::Subsidy::Get(subsidy_id)->src_type;
return static_cast<SubsidyParticipantType>(::Subsidy::Get(subsidy_id)->src.type);
}
/* static */ SQInteger ScriptSubsidy::GetSourceIndex(SubsidyID subsidy_id)
{
if (!IsValidSubsidy(subsidy_id)) return INVALID_SOURCE;
return ::Subsidy::Get(subsidy_id)->src;
return ::Subsidy::Get(subsidy_id)->src.id;
}
/* static */ ScriptSubsidy::SubsidyParticipantType ScriptSubsidy::GetDestinationType(SubsidyID subsidy_id)
{
if (!IsValidSubsidy(subsidy_id)) return SPT_INVALID;
return (SubsidyParticipantType)(uint)::Subsidy::Get(subsidy_id)->dst_type;
return static_cast<SubsidyParticipantType>(::Subsidy::Get(subsidy_id)->dst.type);
}
/* static */ SQInteger ScriptSubsidy::GetDestinationIndex(SubsidyID subsidy_id)
{
if (!IsValidSubsidy(subsidy_id)) return INVALID_SOURCE;
return ::Subsidy::Get(subsidy_id)->dst;
return ::Subsidy::Get(subsidy_id)->dst.id;
}

View File

@ -4246,7 +4246,7 @@ void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint rad
});
}
static uint UpdateStationWaiting(Station *st, CargoType type, uint amount, SourceType source_type, SourceID source_id)
static uint UpdateStationWaiting(Station *st, CargoType type, uint amount, Source source)
{
/* We can't allocate a CargoPacket? Then don't do anything
* at all; i.e. just discard the incoming cargo. */
@ -4261,7 +4261,7 @@ static uint UpdateStationWaiting(Station *st, CargoType type, uint amount, Sourc
if (amount == 0) return 0;
StationID next = ge.GetVia(st->index);
ge.GetOrCreateData().cargo.Append(new CargoPacket(st->index, amount, source_type, source_id), next);
ge.GetOrCreateData().cargo.Append(new CargoPacket(st->index, amount, source), next);
LinkGraph *lg = nullptr;
if (ge.link_graph == INVALID_LINK_GRAPH) {
if (LinkGraph::CanAllocateItem()) {
@ -4391,7 +4391,7 @@ static bool CanMoveGoodsToStation(const Station *st, CargoType type)
return true;
}
uint MoveGoodsToStation(CargoType type, uint amount, SourceType source_type, SourceID source_id, const StationList &all_stations, Owner exclusivity)
uint MoveGoodsToStation(CargoType type, uint amount, Source source, const StationList &all_stations, Owner exclusivity)
{
/* Return if nothing to do. Also the rounding below fails for 0. */
if (all_stations.empty()) return 0;
@ -4424,7 +4424,7 @@ uint MoveGoodsToStation(CargoType type, uint amount, SourceType source_type, Sou
if (used_stations.empty()) {
/* only one station around */
amount *= first_station->goods[type].rating + 1;
return UpdateStationWaiting(first_station, type, amount, source_type, source_id);
return UpdateStationWaiting(first_station, type, amount, source);
}
uint company_best[OWNER_NONE + 1] = {}; // best rating for each company, including OWNER_NONE
@ -4470,7 +4470,7 @@ uint MoveGoodsToStation(CargoType type, uint amount, SourceType source_type, Sou
uint moved = 0;
for (auto &p : used_stations) {
moved += UpdateStationWaiting(p.first, type, p.second, source_type, source_id);
moved += UpdateStationWaiting(p.first, type, p.second, source);
}
return moved;

View File

@ -57,7 +57,7 @@ void Subsidy::AwardTo(CompanyID company)
AddNewsItem(
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier,
NewsType::Subsidies, NewsStyle::Normal, {},
reftype.first, this->src, reftype.second, this->dst
reftype.first, this->src.id, reftype.second, this->dst.id
);
AI::BroadcastNewEvent(new ScriptEventSubsidyAwarded(this->index));
Game::NewEvent(new ScriptEventSubsidyAwarded(this->index));
@ -81,7 +81,7 @@ std::pair<NewsReferenceType, NewsReferenceType> SetupSubsidyDecodeParam(const Su
const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
SetDParam(parameter_offset, cs->name);
switch (s->src_type) {
switch (s->src.type) {
case SourceType::Industry:
reftype1 = NewsReferenceType::Industry;
SetDParam(parameter_offset + 1, STR_INDUSTRY_NAME);
@ -92,9 +92,9 @@ std::pair<NewsReferenceType, NewsReferenceType> SetupSubsidyDecodeParam(const Su
break;
default: NOT_REACHED();
}
SetDParam(parameter_offset + 2, s->src);
SetDParam(parameter_offset + 2, s->src.id);
switch (s->dst_type) {
switch (s->dst.type) {
case SourceType::Industry:
reftype2 = NewsReferenceType::Industry;
SetDParam(parameter_offset + 4, STR_INDUSTRY_NAME);
@ -105,7 +105,7 @@ std::pair<NewsReferenceType, NewsReferenceType> SetupSubsidyDecodeParam(const Su
break;
default: NOT_REACHED();
}
SetDParam(parameter_offset + 5, s->dst);
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) {
@ -117,15 +117,14 @@ std::pair<NewsReferenceType, NewsReferenceType> SetupSubsidyDecodeParam(const Su
/**
* Sets a flag indicating that given town/industry is part of subsidised route.
* @param type is it a town or an industry?
* @param index index of town/industry
* @param source actual source
* @param flag flag to set
*/
static inline void SetPartOfSubsidyFlag(SourceType type, SourceID index, PartOfSubsidy flag)
static inline void SetPartOfSubsidyFlag(Source source, PartOfSubsidy flag)
{
switch (type) {
case SourceType::Industry: Industry::Get(index)->part_of_subsidy |= flag; return;
case SourceType::Town: Town::Get(index)->cache.part_of_subsidy |= flag; return;
switch (source.type) {
case SourceType::Industry: Industry::Get(source.id)->part_of_subsidy |= flag; return;
case SourceType::Town: Town::Get(source.id)->cache.part_of_subsidy |= flag; return;
default: NOT_REACHED();
}
}
@ -138,22 +137,21 @@ void RebuildSubsidisedSourceAndDestinationCache()
for (Industry *i : Industry::Iterate()) i->part_of_subsidy = POS_NONE;
for (const Subsidy *s : Subsidy::Iterate()) {
SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC);
SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST);
SetPartOfSubsidyFlag(s->src, POS_SRC);
SetPartOfSubsidyFlag(s->dst, POS_DST);
}
}
/**
* Delete the subsidies associated with a given cargo source type and id.
* @param type Cargo source type of the id.
* @param index Id to remove.
* @param source The source to look for.
*/
void DeleteSubsidyWith(SourceType type, SourceID index)
void DeleteSubsidyWith(Source source)
{
bool dirty = false;
for (Subsidy *s : Subsidy::Iterate()) {
if ((s->src_type == type && s->src == index) || (s->dst_type == type && s->dst == index)) {
if (s->src == source || s->dst == source) {
delete s;
dirty = true;
}
@ -168,18 +166,14 @@ void DeleteSubsidyWith(SourceType type, SourceID index)
/**
* Check whether a specific subsidy already exists.
* @param cargo Cargo type.
* @param src_type Type of source of the cargo, affects interpretation of \a src.
* @param src Id of the source.
* @param dst_type Type of the destination of the cargo, affects interpretation of \a dst.
* @param dst Id of the destination.
* @param src The source.
* @param dst The destination.
* @return \c true if the subsidy already exists, \c false if not.
*/
static bool CheckSubsidyDuplicate(CargoType cargo, SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
static bool CheckSubsidyDuplicate(CargoType cargo, Source src, Source dst)
{
for (const Subsidy *s : Subsidy::Iterate()) {
if (s->cargo_type == cargo &&
s->src_type == src_type && s->src == src &&
s->dst_type == dst_type && s->dst == dst) {
if (s->cargo_type == cargo && s->src == src && s->dst == dst) {
return true;
}
}
@ -188,43 +182,37 @@ static bool CheckSubsidyDuplicate(CargoType cargo, SourceType src_type, SourceID
/**
* Checks if the source and destination of a subsidy are inside the distance limit.
* @param src_type Type of \a src.
* @param src Index of source.
* @param dst_type Type of \a dst.
* @param dst Index of destination.
* @param src Source of cargo.
* @param dst Destination of cargo.
* @return True if they are inside the distance limit.
*/
static bool CheckSubsidyDistance(SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
static bool CheckSubsidyDistance(Source src, Source dst)
{
TileIndex tile_src = (src_type == SourceType::Town) ? Town::Get(src)->xy : Industry::Get(src)->location.tile;
TileIndex tile_dst = (dst_type == SourceType::Town) ? Town::Get(dst)->xy : Industry::Get(dst)->location.tile;
TileIndex tile_src = (src.type == SourceType::Town) ? Town::Get(src.id)->xy : Industry::Get(src.id)->location.tile;
TileIndex tile_dst = (dst.type == SourceType::Town) ? Town::Get(dst.id)->xy : Industry::Get(dst.id)->location.tile;
return (DistanceManhattan(tile_src, tile_dst) <= SUBSIDY_MAX_DISTANCE);
}
/**
* Creates a subsidy with the given parameters.
* @param cargo_type Subsidised cargo.
* @param src_type Type of \a src.
* @param src Index of source.
* @param dst_type Type of \a dst.
* @param dst Index of destination.
* @param cargo_type Subsidised cargo.
* @param src Source of cargo.
* @param dst Destination of cargo.
*/
void CreateSubsidy(CargoType cargo_type, SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
void CreateSubsidy(CargoType cargo_type, Source src, Source dst)
{
Subsidy *s = new Subsidy();
s->cargo_type = cargo_type;
s->src_type = src_type;
s->src = src;
s->dst_type = dst_type;
s->dst = dst;
s->remaining = SUBSIDY_OFFER_MONTHS;
s->awarded = INVALID_COMPANY;
std::pair<NewsReferenceType, NewsReferenceType> reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsOffered);
AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NewsType::Subsidies, NewsStyle::Normal, {}, reftype.first, s->src, reftype.second, s->dst);
SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC);
SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST);
AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NewsType::Subsidies, NewsStyle::Normal, {}, reftype.first, s->src.id, reftype.second, s->dst.id);
SetPartOfSubsidyFlag(s->src, POS_SRC);
SetPartOfSubsidyFlag(s->dst, POS_DST);
AI::BroadcastNewEvent(new ScriptEventSubsidyOffer(s->index));
Game::NewEvent(new ScriptEventSubsidyOffer(s->index));
@ -235,13 +223,11 @@ void CreateSubsidy(CargoType cargo_type, SourceType src_type, SourceID src, Sour
* Create a new subsidy.
* @param flags type of operation
* @param cargo_type CargoType of subsidy.
* @param src_type SourceType of source.
* @param src SourceID of source.
* @param dst_type SourceType of destination.
* @param dst SourceID of destination.
* @param src Source.
* @param dst Destination.
* @return the cost of this operation or an error
*/
CommandCost CmdCreateSubsidy(DoCommandFlag flags, CargoType cargo_type, SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
CommandCost CmdCreateSubsidy(DoCommandFlag flags, CargoType cargo_type, Source src, Source dst)
{
if (!Subsidy::CanAllocateItem()) return CMD_ERROR;
@ -249,29 +235,29 @@ CommandCost CmdCreateSubsidy(DoCommandFlag flags, CargoType cargo_type, SourceTy
if (cargo_type >= NUM_CARGO || !::CargoSpec::Get(cargo_type)->IsValid()) return CMD_ERROR;
switch (src_type) {
switch (src.type) {
case SourceType::Town:
if (!Town::IsValidID(src)) return CMD_ERROR;
if (!Town::IsValidID(src.id)) return CMD_ERROR;
break;
case SourceType::Industry:
if (!Industry::IsValidID(src)) return CMD_ERROR;
if (!Industry::IsValidID(src.id)) return CMD_ERROR;
break;
default:
return CMD_ERROR;
}
switch (dst_type) {
switch (dst.type) {
case SourceType::Town:
if (!Town::IsValidID(dst)) return CMD_ERROR;
if (!Town::IsValidID(dst.id)) return CMD_ERROR;
break;
case SourceType::Industry:
if (!Industry::IsValidID(dst)) return CMD_ERROR;
if (!Industry::IsValidID(dst.id)) return CMD_ERROR;
break;
default:
return CMD_ERROR;
}
if (flags & DC_EXEC) {
CreateSubsidy(cargo_type, src_type, src, dst_type, dst);
CreateSubsidy(cargo_type, src, dst);
}
return CommandCost();
@ -301,14 +287,14 @@ bool FindSubsidyPassengerRoute()
}
if (DistanceManhattan(src->xy, dst->xy) > SUBSIDY_MAX_DISTANCE) return false;
if (CheckSubsidyDuplicate(cargo_type, SourceType::Town, src->index, SourceType::Town, dst->index)) return false;
if (CheckSubsidyDuplicate(cargo_type, {src->index, SourceType::Town}, {dst->index, SourceType::Town})) return false;
CreateSubsidy(cargo_type, SourceType::Town, src->index, SourceType::Town, dst->index);
CreateSubsidy(cargo_type, {src->index, SourceType::Town}, {dst->index, SourceType::Town});
return true;
}
bool FindSubsidyCargoDestination(CargoType cargo_type, SourceType src_type, SourceID src);
bool FindSubsidyCargoDestination(CargoType cargo_type, Source src);
/**
@ -319,8 +305,6 @@ bool FindSubsidyTownCargoRoute()
{
if (!Subsidy::CanAllocateItem()) return false;
SourceType src_type = SourceType::Town;
/* Select a random town. */
const Town *src_town = Town::GetRandom();
if (src_town->cache.population < SUBSIDY_CARGO_MIN_POPULATION) return false;
@ -363,9 +347,7 @@ bool FindSubsidyTownCargoRoute()
/* Quit if the percentage transported is large enough. */
if (src_town->GetPercentTransported(cargo_type) > SUBSIDY_MAX_PCT_TRANSPORTED) return false;
SourceID src = src_town->index;
return FindSubsidyCargoDestination(cargo_type, src_type, src);
return FindSubsidyCargoDestination(cargo_type, {src_town->index, SourceType::Town});
}
/**
@ -376,8 +358,6 @@ bool FindSubsidyIndustryCargoRoute()
{
if (!Subsidy::CanAllocateItem()) return false;
SourceType src_type = SourceType::Industry;
/* Select a random industry. */
const Industry *src_ind = Industry::GetRandom();
if (src_ind == nullptr) return false;
@ -411,25 +391,21 @@ bool FindSubsidyIndustryCargoRoute()
return false;
}
SourceID src = src_ind->index;
return FindSubsidyCargoDestination(cargo_type, src_type, src);
return FindSubsidyCargoDestination(cargo_type, {src_ind->index, SourceType::Industry});
}
/**
* Tries to find a suitable destination for the given source and cargo.
* @param cargo_type Subsidized cargo.
* @param src_type Type of \a src.
* @param src Index of source.
* @param cargo_type Subsidized cargo.
* @param src Source of cargo.
* @return True iff the subsidy was created.
*/
bool FindSubsidyCargoDestination(CargoType cargo_type, SourceType src_type, SourceID src)
bool FindSubsidyCargoDestination(CargoType cargo_type, Source src)
{
/* Choose a random destination. */
SourceType dst_type = Chance16(1, 2) ? SourceType::Town : SourceType::Industry;
Source dst{INVALID_SOURCE, Chance16(1, 2) ? SourceType::Town : SourceType::Industry};
SourceID dst;
switch (dst_type) {
switch (dst.type) {
case SourceType::Town: {
/* Select a random town. */
const Town *dst_town = Town::GetRandom();
@ -446,7 +422,7 @@ bool FindSubsidyCargoDestination(CargoType cargo_type, SourceType src_type, Sour
/* Check if the town can accept this cargo. */
if (town_cargo_accepted[cargo_type] < 8) return false;
dst = dst_town->index;
dst.id = dst_town->index;
break;
}
@ -458,7 +434,7 @@ bool FindSubsidyCargoDestination(CargoType cargo_type, SourceType src_type, Sour
/* The industry must accept the cargo */
if (!dst_ind->IsCargoAccepted(cargo_type)) return false;
dst = dst_ind->index;
dst.id = dst_ind->index;
break;
}
@ -466,15 +442,15 @@ bool FindSubsidyCargoDestination(CargoType cargo_type, SourceType src_type, Sour
}
/* Check that the source and the destination are not the same. */
if (src_type == dst_type && src == dst) return false;
if (src == dst) return false;
/* Check distance between source and destination. */
if (!CheckSubsidyDistance(src_type, src, dst_type, dst)) return false;
if (!CheckSubsidyDistance(src, dst)) return false;
/* Avoid duplicate subsidies. */
if (CheckSubsidyDuplicate(cargo_type, src_type, src, dst_type, dst)) return false;
if (CheckSubsidyDuplicate(cargo_type, src, dst)) return false;
CreateSubsidy(cargo_type, src_type, src, dst_type, dst);
CreateSubsidy(cargo_type, src, dst);
return true;
}
@ -488,13 +464,13 @@ static IntervalTimer<TimerGameEconomy> _economy_subsidies_monthly({TimerGameEcon
if (--s->remaining == 0) {
if (!s->IsAwarded()) {
std::pair<NewsReferenceType, NewsReferenceType> reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn);
AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NewsType::Subsidies, NewsStyle::Normal, {}, reftype.first, s->src, reftype.second, s->dst);
AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NewsType::Subsidies, NewsStyle::Normal, {}, reftype.first, s->src.id, reftype.second, s->dst.id);
AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index));
Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index));
} else {
if (s->awarded == _local_company) {
std::pair<NewsReferenceType, NewsReferenceType> reftype = SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn);
AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NewsType::Subsidies, NewsStyle::Normal, {}, reftype.first, s->src, reftype.second, s->dst);
AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NewsType::Subsidies, NewsStyle::Normal, {}, reftype.first, s->src.id, reftype.second, s->dst.id);
}
AI::BroadcastNewEvent(new ScriptEventSubsidyExpired(s->index));
Game::NewEvent(new ScriptEventSubsidyExpired(s->index));
@ -556,21 +532,20 @@ static IntervalTimer<TimerGameEconomy> _economy_subsidies_monthly({TimerGameEcon
* Tests whether given delivery is subsidised and possibly awards the subsidy to delivering company
* @param cargo_type type of cargo
* @param company company delivering the cargo
* @param src_type type of \a src
* @param src index of source
* @param src source of cargo
* @param st station where the cargo is delivered to
* @return is the delivery subsidised?
*/
bool CheckSubsidised(CargoType cargo_type, CompanyID company, SourceType src_type, SourceID src, const Station *st)
bool CheckSubsidised(CargoType cargo_type, CompanyID company, Source src, const Station *st)
{
/* If the source isn't subsidised, don't continue */
if (src == INVALID_SOURCE) return false;
switch (src_type) {
if (src.id == INVALID_SOURCE) return false;
switch (src.type) {
case SourceType::Industry:
if (!(Industry::Get(src)->part_of_subsidy & POS_SRC)) return false;
if (!(Industry::Get(src.id)->part_of_subsidy & POS_SRC)) return false;
break;
case SourceType::Town:
if (!(Town::Get(src)->cache.part_of_subsidy & POS_SRC)) return false;
if (!(Town::Get(src.id)->cache.part_of_subsidy & POS_SRC)) return false;
break;
default: return false;
}
@ -581,8 +556,8 @@ bool CheckSubsidised(CargoType cargo_type, CompanyID company, SourceType src_typ
if (!st->rect.IsEmpty()) {
for (const Subsidy *s : Subsidy::Iterate()) {
/* Don't create the cache if there is no applicable subsidy with town as destination */
if (s->dst_type != SourceType::Town) continue;
if (s->cargo_type != cargo_type || s->src_type != src_type || s->src != src) continue;
if (s->dst.type != SourceType::Town) continue;
if (s->cargo_type != cargo_type || s->src != src) continue;
if (s->IsAwarded() && s->awarded != company) continue;
BitmapTileIterator it(st->catchment_tiles);
@ -600,11 +575,11 @@ bool CheckSubsidised(CargoType cargo_type, CompanyID company, SourceType src_typ
/* Check if there's a (new) subsidy that applies. There can be more subsidies triggered by this delivery!
* Think about the case that subsidies are A->B and A->C and station has both B and C in its catchment area */
for (Subsidy *s : Subsidy::Iterate()) {
if (s->cargo_type == cargo_type && s->src_type == src_type && s->src == src && (!s->IsAwarded() || s->awarded == company)) {
switch (s->dst_type) {
if (s->cargo_type == cargo_type && s->src == src && (!s->IsAwarded() || s->awarded == company)) {
switch (s->dst.type) {
case SourceType::Industry:
for (const auto &i : st->industries_near) {
if (s->dst == i.industry->index) {
if (s->dst.id == i.industry->index) {
assert(i.industry->part_of_subsidy & POS_DST);
subsidised = true;
if (!s->IsAwarded()) s->AwardTo(company);
@ -613,7 +588,7 @@ bool CheckSubsidised(CargoType cargo_type, CompanyID company, SourceType src_typ
break;
case SourceType::Town:
for (const Town *tp : towns_near) {
if (s->dst == tp->index) {
if (s->dst.id == tp->index) {
assert(tp->cache.part_of_subsidy & POS_DST);
subsidised = true;
if (!s->IsAwarded()) s->AwardTo(company);

View File

@ -23,10 +23,8 @@ struct Subsidy : SubsidyPool::PoolItem<&_subsidy_pool> {
CargoType cargo_type; ///< Cargo type involved in this subsidy, INVALID_CARGO for invalid subsidy
uint16_t remaining; ///< Remaining months when this subsidy is valid
CompanyID awarded; ///< Subsidy is awarded to this company; INVALID_COMPANY if it's not awarded to anyone
SourceType src_type; ///< Source of subsidised path (SourceType::Industry or SourceType::Town)
SourceType dst_type; ///< Destination of subsidised path (SourceType::Industry or SourceType::Town)
SourceID src; ///< Index of source. Either TownID or IndustryID
SourceID dst; ///< Index of destination. Either TownID or IndustryID
Source src; ///< Source of subsidised path
Source dst; ///< Destination of subsidised path
/**
* We need an (empty) constructor so struct isn't zeroed (as C++ standard states)

View File

@ -12,9 +12,22 @@
#include "command_type.h"
#include "cargo_type.h"
#include "misc/endian_buffer.hpp"
CommandCost CmdCreateSubsidy(DoCommandFlag flags, CargoType cargo_type, SourceType src_type, SourceID src, SourceType dst_type, SourceID dst);
CommandCost CmdCreateSubsidy(DoCommandFlag flags, CargoType cargo_type, Source src, Source dst);
DEF_CMD_TRAIT(CMD_CREATE_SUBSIDY, CmdCreateSubsidy, CMD_DEITY, CMDT_OTHER_MANAGEMENT)
template <typename Tcont, typename Titer>
inline EndianBufferWriter<Tcont, Titer> &operator <<(EndianBufferWriter<Tcont, Titer> &buffer, const Source &source)
{
return buffer << source.id << source.type;
}
inline EndianBufferReader &operator >>(EndianBufferReader &buffer, Source &source)
{
return buffer >> source.id >> source.type;
}
#endif /* SUBSIDY_CMD_H */

View File

@ -18,8 +18,8 @@
#include "subsidy_base.h"
std::pair<NewsReferenceType, NewsReferenceType> SetupSubsidyDecodeParam(const struct Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset = 0);
void DeleteSubsidyWith(SourceType type, SourceID index);
bool CheckSubsidised(CargoType cargo_type, CompanyID company, SourceType src_type, SourceID src, const Station *st);
void DeleteSubsidyWith(Source src);
bool CheckSubsidised(CargoType cargo_type, CompanyID company, Source src, const Station *st);
void RebuildSubsidisedSourceAndDestinationCache();
#endif /* SUBSIDY_FUNC_H */

View File

@ -82,9 +82,9 @@ struct SubsidyListWindow : Window {
{
/* determine src coordinate for subsidy and try to scroll to it */
TileIndex xy;
switch (s->src_type) {
case SourceType::Industry: xy = Industry::Get(s->src)->location.tile; break;
case SourceType::Town: xy = Town::Get(s->src)->xy; break;
switch (s->src.type) {
case SourceType::Industry: xy = Industry::Get(s->src.id)->location.tile; break;
case SourceType::Town: xy = Town::Get(s->src.id)->xy; break;
default: NOT_REACHED();
}
@ -92,9 +92,9 @@ struct SubsidyListWindow : Window {
if (_ctrl_pressed) ShowExtraViewportWindow(xy);
/* otherwise determine dst coordinate for subsidy and scroll to it */
switch (s->dst_type) {
case SourceType::Industry: xy = Industry::Get(s->dst)->location.tile; break;
case SourceType::Town: xy = Town::Get(s->dst)->xy; break;
switch (s->dst.type) {
case SourceType::Industry: xy = Industry::Get(s->dst.id)->location.tile; break;
case SourceType::Town: xy = Town::Get(s->dst.id)->xy; break;
default: NOT_REACHED();
}

View File

@ -153,9 +153,10 @@ Town::~Town()
}
this->psa_list.clear();
DeleteSubsidyWith(SourceType::Town, this->index);
Source src{this->index, SourceType::Town};
DeleteSubsidyWith(src);
DeleteNewGRFInspectWindow(GSF_FAKE_TOWNS, this->index);
CargoPacket::InvalidateAllFrom(SourceType::Town, this->index);
CargoPacket::InvalidateAllFrom(src);
MarkWholeScreenDirty();
}
@ -548,7 +549,7 @@ static void TownGenerateCargo(Town *t, CargoType ct, uint amount, StationFinder
/* Actually generate cargo and update town statistics. */
t->supplied[ct].new_max += amount;
t->supplied[ct].new_act += MoveGoodsToStation(ct, amount, SourceType::Town, t->index, stations.GetStations());;
t->supplied[ct].new_act += MoveGoodsToStation(ct, amount, {t->index, SourceType::Town}, stations.GetStations());;
}
/**