summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsmatz <smatz@openttd.org>2009-08-08 16:42:55 +0000
committersmatz <smatz@openttd.org>2009-08-08 16:42:55 +0000
commit2a430d981f680485b9d4f9e5fab8bc642952b9bf (patch)
treee37f617ae610677d7c92aad77b5f184545599102
parenteff8cb839072c3aa80d1e54b189810061160669a (diff)
downloadopenttd-2a430d981f680485b9d4f9e5fab8bc642952b9bf.tar.xz
(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
-rw-r--r--projects/openttd_vs80.vcproj4
-rw-r--r--projects/openttd_vs90.vcproj4
-rw-r--r--source.list1
-rw-r--r--src/ai/api/ai_changelog.hpp2
-rw-r--r--src/ai/api/ai_subsidy.cpp19
-rw-r--r--src/ai/api/ai_subsidy.hpp16
-rw-r--r--src/cargo_type.h10
-rw-r--r--src/cargopacket.cpp27
-rw-r--r--src/cargopacket.h11
-rw-r--r--src/economy.cpp43
-rw-r--r--src/economy_func.h2
-rw-r--r--src/industry.h3
-rw-r--r--src/industry_cmd.cpp5
-rw-r--r--src/lang/english.txt12
-rw-r--r--src/saveload/afterload.cpp19
-rw-r--r--src/saveload/cargopacket_sl.cpp2
-rw-r--r--src/saveload/oldloader_sl.cpp2
-rw-r--r--src/saveload/saveload.cpp2
-rw-r--r--src/saveload/subsidy_sl.cpp13
-rw-r--r--src/station.cpp3
-rw-r--r--src/station_cmd.cpp12
-rw-r--r--src/subsidy.cpp202
-rw-r--r--src/subsidy_base.h19
-rw-r--r--src/subsidy_func.h4
-rw-r--r--src/subsidy_gui.cpp9
-rw-r--r--src/subsidy_type.h22
-rw-r--r--src/town.h3
-rw-r--r--src/town_cmd.cpp8
-rw-r--r--src/unmovable_cmd.cpp7
29 files changed, 309 insertions, 177 deletions
diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj
index bf10c3c04..2b8d7257a 100644
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -1488,6 +1488,10 @@
>
</File>
<File
+ RelativePath=".\..\src\subsidy_type.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\tar_type.h"
>
</File>
diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj
index 0e07feca7..5b65ba977 100644
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -1485,6 +1485,10 @@
>
</File>
<File
+ RelativePath=".\..\src\subsidy_type.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\tar_type.h"
>
</File>
diff --git a/source.list b/source.list
index 4318e4dc4..ca42b2430 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 5750ab0ac..a8e511030 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 fd3e29745..39358e963 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 7be86b0e8..96ad92c31 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 30145f266..0222af806 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<SourceType, byte> 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 65514e647..355cabebb 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 414003faa..de8268a98 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 <list>
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 45cab5c59..f8bba522c 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 85def7807..af31e8c7d 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 404a4e25a..090f9267d 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 f38648a15..3efc21a35 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 ca5c5bf70..6ed40ea98 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 fa772cac1..0331feed7 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 d0a7783b8..7a6a1c812 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 f8fc0b777..14db853bf 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 731679dc5..ddb374dd0 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 b1e889e8f..163a9ce8c 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 81c6c186d..749c81174 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 6d007dfcc..842c35134 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 d09030df4..ad79c37e0 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<char>(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<const Town *, 2> 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 1460c4eec..4750605bc 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 5ec466a5f..1cca00a59 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 de7d71c57..becc4d97a 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 000000000..db7f989eb
--- /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<PartOfSubsidy, byte> 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 38327fa41..d41b1fc82 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 <typename T>
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 bb16c11e1..b4249a1f8 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 832318dd5..0aec67b6a 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));
}
}