From 0502a6df425ce15541b71f95357f575b578d1024 Mon Sep 17 00:00:00 2001 From: smatz Date: Sat, 8 Aug 2009 16:42:55 +0000 Subject: [PATCH] (svn r17113) -Change [FS#265][FS#2094][FS#2589]: apply the subsidy when subsidy's destination is in station's catchment area and cargo packets originate from subsidy's source -Change [FS#1134]: subsidies aren't bound to stations after awarding anymore, they still apply to town or industry, no matter what station is used for loading and unloading. Awarded subsidies from older savegames are lost -Change [NoAI]: due to these changes, AISubsidy::GetSource and AISubsidy::GetDestination now return STATION_INVALID for awarded subsidies --- projects/openttd_vs80.vcproj | 4 + projects/openttd_vs90.vcproj | 4 + source.list | 1 + src/ai/api/ai_changelog.hpp | 2 + src/ai/api/ai_subsidy.cpp | 19 ++- src/ai/api/ai_subsidy.hpp | 16 +-- src/cargo_type.h | 10 +- src/cargopacket.cpp | 27 ++++- src/cargopacket.h | 11 +- src/economy.cpp | 43 +++---- src/economy_func.h | 2 +- src/industry.h | 3 + src/industry_cmd.cpp | 5 +- src/lang/english.txt | 12 +- src/saveload/afterload.cpp | 19 +-- src/saveload/cargopacket_sl.cpp | 2 + src/saveload/oldloader_sl.cpp | 2 +- src/saveload/saveload.cpp | 2 +- src/saveload/subsidy_sl.cpp | 13 +- src/station.cpp | 3 - src/station_cmd.cpp | 12 +- src/subsidy.cpp | 202 +++++++++++++++++++++----------- src/subsidy_base.h | 19 ++- src/subsidy_func.h | 4 +- src/subsidy_gui.cpp | 9 +- src/subsidy_type.h | 22 ++++ src/town.h | 3 + src/town_cmd.cpp | 8 +- src/unmovable_cmd.cpp | 7 +- 29 files changed, 309 insertions(+), 177 deletions(-) create mode 100644 src/subsidy_type.h diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index bf10c3c042..2b8d7257ae 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -1487,6 +1487,10 @@ RelativePath=".\..\src\subsidy_func.h" > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 0e07feca72..5b65ba9773 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -1484,6 +1484,10 @@ RelativePath=".\..\src\subsidy_func.h" > + + diff --git a/source.list b/source.list index 4318e4dc41..ca42b24307 100644 --- a/source.list +++ b/source.list @@ -300,6 +300,7 @@ strings_func.h strings_type.h subsidy_base.h subsidy_func.h +subsidy_type.h tar_type.h terraform_gui.h textbuf_gui.h diff --git a/src/ai/api/ai_changelog.hpp b/src/ai/api/ai_changelog.hpp index 5750ab0aca..a8e5110303 100644 --- a/src/ai/api/ai_changelog.hpp +++ b/src/ai/api/ai_changelog.hpp @@ -29,6 +29,8 @@ * \li WaypointID was replaced by StationID. All WaypointIDs from previous * savegames are invalid * \li WAYPOINT_INVALID is now deprecated, use STATION_INVALID instead + * \li AISubsidy::GetSource and AISubsidy::GetDestination return STATION_INVALID + * for awarded subsidies * \li AIs can create subclasses of API classes and use API constants as part * of their own constants * \li AIVehicleList_Station now also works for waypoints diff --git a/src/ai/api/ai_subsidy.cpp b/src/ai/api/ai_subsidy.cpp index fd3e29745c..39358e963a 100644 --- a/src/ai/api/ai_subsidy.cpp +++ b/src/ai/api/ai_subsidy.cpp @@ -4,6 +4,7 @@ #include "ai_subsidy.hpp" #include "ai_date.hpp" +#include "ai_log.hpp" #include "../../subsidy_base.h" #include "../../station_base.h" #include "../../cargotype.h" @@ -24,7 +25,7 @@ { if (!IsAwarded(subsidy_id)) return AICompany::COMPANY_INVALID; - return (AICompany::CompanyID)((byte)::Station::Get(::Subsidy::Get(subsidy_id)->src)->owner); + return (AICompany::CompanyID)((byte)::Subsidy::Get(subsidy_id)->awarded); } /* static */ int32 AISubsidy::GetExpireDate(SubsidyID subsidy_id) @@ -34,11 +35,7 @@ int year = AIDate::GetYear(AIDate::GetCurrentDate()); int month = AIDate::GetMonth(AIDate::GetCurrentDate()); - if (IsAwarded(subsidy_id)) { - month += 24 - ::Subsidy::Get(subsidy_id)->age; - } else { - month += 12 - ::Subsidy::Get(subsidy_id)->age; - } + month += ::Subsidy::Get(subsidy_id)->remaining; year += (month - 1) / 12; month = ((month - 1) % 12) + 1; @@ -64,6 +61,11 @@ { if (!IsValidSubsidy(subsidy_id)) return INVALID_STATION; + if (IsAwarded(subsidy_id)) { + AILog::Error("AISubsidy::GetSource returned INVALID_STATION due to internal changes in the Subsidy logic."); + return INVALID_STATION; + } + return ::Subsidy::Get(subsidy_id)->src; } @@ -78,5 +80,10 @@ { if (!IsValidSubsidy(subsidy_id)) return INVALID_STATION; + if (IsAwarded(subsidy_id)) { + AILog::Error("AISubsidy::GetDestination returned INVALID_STATION due to internal changes in the Subsidy logic."); + return INVALID_STATION; + } + return ::Subsidy::Get(subsidy_id)->dst; } diff --git a/src/ai/api/ai_subsidy.hpp b/src/ai/api/ai_subsidy.hpp index 7be86b0e8b..96ad92c31c 100644 --- a/src/ai/api/ai_subsidy.hpp +++ b/src/ai/api/ai_subsidy.hpp @@ -69,12 +69,12 @@ public: /** * Return the source TownID/IndustryID/StationID the subsidy is for. - * 1) IsAwarded(subsidy_id) -> return the StationID the subsidy is awarded to. - * 2) !IsAwarded(subsidy_id) && SourceIsTown(subsidy_id) -> return the TownID. - * 3) !IsAwarded(subsidy_id) && !SourceIsTown(subsidy_id) -> return the IndustryID. + * \li IsAwarded(subsidy_id) -> return INVALID_STATION. + * \li !IsAwarded(subsidy_id) && SourceIsTown(subsidy_id) -> return the TownID. + * \li !IsAwarded(subsidy_id) && !SourceIsTown(subsidy_id) -> return the IndustryID. * @param subsidy_id The SubsidyID to check. * @pre IsValidSubsidy(subsidy_id). - * @return One of TownID/IndustryID/StationID. + * @return One of TownID/IndustryID/INVALID_STATION. */ static int32 GetSource(SubsidyID subsidy_id); @@ -88,12 +88,12 @@ public: /** * Return the destination TownID/IndustryID/StationID the subsidy is for. - * 1) IsAwarded(subsidy_id) -> return the StationID the subsidy is awarded to. - * 2) !IsAwarded(subsidy_id) && SourceIsTown(subsidy_id) -> return the TownID. - * 3) !IsAwarded(subsidy_id) && !SourceIsTown(subsidy_id) -> return the IndustryID. + * \li IsAwarded(subsidy_id) -> return INVALID_STATION. + * \li !IsAwarded(subsidy_id) && DestinationIsTown(subsidy_id) -> return the TownID. + * \li !IsAwarded(subsidy_id) && !DestinationIsTown(subsidy_id) -> return the IndustryID. * @param subsidy_id the SubsidyID to check. * @pre IsValidSubsidy(subsidy_id). - * @return One of TownID/IndustryID/StationID. + * @return One of TownID/IndustryID/INVALID_STATION. */ static int32 GetDestination(SubsidyID subsidy_id); }; diff --git a/src/cargo_type.h b/src/cargo_type.h index 30145f266f..0222af8061 100644 --- a/src/cargo_type.h +++ b/src/cargo_type.h @@ -85,15 +85,15 @@ public: }; -/** Types of subsidy source and destination */ +/** Types of cargo source and destination */ enum SourceType { - ST_INDUSTRY, ///< Source/destination is an industry - ST_TOWN, ///< Source/destination is a town - ST_STATION, ///< Source/destination is a station + ST_INDUSTRY, ///< Source/destination is an industry + ST_TOWN, ///< Source/destination is a town + ST_HEADQUARTERS, ///< Source/destination are company headquarters }; typedef SimpleTinyEnumT SourceTypeByte; -typedef uint16 SourceID; ///< Contains either industry ID, town ID or station ID (or INVALID_SOURCE) +typedef uint16 SourceID; ///< Contains either industry ID, town ID or company ID (or INVALID_SOURCE) static const SourceID INVALID_SOURCE = 0xFFFF; ///< Invalid/unknown index of source #endif /* CARGO_TYPE_H */ diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp index 65514e647f..355cabebb0 100644 --- a/src/cargopacket.cpp +++ b/src/cargopacket.cpp @@ -16,17 +16,33 @@ void InitializeCargoPackets() _cargopacket_pool.CleanPool(); } -CargoPacket::CargoPacket(StationID source, uint16 count) +CargoPacket::CargoPacket(StationID source, uint16 count, SourceType source_type, SourceID source_id) { if (source != INVALID_STATION) assert(count != 0); - this->source = source; +// this->feeder_share = 0; // no need to zero already zeroed data (by operator new) this->source_xy = (source != INVALID_STATION) ? Station::Get(source)->xy : 0; this->loaded_at_xy = this->source_xy; + this->source = source; this->count = count; - this->days_in_transit = 0; - this->feeder_share = 0; +// this->days_in_transit = 0; + + this->source_type = source_type; + this->source_id = source_id; +} + +/** + * Invalidates (sets source_id to INVALID_SOURCE) all cargo packets from given source + * @param src_type type of source + * @param src index of source + */ +/* static */ void CargoPacket::InvalidateAllFrom(SourceType src_type, SourceID src) +{ + CargoPacket *cp; + FOR_ALL_CARGOPACKETS(cp) { + if (cp->source_type == src_type && cp->source_id == src) cp->source_id = INVALID_SOURCE; + } } /* @@ -149,6 +165,9 @@ bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta, cp_new->days_in_transit = cp->days_in_transit; cp_new->feeder_share = fs; + cp_new->source_type = cp->source_type; + cp_new->source_id = cp->source_id; + cp_new->count = count; dest->packets.push_back(cp_new); diff --git a/src/cargopacket.h b/src/cargopacket.h index 414003faa4..de8268a98c 100644 --- a/src/cargopacket.h +++ b/src/cargopacket.h @@ -9,6 +9,7 @@ #include "economy_type.h" #include "tile_type.h" #include "station_type.h" +#include "cargo_type.h" #include typedef uint32 CargoPacketID; @@ -30,13 +31,16 @@ struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> { uint16 count; ///< The amount of cargo in this packet byte days_in_transit; ///< Amount of days this packet has been in transit + SourceTypeByte source_type; ///< Type of #source_id + SourceID source_id; ///< Index of source, INVALID_SOURCE if unknown/invalid + /** * Creates a new cargo packet * @param source the source of the packet * @param count the number of cargo entities to put in this packet * @pre count != 0 || source == INVALID_STATION */ - CargoPacket(StationID source = INVALID_STATION, uint16 count = 0); + CargoPacket(StationID source = INVALID_STATION, uint16 count = 0, SourceType source_type = ST_INDUSTRY, SourceID source_id = INVALID_SOURCE); /** Destroy the packet */ ~CargoPacket() { } @@ -49,8 +53,11 @@ struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> { */ FORCEINLINE bool SameSource(const CargoPacket *cp) const { - return this->source_xy == cp->source_xy && this->days_in_transit == cp->days_in_transit; + return this->source_xy == cp->source_xy && this->days_in_transit == cp->days_in_transit && + this->source_type == cp->source_type && this->source_id == cp->source_id; } + + static void InvalidateAllFrom(SourceType src_type, SourceID src); }; /** diff --git a/src/economy.cpp b/src/economy.cpp index 45cab5c594..f8bba522c3 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -328,11 +328,13 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) Company::Get(old_owner)->money = UINT64_MAX >> 2; // jackpot ;p } - if (new_owner == INVALID_OWNER) { - Subsidy *s; - FOR_ALL_SUBSIDIES(s) { - if (s->IsAwarded() && Station::Get(s->dst)->owner == old_owner) { - s->cargo_type = CT_INVALID; + Subsidy *s; + FOR_ALL_SUBSIDIES(s) { + if (s->awarded == old_owner) { + if (new_owner == INVALID_OWNER) { + DeleteSubsidy(s); + } else { + s->awarded = new_owner; } } } @@ -916,45 +918,38 @@ static void DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, int nu /** * Delivers goods to industries/towns and calculates the payment * @param num_pieces amount of cargo delivered - * @param source Originstation of the cargo * @param dest Station the cargo has been unloaded * @param source_tile The origin of the cargo for distance calculation * @param days_in_transit Travel time * @param company The company delivering the cargo - * The cargo is just added to the stockpile of the industry. It is due to the caller to trigger the industry's production machinery + * @param src_type Type of source of cargo (industry, town, headquarters) + * @param src Index of 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, CargoID cargo_type, StationID source, StationID dest, TileIndex source_tile, byte days_in_transit, Company *company) +static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID dest, TileIndex source_tile, byte days_in_transit, Company *company, SourceType src_type, SourceID src) { - bool subsidised = false; - assert(num_pieces > 0); /* Update company statistics */ company->cur_economy.delivered_cargo += num_pieces; SetBit(company->cargo_types, cargo_type); - const Station *s_to = Station::Get(dest); - - if (source != INVALID_STATION) { - const Station *s_from = Station::Get(source); - - /* Check if a subsidy applies. */ - subsidised = CheckSubsidised(s_from, s_to, cargo_type, company->index); - } + const Station *st = Station::Get(dest); /* Increase town's counter for some special goods types */ const CargoSpec *cs = CargoSpec::Get(cargo_type); - if (cs->town_effect == TE_FOOD) s_to->town->new_act_food += num_pieces; - if (cs->town_effect == TE_WATER) s_to->town->new_act_water += num_pieces; + if (cs->town_effect == TE_FOOD) st->town->new_act_food += num_pieces; + if (cs->town_effect == TE_WATER) st->town->new_act_water += num_pieces; /* Give the goods to the industry. */ - DeliverGoodsToIndustry(s_to, cargo_type, num_pieces); + DeliverGoodsToIndustry(st, cargo_type, num_pieces); /* Determine profit */ - Money profit = GetTransportedGoodsIncome(num_pieces, DistanceManhattan(source_tile, s_to->xy), days_in_transit, cargo_type); + Money profit = GetTransportedGoodsIncome(num_pieces, DistanceManhattan(source_tile, st->xy), days_in_transit, cargo_type); /* Modify profit if a subsidy is in effect */ - if (subsidised) { + if (CheckSubsidised(cargo_type, company->index, src_type, src, st)) { switch (_settings_game.difficulty.subsidy_multiplier) { case 0: profit += profit >> 1; break; case 1: profit *= 2; break; @@ -1051,7 +1046,7 @@ void CargoPayment::PayFinalDelivery(CargoPacket *cp, uint count) } /* Handle end of route payment */ - Money profit = DeliverGoods(count, this->ct, cp->source, this->current_station, cp->source_xy, cp->days_in_transit, this->owner); + Money profit = DeliverGoods(count, this->ct, this->current_station, cp->source_xy, cp->days_in_transit, this->owner, cp->source_type, cp->source_id); this->route_profit += profit; /* The vehicle's profit is whatever route profit there is minus feeder shares. */ diff --git a/src/economy_func.h b/src/economy_func.h index 85def7807a..af31e8c7d3 100644 --- a/src/economy_func.h +++ b/src/economy_func.h @@ -32,7 +32,7 @@ int UpdateCompanyRatingAndValue(Company *c, bool update); void StartupIndustryDailyChanges(bool init_counter); Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type); -uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount); +uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount, SourceType source_type, SourceID source_id); void PrepareUnload(Vehicle *front_v); void LoadUnloadStation(Station *st); diff --git a/src/industry.h b/src/industry.h index 404a4e25a6..090f9267de 100644 --- a/src/industry.h +++ b/src/industry.h @@ -19,6 +19,7 @@ #include "tile_type.h" #include "company_type.h" #include "strings_type.h" +#include "subsidy_type.h" enum { INVALID_INDUSTRY = 0xFFFF, @@ -125,6 +126,8 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> { Year last_prod_year; ///< last year of production byte was_cargo_delivered; ///< flag that indicate this has been the closest industry chosen for cargo delivery by a station. see DeliverGoodsToIndustry + PartOfSubsidyByte part_of_subsidy; ///< NOSAVE: is this industry a source/destination of a subsidy? + OwnerByte founder; ///< Founder of the industry Date construction_date; ///< Date of the construction of the industry uint8 construction_type; ///< Way the industry was constructed (@see IndustryConstructionType) diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index f38648a158..3efc21a35f 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -167,11 +167,12 @@ Industry::~Industry() DecIndustryTypeCount(this->type); - DeleteSubsidyWith(ST_INDUSTRY, this->index); DeleteIndustryNews(this->index); DeleteWindowById(WC_INDUSTRY_VIEW, this->index); InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0); + DeleteSubsidyWith(ST_INDUSTRY, this->index); + CargoPacket::InvalidateAllFrom(ST_INDUSTRY, this->index); Station::RecomputeIndustriesNearForAll(); } @@ -479,7 +480,7 @@ static void TransportIndustryGoods(TileIndex tile) i->this_month_production[j] += cw; - uint am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[j], cw); + uint am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[j], cw, ST_INDUSTRY, i->index); i->this_month_transported[j] += am; moved_cargo |= (am != 0); diff --git a/src/lang/english.txt b/src/lang/english.txt index ca5c5bf70a..6ed40ea981 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -797,12 +797,12 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO :{WHITE}{STATION STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION} now accepts {STRING} and {STRING} STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIGFONT}{BLACK}Offer of subsidy expired:{}{}{STRING} from {STRING2} to {STRING2} will now not attract a subsidy. -STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIGFONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STATION} to {STATION} is no longer subsidised. +STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIGFONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STRING2} to {STRING2} is no longer subsidised. STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIGFONT}{BLACK}Service subsidy offered:{}{}First {STRING} service from {STRING2} to {STRING2} will attract a year's subsidy from the local authority! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIGFONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STATION} to {STATION} will pay 50% extra for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIGFONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STATION} to {STATION} will pay double rates for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIGFONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STATION} to {STATION} will pay triple rates for the next year! -STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIGFONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STATION} to {STATION} will pay quadruple rates for the next year! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIGFONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay 50% extra for the next year! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIGFONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay double rates for the next year! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIGFONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay triple rates for the next year! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIGFONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} service from {STRING2} to {STRING2} will pay quadruple rates for the next year! STR_NEWS_ROAD_REBUILDING :{BIGFONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {RAW_STRING} brings 6 months of misery to motorists! @@ -2397,7 +2397,7 @@ STR_SUBSIDIES_OFFERED_TITLE :{BLACK}Subsidie STR_SUBSIDIES_OFFERED_FROM_TO :{ORANGE}{STRING} from {STRING2} to {STRING2}{YELLOW} (by {DATE_SHORT}) STR_SUBSIDIES_NONE :{ORANGE}None STR_SUBSIDIES_SUBSIDISED_TITLE :{BLACK}Services already subsidised: -STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{STRING} from {STATION} to {STATION}{YELLOW} ({COMPANY}{YELLOW}, until {DATE_SHORT}) +STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{STRING} from {STRING2} to {STRING2}{YELLOW} ({COMPANY}{YELLOW}, until {DATE_SHORT}) STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Click on service to centre view on industry/town # Station list window diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index fa772cac15..0331feed72 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -32,6 +32,7 @@ #include "../economy_base.h" #include "../animated_tile_func.h" #include "../subsidy_base.h" +#include "../subsidy_func.h" #include "table/strings.h" @@ -230,6 +231,7 @@ static bool InitializeWindowsAndCaches() SetCachedEngineCounts(); Station::RecomputeIndustriesNearForAll(); + RebuildSubsidisedSourceAndDestinationCache(); /* Towns have a noise controlled number of airports system * So each airport's noise value must be added to the town->noise_reached value @@ -1868,17 +1870,15 @@ bool AfterLoadGame() } } - { - /* Delete invalid subsidies possibly present in old versions (but converted to new savegame) */ + if (CheckSavegameVersion(125)) { + /* Convert old subsidies */ Subsidy *s; FOR_ALL_SUBSIDIES(s) { - if (s->IsAwarded()) { - /* Station -> Station */ - const Station *from = Station::GetIfValid(s->src); - const Station *to = Station::GetIfValid(s->dst); - s->src_type = s->dst_type = ST_STATION; - if (from != NULL && to != NULL && from->owner == to->owner && Company::IsValidID(from->owner)) continue; - } else { + /* Convert only nonawarded subsidies. The original source and destination town/industry + * anymore for awarded subsidies, so invalidate them. */ + if (s->remaining < 12) { + s->remaining = 12 - s->remaining; // convert "age" to "remaining" + s->awarded = INVALID_COMPANY; // not awarded to anyone const CargoSpec *cs = CargoSpec::Get(s->cargo_type); switch (cs->town_effect) { case TE_PASSENGERS: @@ -1901,6 +1901,7 @@ bool AfterLoadGame() break; } } + /* Awarded subsidy or invalid source/destination, invalidate */ s->cargo_type = CT_INVALID; } } diff --git a/src/saveload/cargopacket_sl.cpp b/src/saveload/cargopacket_sl.cpp index d0a7783b8f..7a6a1c812b 100644 --- a/src/saveload/cargopacket_sl.cpp +++ b/src/saveload/cargopacket_sl.cpp @@ -14,6 +14,8 @@ static const SaveLoad _cargopacket_desc[] = { SLE_VAR(CargoPacket, count, SLE_UINT16), SLE_VAR(CargoPacket, days_in_transit, SLE_UINT8), SLE_VAR(CargoPacket, feeder_share, SLE_INT64), + SLE_CONDVAR(CargoPacket, source_type, SLE_UINT8, 125, SL_MAX_VERSION), + SLE_CONDVAR(CargoPacket, source_id, SLE_UINT16, 125, SL_MAX_VERSION), /* Used to be paid_for, but that got changed. */ SLE_CONDNULL(1, 0, 120), diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index f8fc0b7778..14db853bfb 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -1468,7 +1468,7 @@ static bool LoadOldEngineName(LoadgameState *ls, int num) static const OldChunks subsidy_chunk[] = { OCL_SVAR( OC_UINT8, Subsidy, cargo_type ), - OCL_SVAR( OC_UINT8, Subsidy, age ), + OCL_SVAR( OC_UINT8, Subsidy, remaining ), OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, src ), OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, dst ), diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 731679dc5c..ddb374dd07 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -41,7 +41,7 @@ #include "saveload_internal.h" -extern const uint16 SAVEGAME_VERSION = 124; +extern const uint16 SAVEGAME_VERSION = 125; SavegameType _savegame_type; ///< type of savegame we are loading diff --git a/src/saveload/subsidy_sl.cpp b/src/saveload/subsidy_sl.cpp index b1e889e8fa..163a9ce8c0 100644 --- a/src/saveload/subsidy_sl.cpp +++ b/src/saveload/subsidy_sl.cpp @@ -9,11 +9,14 @@ static const SaveLoad _subsidies_desc[] = { SLE_VAR(Subsidy, cargo_type, SLE_UINT8), - SLE_VAR(Subsidy, age, SLE_UINT8), - SLE_CONDVAR(Subsidy, src, SLE_FILE_U8 | SLE_VAR_U16, 0, 4), - SLE_CONDVAR(Subsidy, src, SLE_UINT16, 5, SL_MAX_VERSION), - SLE_CONDVAR(Subsidy, dst, SLE_FILE_U8 | SLE_VAR_U16, 0, 4), - SLE_CONDVAR(Subsidy, dst, SLE_UINT16, 5, SL_MAX_VERSION), + SLE_VAR(Subsidy, remaining, SLE_UINT8), + SLE_CONDVAR(Subsidy, awarded, SLE_UINT8, 125, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, src_type, SLE_UINT8, 125, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, dst_type, SLE_UINT8, 125, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, src, SLE_FILE_U8 | SLE_VAR_U16, 0, 4), + SLE_CONDVAR(Subsidy, src, SLE_UINT16, 5, SL_MAX_VERSION), + SLE_CONDVAR(Subsidy, dst, SLE_FILE_U8 | SLE_VAR_U16, 0, 4), + SLE_CONDVAR(Subsidy, dst, SLE_UINT16, 5, SL_MAX_VERSION), SLE_END() }; diff --git a/src/station.cpp b/src/station.cpp index 81c6c186df..749c811745 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -90,9 +90,6 @@ Station::~Station() /* Now delete all orders that go to the station */ RemoveOrderFromAllVehicles(OT_GOTO_STATION, this->index); - /* Subsidies need removal as well */ - DeleteSubsidyWith(ST_STATION, this->index); - /* Remove all news items */ DeleteStationNews(this->index); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 6d007dfcc5..842c35134e 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2840,9 +2840,9 @@ void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint rad } } -static void UpdateStationWaiting(Station *st, CargoID type, uint amount) +static void UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id) { - st->goods[type].cargo.Append(new CargoPacket(st->index, amount)); + st->goods[type].cargo.Append(new CargoPacket(st->index, amount, source_type, source_id)); SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP); StationAnimationTrigger(st, st->xy, STAT_ANIM_NEW_CARGO, type); @@ -2926,7 +2926,7 @@ void FindStationsAroundTiles(TileIndex tile, int w_prod, int h_prod, StationList } } -uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount) +uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount, SourceType source_type, SourceID source_id) { /* Return if nothing to do. Also the rounding below fails for 0. */ if (amount == 0) return 0; @@ -2968,7 +2968,7 @@ uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount) if (st2 == NULL) { /* only one station around */ uint moved = amount * best_rating1 / 256 + 1; - UpdateStationWaiting(st1, type, moved); + UpdateStationWaiting(st1, type, moved, source_type, source_id); return moved; } @@ -2987,13 +2987,13 @@ uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount) if (t != 0) { moved = t * best_rating1 / 256 + 1; amount -= t; - UpdateStationWaiting(st1, type, moved); + UpdateStationWaiting(st1, type, moved, source_type, source_id); } if (amount != 0) { amount = amount * best_rating2 / 256 + 1; moved += amount; - UpdateStationWaiting(st2, type, amount); + UpdateStationWaiting(st2, type, amount, source_type, source_id); } return moved; diff --git a/src/subsidy.cpp b/src/subsidy.cpp index d09030df44..ad79c37e01 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -22,27 +22,23 @@ /** * Marks subsidy as awarded, creates news and AI event - * @param from source station - * @param to destination station * @param company awarded company */ -void Subsidy::AwardTo(StationID from, StationID to, CompanyID company) +void Subsidy::AwardTo(CompanyID company) { assert(!this->IsAwarded()); - this->age = 12; - this->src_type = this->dst_type = ST_STATION; - this->src = from; - this->dst = to; - - /* Add a news item */ - Pair reftype = SetupSubsidyDecodeParam(this, 0); - InjectDParam(1); + this->awarded = company; + this->remaining = 12; char *company_name = MallocT(MAX_LENGTH_COMPANY_NAME_BYTES); SetDParam(0, company); GetString(company_name, STR_COMPANY_NAME, company_name + MAX_LENGTH_COMPANY_NAME_BYTES - 1); + /* Add a news item */ + Pair reftype = SetupSubsidyDecodeParam(this, 0); + InjectDParam(1); + SetDParamStr(0, company_name); AddNewsItem( STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier, @@ -62,7 +58,10 @@ void Subsidy::AwardTo(StationID from, StationID to, CompanyID company) /* static */ Subsidy *Subsidy::AllocateItem() { for (Subsidy *s = Subsidy::array; s < endof(Subsidy::array); s++) { - if (!s->IsValid()) return s; + if (!s->IsValid()) { + s->awarded = INVALID_COMPANY; + return s; + } } return NULL; @@ -105,10 +104,6 @@ Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode) reftype1 = NR_TOWN; SetDParam(1, STR_TOWN_NAME); break; - case ST_STATION: - reftype1 = NR_STATION; - SetDParam(1, s->src); - break; default: NOT_REACHED(); } SetDParam(2, s->src); @@ -122,10 +117,6 @@ Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode) reftype2 = NR_TOWN; SetDParam(4, STR_TOWN_NAME); break; - case ST_STATION: - reftype2 = NR_STATION; - SetDParam(2, s->dst); - break; default: NOT_REACHED(); } SetDParam(5, s->dst); @@ -136,6 +127,42 @@ Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode) return p; } +/** + * 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 flag flag to set + */ +static inline void SetPartOfSubsidyFlag(SourceType type, SourceID index, PartOfSubsidy flag) +{ + switch (type) { + case ST_INDUSTRY: Industry::Get(index)->part_of_subsidy |= flag; return; + case ST_TOWN: Town::Get(index)->part_of_subsidy |= flag; return; + default: NOT_REACHED(); + } +} + +void RebuildSubsidisedSourceAndDestinationCache() +{ + Town *t; + FOR_ALL_TOWNS(t) t->part_of_subsidy = POS_NONE; + + Industry *i; + FOR_ALL_INDUSTRIES(i) i->part_of_subsidy = POS_NONE; + + const Subsidy *s; + FOR_ALL_SUBSIDIES(s) { + SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC); + SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST); + } +} + +void DeleteSubsidy(Subsidy *s) +{ + s->cargo_type = CT_INVALID; + RebuildSubsidisedSourceAndDestinationCache(); +} + void DeleteSubsidyWith(SourceType type, SourceID index) { bool dirty = false; @@ -252,23 +279,20 @@ void SubsidyMonthlyLoop() Subsidy *s; FOR_ALL_SUBSIDIES(s) { - if (s->age == 12 - 1) { - Pair reftype = SetupSubsidyDecodeParam(s, 1); - AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst); - s->cargo_type = CT_INVALID; - modified = true; - AI::BroadcastNewEvent(new AIEventSubsidyOfferExpired(s->Index())); - } else if (s->age == 2 * 12 - 1) { - Station *st = Station::Get(s->dst); - if (st->owner == _local_company) { + if (--s->remaining == 0) { + if (!s->IsAwarded()) { Pair reftype = SetupSubsidyDecodeParam(s, 1); - AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst); + AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst); + AI::BroadcastNewEvent(new AIEventSubsidyOfferExpired(s->Index())); + } else { + if (s->awarded == _local_company) { + Pair reftype = SetupSubsidyDecodeParam(s, 1); + AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst); + } + AI::BroadcastNewEvent(new AIEventSubsidyExpired(s->Index())); } - s->cargo_type = CT_INVALID; + DeleteSubsidy(s); modified = true; - AI::BroadcastNewEvent(new AIEventSubsidyExpired(s->Index())); - } else { - s->age++; } } @@ -306,9 +330,11 @@ void SubsidyMonthlyLoop() } add_subsidy: if (!CheckSubsidyDuplicate(s)) { - s->age = 0; + s->remaining = 12; Pair reftype = SetupSubsidyDecodeParam(s, 0); AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst); + SetPartOfSubsidyFlag(s->src_type, s->src, POS_SRC); + SetPartOfSubsidyFlag(s->dst_type, s->dst, POS_DST); AI::BroadcastNewEvent(new AIEventSubsidyOffer(s->Index())); modified = true; break; @@ -321,51 +347,85 @@ no_add:; InvalidateWindow(WC_SUBSIDIES_LIST, 0); } -bool CheckSubsidised(const Station *from, const Station *to, CargoID cargo_type, CompanyID company) +/** + * 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 #src + * @param src index of source + * @param st station where the cargo is delivered to + * @return is the delivery subsidised? + */ +bool CheckSubsidised(CargoID cargo_type, CompanyID company, SourceType src_type, SourceID src, const Station *st) { - Subsidy *s; - TileIndex xy; + /* If the source isn't subsidised, don't continue */ + if (src == INVALID_SOURCE) return false; + switch (src_type) { + case ST_INDUSTRY: + if (!(Industry::Get(src)->part_of_subsidy & POS_SRC)) return false; + break; + case ST_TOWN: + if (!( Town::Get(src)->part_of_subsidy & POS_SRC)) return false; + break; + default: return false; + } - /* check if there is an already existing subsidy that applies to us */ - FOR_ALL_SUBSIDIES(s) { - if (s->cargo_type == cargo_type && - s->IsAwarded() && - s->src == from->index && - s->dst == to->index) { - return true; + /* Remember all towns near this station (at least one house in its catchment radius) + * which are destination of subsidised path. Do that only if needed */ + SmallVector towns_near; + if (!st->rect.IsEmpty()) { + Subsidy *s; + FOR_ALL_SUBSIDIES(s) { + /* Don't create the cache if there is no applicable subsidy with town as destination */ + if (s->dst_type != ST_TOWN) continue; + if (s->cargo_type != cargo_type || s->src_type != src_type || s->src != src) continue; + if (s->IsAwarded() && s->awarded != company) continue; + + Rect rect = st->GetCatchmentRect(); + + for (int y = rect.top; y <= rect.bottom; y++) { + for (int x = rect.left; x <= rect.right; x++) { + TileIndex tile = TileXY(x, y); + if (!IsTileType(tile, MP_HOUSE)) continue; + const Town *t = Town::GetByTile(tile); + if (t->part_of_subsidy & POS_DST) towns_near.Include(t); + } + } + break; } } - /* check if there's a new subsidy that applies.. */ + bool subsidised = false; + + /* 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 */ + Subsidy *s; FOR_ALL_SUBSIDIES(s) { - if (s->cargo_type == cargo_type && !s->IsAwarded()) { - /* Check distance from source */ - const CargoSpec *cs = CargoSpec::Get(cargo_type); - if (cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) { - xy = Town::Get(s->src)->xy; - } else { - xy = Industry::Get(s->src)->xy; - } - if (DistanceMax(xy, from->xy) > 9) continue; - - /* Check distance from dest */ - switch (cs->town_effect) { - case TE_PASSENGERS: - case TE_MAIL: - case TE_GOODS: - case TE_FOOD: - xy = Town::Get(s->dst)->xy; + if (s->cargo_type == cargo_type && s->src_type == src_type && s->src == src && (!s->IsAwarded() || s->awarded == company)) { + switch (s->dst_type) { + case ST_INDUSTRY: + for (const Industry * const *ip = st->industries_near.Begin(); ip != st->industries_near.End(); ip++) { + if (s->dst == (*ip)->index) { + assert((*ip)->part_of_subsidy & POS_DST); + subsidised = true; + if (!s->IsAwarded()) s->AwardTo(company); + } + } break; - - default: - xy = Industry::Get(s->dst)->xy; + case ST_TOWN: + for (const Town * const *tp = towns_near.Begin(); tp != towns_near.End(); tp++) { + if (s->dst == (*tp)->index) { + assert((*tp)->part_of_subsidy & POS_DST); + subsidised = true; + if (!s->IsAwarded()) s->AwardTo(company); + } + } break; + default: + NOT_REACHED(); } - if (DistanceMax(xy, to->xy) > 9) continue; - - s->AwardTo(from->index, to->index, company); - return true; } } - return false; + + return subsidised; } diff --git a/src/subsidy_base.h b/src/subsidy_base.h index 1460c4eecb..4750605bc6 100644 --- a/src/subsidy_base.h +++ b/src/subsidy_base.h @@ -7,18 +7,17 @@ #include "cargo_type.h" #include "company_type.h" -#include "station_type.h" - -typedef uint16 SubsidyID; ///< ID of a subsidy +#include "subsidy_type.h" /** Struct about subsidies, offered and awarded */ struct Subsidy { CargoID cargo_type; ///< Cargo type involved in this subsidy, CT_INVALID for invalid subsidy - byte age; ///< Subsidy age; < 12 is unawarded, >= 12 is awarded - SourceTypeByte src_type; ///< Source of subsidised path - SourceTypeByte dst_type; ///< Destination of subsidised path - uint16 src; ///< Index of source. Either TownID, IndustryID or StationID, when awarded - uint16 dst; ///< Index of destination. Either TownID, IndustryID or StationID, when awarded + byte remaining; ///< Remaining months when this subsidy is valid + CompanyByte awarded; ///< Subsidy is awarded to this company; INVALID_COMPANY if it's not awarded to anyone + SourceTypeByte src_type; ///< Source of subsidised path (ST_INDUSTRY or ST_TOWN) + SourceTypeByte dst_type; ///< Destination of subsidised path (ST_INDUSTRY or ST_TOWN) + SourceID src; ///< Index of source. Either TownID or IndustryID + SourceID dst; ///< Index of destination. Either TownID or IndustryID /** * Tests whether this subsidy has been awarded to someone @@ -26,10 +25,10 @@ struct Subsidy { */ FORCEINLINE bool IsAwarded() const { - return this->age >= 12; + return this->awarded != INVALID_COMPANY; } - void AwardTo(StationID from, StationID to, CompanyID company); + void AwardTo(CompanyID company); /** * Determines index of this subsidy diff --git a/src/subsidy_func.h b/src/subsidy_func.h index 5ec466a5f6..1cca00a590 100644 --- a/src/subsidy_func.h +++ b/src/subsidy_func.h @@ -13,7 +13,9 @@ Pair SetupSubsidyDecodeParam(const struct Subsidy *s, bool mode); void DeleteSubsidyWith(SourceType type, SourceID index); -bool CheckSubsidised(const Station *from, const Station *to, CargoID cargo_type, CompanyID company); +bool CheckSubsidised(CargoID cargo_type, CompanyID company, SourceType src_type, SourceID src, const Station *st); void SubsidyMonthlyHandler(); +void RebuildSubsidisedSourceAndDestinationCache(); +void DeleteSubsidy(struct Subsidy *s); #endif /* SUBSIDY_FUNC_H */ diff --git a/src/subsidy_gui.cpp b/src/subsidy_gui.cpp index de7d71c570..becc4d97a5 100644 --- a/src/subsidy_gui.cpp +++ b/src/subsidy_gui.cpp @@ -83,7 +83,6 @@ struct SubsidyListWindow : Window { switch (s->src_type) { case ST_INDUSTRY: xy = Industry::Get(s->src)->xy; break; case ST_TOWN: xy = Town::Get(s->src)->xy; break; - case ST_STATION: xy = Station::Get(s->src)->xy; break; default: NOT_REACHED(); } @@ -94,11 +93,9 @@ struct SubsidyListWindow : Window { switch (s->dst_type) { case ST_INDUSTRY: xy = Industry::Get(s->dst)->xy; break; case ST_TOWN: xy = Town::Get(s->dst)->xy; break; - case ST_STATION: xy = Station::Get(s->dst)->xy; break; default: NOT_REACHED(); } - if (_ctrl_pressed) { ShowExtraViewPortWindow(xy); } else { @@ -129,7 +126,7 @@ struct SubsidyListWindow : Window { if (!s->IsAwarded()) { /* Displays the two offered towns */ SetupSubsidyDecodeParam(s, 1); - SetDParam(7, _date - ymd.day + 384 - s->age * 32); + SetDParam(7, _date - ymd.day + s->remaining * 32); DrawString(x + 2, right - 2, y, STR_SUBSIDIES_OFFERED_FROM_TO); y += FONT_HEIGHT_NORMAL; @@ -150,8 +147,8 @@ struct SubsidyListWindow : Window { FOR_ALL_SUBSIDIES(s) { if (s->IsAwarded()) { SetupSubsidyDecodeParam(s, 1); - SetDParam(3, Station::Get(s->dst)->owner); - SetDParam(4, _date - ymd.day + 768 - s->age * 32); + SetDParam(7, s->awarded); + SetDParam(8, _date - ymd.day + s->remaining * 32); /* Displays the two connected stations */ DrawString(x + 2, right - 2, y, STR_SUBSIDIES_SUBSIDISED_FROM_TO); diff --git a/src/subsidy_type.h b/src/subsidy_type.h new file mode 100644 index 0000000000..db7f989ebb --- /dev/null +++ b/src/subsidy_type.h @@ -0,0 +1,22 @@ +/* $Id$ */ + +/** @file subsidy_type.h basic types related to subsidies */ + +#ifndef SUBSIDY_TYPE_H +#define SUBSIDY_TYPE_H + +#include "core/enum_type.hpp" + +enum PartOfSubsidy { + POS_NONE = 0, + POS_SRC = 1 << 0, ///< bit 0 set -> town/industry is source of subsidised path + POS_DST = 1 << 1, ///< bit 1 set -> town/industry is destination of subsidised path +}; +typedef SimpleTinyEnumT PartOfSubsidyByte; + +DECLARE_ENUM_AS_BIT_SET(PartOfSubsidy); + +typedef uint16 SubsidyID; ///< ID of a subsidy +struct Subsidy; + +#endif /* SUBSIDY_TYPE_H */ diff --git a/src/town.h b/src/town.h index 38327fa414..d41b1fc827 100644 --- a/src/town.h +++ b/src/town.h @@ -20,6 +20,7 @@ #include "map_type.h" #include "command_type.h" #include "town_map.h" +#include "subsidy_type.h" template struct BuildingCounts { @@ -107,6 +108,8 @@ struct Town : TownPool::PoolItem<&_town_pool> { bool larger_town; TownLayoutByte layout; ///< town specific road layout + PartOfSubsidyByte part_of_subsidy; ///< NOSAVE: is this town a source/destination of a subsidy? + /* NOSAVE: UpdateTownRadius updates this given the house count. */ uint32 squared_town_zone_radius[HZB_END]; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index bb16c11e12..b4249a1f86 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -99,7 +99,7 @@ Town::~Town() } DeleteSubsidyWith(ST_TOWN, this->index); - + CargoPacket::InvalidateAllFrom(ST_TOWN, this->index); MarkWholeScreenDirty(); } @@ -460,7 +460,7 @@ static void TileLoop_Town(TileIndex tile) uint amt = GB(callback, 0, 8); if (amt == 0) continue; - uint moved = MoveGoodsToStation(tile, 1, 1, cargo, amt); + uint moved = MoveGoodsToStation(tile, 1, 1, cargo, amt, ST_TOWN, t->index); const CargoSpec *cs = CargoSpec::Get(cargo); switch (cs->town_effect) { @@ -484,7 +484,7 @@ static void TileLoop_Town(TileIndex tile) if (_economy.fluct <= 0) amt = (amt + 1) >> 1; t->new_max_pass += amt; - t->new_act_pass += MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt); + t->new_act_pass += MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt, ST_TOWN, t->index); } if (GB(r, 8, 8) < hs->mail_generation) { @@ -492,7 +492,7 @@ static void TileLoop_Town(TileIndex tile) if (_economy.fluct <= 0) amt = (amt + 1) >> 1; t->new_max_mail += amt; - t->new_act_mail += MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt); + t->new_act_mail += MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt, ST_TOWN, t->index); } } diff --git a/src/unmovable_cmd.cpp b/src/unmovable_cmd.cpp index 832318dd51..0aec67b6a3 100644 --- a/src/unmovable_cmd.cpp +++ b/src/unmovable_cmd.cpp @@ -23,6 +23,7 @@ #include "cheat_type.h" #include "landscape_type.h" #include "unmovable.h" +#include "cargopacket.h" #include "table/strings.h" #include "table/sprites.h" @@ -62,6 +63,8 @@ static CommandCost DestroyCompanyHQ(CompanyID cid, DoCommandFlag flags) DoClearSquare(t + TileDiffXY(1, 1)); c->location_of_HQ = INVALID_TILE; // reset HQ position InvalidateWindow(WC_COMPANY, cid); + + CargoPacket::InvalidateAllFrom(ST_HEADQUARTERS, cid); } /* cost of relocating company is 1% of company value */ @@ -335,7 +338,7 @@ static void TileLoop_Unmovable(TileIndex tile) if (GB(r, 0, 8) < (256 / 4 / (6 - level))) { uint amt = GB(r, 0, 8) / 8 / 4 + 1; if (_economy.fluct <= 0) amt = (amt + 1) >> 1; - MoveGoodsToStation(tile, 2, 2, CT_PASSENGERS, amt); + MoveGoodsToStation(tile, 2, 2, CT_PASSENGERS, amt, ST_HEADQUARTERS, GetTileOwner(tile)); } /* Top town building generates 90, HQ can make up to 196. The @@ -344,7 +347,7 @@ static void TileLoop_Unmovable(TileIndex tile) if (GB(r, 8, 8) < (196 / 4 / (6 - level))) { uint amt = GB(r, 8, 8) / 8 / 4 + 1; if (_economy.fluct <= 0) amt = (amt + 1) >> 1; - MoveGoodsToStation(tile, 2, 2, CT_MAIL, amt); + MoveGoodsToStation(tile, 2, 2, CT_MAIL, amt, ST_HEADQUARTERS, GetTileOwner(tile)); } }