changeset 12652:0f7fab6a27e9 draft

(svn r17107) -Codechange: store type of subsidy source and destination in the Subsidy struct instead of determining it every time it's needed
author smatz <smatz@openttd.org>
date Fri, 07 Aug 2009 22:23:34 +0000
parents e3aac139122f
children ec0f06c32432
files src/ai/api/ai_subsidy.cpp src/cargo_type.h src/economy.cpp src/industry_cmd.cpp src/saveload/afterload.cpp src/saveload/oldloader_sl.cpp src/saveload/subsidy_sl.cpp src/station.cpp src/subsidy.cpp src/subsidy_base.h src/subsidy_func.h src/subsidy_gui.cpp src/town_cmd.cpp
diffstat 13 files changed, 156 insertions(+), 170 deletions(-) [+]
line wrap: on
line diff
--- a/src/ai/api/ai_subsidy.cpp
+++ b/src/ai/api/ai_subsidy.cpp
@@ -10,21 +10,21 @@
 
 /* static */ bool AISubsidy::IsValidSubsidy(SubsidyID subsidy_id)
 {
-	return Subsidy::IsValidID(subsidy_id);
+	return ::Subsidy::IsValidID(subsidy_id);
 }
 
 /* static */ bool AISubsidy::IsAwarded(SubsidyID subsidy_id)
 {
 	if (!IsValidSubsidy(subsidy_id)) return false;
 
-	return Subsidy::Get(subsidy_id)->IsAwarded();
+	return ::Subsidy::Get(subsidy_id)->IsAwarded();
 }
 
 /* static */ AICompany::CompanyID AISubsidy::GetAwardedTo(SubsidyID subsidy_id)
 {
 	if (!IsAwarded(subsidy_id)) return AICompany::COMPANY_INVALID;
 
-	return (AICompany::CompanyID)((byte)Station::Get(Subsidy::Get(subsidy_id)->from)->owner);
+	return (AICompany::CompanyID)((byte)::Station::Get(::Subsidy::Get(subsidy_id)->src)->owner);
 }
 
 /* static */ int32 AISubsidy::GetExpireDate(SubsidyID subsidy_id)
@@ -35,9 +35,9 @@
 	int month = AIDate::GetMonth(AIDate::GetCurrentDate());
 
 	if (IsAwarded(subsidy_id)) {
-		month += 24 - Subsidy::Get(subsidy_id)->age;
+		month += 24 - ::Subsidy::Get(subsidy_id)->age;
 	} else {
-		month += 12 - Subsidy::Get(subsidy_id)->age;
+		month += 12 - ::Subsidy::Get(subsidy_id)->age;
 	}
 
 	year += (month - 1) / 12;
@@ -50,42 +50,33 @@
 {
 	if (!IsValidSubsidy(subsidy_id)) return CT_INVALID;
 
-	return Subsidy::Get(subsidy_id)->cargo_type;
+	return ::Subsidy::Get(subsidy_id)->cargo_type;
 }
 
 /* static */ bool AISubsidy::SourceIsTown(SubsidyID subsidy_id)
 {
 	if (!IsValidSubsidy(subsidy_id) || IsAwarded(subsidy_id)) return false;
 
-	return CargoSpec::Get(GetCargoType(subsidy_id))->town_effect == TE_PASSENGERS ||
-	       CargoSpec::Get(GetCargoType(subsidy_id))->town_effect == TE_MAIL;
+	return ::Subsidy::Get(subsidy_id)->src_type == ST_TOWN;
 }
 
 /* static */ int32 AISubsidy::GetSource(SubsidyID subsidy_id)
 {
 	if (!IsValidSubsidy(subsidy_id)) return INVALID_STATION;
 
-	return Subsidy::Get(subsidy_id)->from;
+	return ::Subsidy::Get(subsidy_id)->src;
 }
 
 /* static */ bool AISubsidy::DestinationIsTown(SubsidyID subsidy_id)
 {
 	if (!IsValidSubsidy(subsidy_id) || IsAwarded(subsidy_id)) return false;
 
-	switch (CargoSpec::Get(GetCargoType(subsidy_id))->town_effect) {
-		case TE_PASSENGERS:
-		case TE_MAIL:
-		case TE_GOODS:
-		case TE_FOOD:
-			return true;
-		default:
-			return false;
-	}
+	return ::Subsidy::Get(subsidy_id)->dst_type == ST_TOWN;
 }
 
 /* static */ int32 AISubsidy::GetDestination(SubsidyID subsidy_id)
 {
 	if (!IsValidSubsidy(subsidy_id)) return INVALID_STATION;
 
-	return Subsidy::Get(subsidy_id)->to;
+	return ::Subsidy::Get(subsidy_id)->dst;
 }
--- a/src/cargo_type.h
+++ b/src/cargo_type.h
@@ -5,6 +5,8 @@
 #ifndef CARGO_TYPE_H
 #define CARGO_TYPE_H
 
+#include "core/enum_type.hpp"
+
 typedef byte CargoID;
 
 /** Available types of cargo */
@@ -82,4 +84,16 @@
 	}
 };
 
+
+/** Types of subsidy 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
+};
+typedef SimpleTinyEnumT<SourceType, byte> SourceTypeByte;
+
+typedef uint16 SourceID; ///< Contains either industry ID, town ID or station ID (or INVALID_SOURCE)
+static const SourceID INVALID_SOURCE = 0xFFFF; ///< Invalid/unknown index of source
+
 #endif /* CARGO_TYPE_H */
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -331,7 +331,7 @@
 	if (new_owner == INVALID_OWNER) {
 		Subsidy *s;
 		FOR_ALL_SUBSIDIES(s) {
-			if (s->IsAwarded() && Station::Get(s->to)->owner == old_owner) {
+			if (s->IsAwarded() && Station::Get(s->dst)->owner == old_owner) {
 				s->cargo_type = CT_INVALID;
 			}
 		}
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -167,7 +167,7 @@
 
 	DecIndustryTypeCount(this->type);
 
-	DeleteSubsidyWithIndustry(this->index);
+	DeleteSubsidyWith(ST_INDUSTRY, this->index);
 	DeleteIndustryNews(this->index);
 	DeleteWindowById(WC_INDUSTRY_VIEW, this->index);
 	InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -1850,36 +1850,6 @@
 				i++;
 			}
 		}
-
-		/* Delete invalid subsidies possibly present in old versions (but converted to new savegame) */
-		Subsidy *s;
-		FOR_ALL_SUBSIDIES(s) {
-			if (s->IsAwarded()) {
-				/* Station -> Station */
-				const Station *from = Station::GetIfValid(s->from);
-				const Station *to = Station::GetIfValid(s->to);
-				if (from != NULL && to != NULL && from->owner == to->owner && Company::IsValidID(from->owner)) continue;
-			} else {
-				const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
-				switch (cs->town_effect) {
-					case TE_PASSENGERS:
-					case TE_MAIL:
-						/* Town -> Town */
-						if (Town::IsValidID(s->from) && Town::IsValidID(s->to)) continue;
-						break;
-					case TE_GOODS:
-					case TE_FOOD:
-						/* Industry -> Town */
-						if (Industry::IsValidID(s->from) && Town::IsValidID(s->to)) continue;
-						break;
-					default:
-						/* Industry -> Industry */
-						if (Industry::IsValidID(s->from) && Industry::IsValidID(s->to)) continue;
-						break;
-				}
-			}
-			s->cargo_type = CT_INVALID;
-		}
 	}
 
 	if (CheckSavegameVersion(124)) {
@@ -1898,6 +1868,43 @@
 		}
 	}
 
+	{
+		/* Delete invalid subsidies possibly present in old versions (but converted to new savegame) */
+		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 {
+				const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
+				switch (cs->town_effect) {
+					case TE_PASSENGERS:
+					case TE_MAIL:
+						/* Town -> Town */
+						s->src_type = s->dst_type = ST_TOWN;
+						if (Town::IsValidID(s->src) && Town::IsValidID(s->dst)) continue;
+						break;
+					case TE_GOODS:
+					case TE_FOOD:
+						/* Industry -> Town */
+						s->src_type = ST_INDUSTRY;
+						s->dst_type = ST_TOWN;
+						if (Industry::IsValidID(s->src) && Town::IsValidID(s->dst)) continue;
+						break;
+					default:
+						/* Industry -> Industry */
+						s->src_type = s->dst_type = ST_INDUSTRY;
+						if (Industry::IsValidID(s->src) && Industry::IsValidID(s->dst)) continue;
+						break;
+				}
+			}
+			s->cargo_type = CT_INVALID;
+		}
+	}
+
 	AfterLoadLabelMaps();
 
 	GamelogPrintDebug(1);
--- a/src/saveload/oldloader_sl.cpp
+++ b/src/saveload/oldloader_sl.cpp
@@ -1469,8 +1469,8 @@
 static const OldChunks subsidy_chunk[] = {
 	OCL_SVAR(  OC_UINT8, Subsidy, cargo_type ),
 	OCL_SVAR(  OC_UINT8, Subsidy, age ),
-	OCL_SVAR(  OC_FILE_U8 | OC_VAR_U16, Subsidy, from ),
-	OCL_SVAR(  OC_FILE_U8 | OC_VAR_U16, Subsidy, to ),
+	OCL_SVAR(  OC_FILE_U8 | OC_VAR_U16, Subsidy, src ),
+	OCL_SVAR(  OC_FILE_U8 | OC_VAR_U16, Subsidy, dst ),
 
 	OCL_END()
 };
--- a/src/saveload/subsidy_sl.cpp
+++ b/src/saveload/subsidy_sl.cpp
@@ -10,10 +10,10 @@
 static const SaveLoad _subsidies_desc[] = {
 	    SLE_VAR(Subsidy, cargo_type, SLE_UINT8),
 	    SLE_VAR(Subsidy, age,        SLE_UINT8),
-	SLE_CONDVAR(Subsidy, from,       SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
-	SLE_CONDVAR(Subsidy, from,       SLE_UINT16,                5, SL_MAX_VERSION),
-	SLE_CONDVAR(Subsidy, to,         SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
-	SLE_CONDVAR(Subsidy, to,         SLE_UINT16,                5, 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()
 };
 
--- a/src/station.cpp
+++ b/src/station.cpp
@@ -88,10 +88,10 @@
 	DeleteWindowById(WC_AIRCRAFT_LIST, wno | (VEH_AIRCRAFT << 11));
 
 	/* Now delete all orders that go to the station */
-	RemoveOrderFromAllVehicles(OT_GOTO_STATION, index);
+	RemoveOrderFromAllVehicles(OT_GOTO_STATION, this->index);
 
 	/* Subsidies need removal as well */
-	DeleteSubsidyWithStation(index);
+	DeleteSubsidyWith(ST_STATION, this->index);
 
 	/* Remove all news items */
 	DeleteStationNews(this->index);
--- a/src/subsidy.cpp
+++ b/src/subsidy.cpp
@@ -31,8 +31,9 @@
 	assert(!this->IsAwarded());
 
 	this->age = 12;
-	this->from = from;
-	this->to = to;
+	this->src_type = this->dst_type = ST_STATION;
+	this->src = from;
+	this->dst = to;
 
 	/* Add a news item */
 	Pair reftype = SetupSubsidyDecodeParam(this, 0);
@@ -46,7 +47,7 @@
 	AddNewsItem(
 		STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier,
 		NS_SUBSIDIES,
-		(NewsReferenceType)reftype.a, this->from, (NewsReferenceType)reftype.b, this->to,
+		(NewsReferenceType)reftype.a, this->src, (NewsReferenceType)reftype.b, this->dst,
 		company_name
 	);
 	AI::BroadcastNewEvent(new AIEventSubsidyAwarded(this->Index()));
@@ -95,37 +96,39 @@
 	const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
 	SetDParam(0, mode ? cs->name : cs->name_single);
 
-	if (!s->IsAwarded()) {
-		if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL) {
+	switch (s->src_type) {
+		case ST_INDUSTRY:
+			reftype1 = NR_INDUSTRY;
 			SetDParam(1, STR_INDUSTRY_NAME);
-			SetDParam(2, s->from);
-			reftype1 = NR_INDUSTRY;
+			break;
+		case ST_TOWN:
+			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);
 
-			if (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD) {
-				SetDParam(4, STR_INDUSTRY_NAME);
-				SetDParam(5, s->to);
-				reftype2 = NR_INDUSTRY;
-			} else {
-				SetDParam(4, STR_TOWN_NAME);
-				SetDParam(5, s->to);
-				reftype2 = NR_TOWN;
-			}
-		} else {
-			SetDParam(1, STR_TOWN_NAME);
-			SetDParam(2, s->from);
-			reftype1 = NR_TOWN;
-
+	switch (s->dst_type) {
+		case ST_INDUSTRY:
+			reftype2 = NR_INDUSTRY;
+			SetDParam(4, STR_INDUSTRY_NAME);
+			break;
+		case ST_TOWN:
+			reftype2 = NR_TOWN;
 			SetDParam(4, STR_TOWN_NAME);
-			SetDParam(5, s->to);
-			reftype2 = NR_TOWN;
-		}
-	} else {
-		SetDParam(1, s->from);
-		reftype1 = NR_STATION;
-
-		SetDParam(2, s->to);
-		reftype2 = NR_STATION;
+			break;
+		case ST_STATION:
+			reftype2 = NR_STATION;
+			SetDParam(2, s->dst);
+			break;
+		default: NOT_REACHED();
 	}
+	SetDParam(5, s->dst);
 
 	Pair p;
 	p.a = reftype1;
@@ -133,48 +136,19 @@
 	return p;
 }
 
-void DeleteSubsidyWithTown(TownID index)
-{
-	Subsidy *s;
-	FOR_ALL_SUBSIDIES(s) {
-		if (!s->IsAwarded()) {
-			const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
-			if (((cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) && (index == s->from || index == s->to)) ||
-				((cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) && index == s->to)) {
-				s->cargo_type = CT_INVALID;
-			}
-		}
-	}
-}
-
-void DeleteSubsidyWithIndustry(IndustryID index)
-{
-	Subsidy *s;
-	FOR_ALL_SUBSIDIES(s) {
-		if (!s->IsAwarded()) {
-			const CargoSpec *cs = CargoSpec::Get(s->cargo_type);
-			if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL &&
-				(index == s->from || (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD && index == s->to))) {
-				s->cargo_type = CT_INVALID;
-			}
-		}
-	}
-}
-
-void DeleteSubsidyWithStation(StationID index)
+void DeleteSubsidyWith(SourceType type, SourceID index)
 {
 	bool dirty = false;
 
 	Subsidy *s;
 	FOR_ALL_SUBSIDIES(s) {
-		if (s->IsAwarded() && (s->from == index || s->to == index)) {
+		if ((s->src_type == type && s->src == index) || (s->dst_type == type && s->dst == index)) {
 			s->cargo_type = CT_INVALID;
 			dirty = true;
 		}
 	}
 
-	if (dirty)
-		InvalidateWindow(WC_SUBSIDIES_LIST, 0);
+	if (dirty) InvalidateWindow(WC_SUBSIDIES_LIST, 0);
 }
 
 struct FoundRoute {
@@ -261,10 +235,9 @@
 {
 	const Subsidy *ss;
 	FOR_ALL_SUBSIDIES(ss) {
-		if (s != ss &&
-				ss->from == s->from &&
-				ss->to == s->to &&
-				ss->cargo_type == s->cargo_type) {
+		if (s != ss && ss->cargo_type == s->cargo_type &&
+				ss->src_type == s->src_type && ss->src == s->src &&
+				ss->dst_type == s->dst_type && ss->dst == s->dst) {
 			s->cargo_type = CT_INVALID;
 			return true;
 		}
@@ -275,24 +248,21 @@
 
 void SubsidyMonthlyLoop()
 {
-	Station *st;
-	uint n;
-	FoundRoute fr;
 	bool modified = false;
 
 	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->from, (NewsReferenceType)reftype.b, s->to);
+			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) {
-			st = Station::Get(s->to);
+			Station *st = Station::Get(s->dst);
 			if (st->owner == _local_company) {
 				Pair reftype = SetupSubsidyDecodeParam(s, 1);
-				AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->from, (NewsReferenceType)reftype.b, s->to);
+				AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst);
 			}
 			s->cargo_type = CT_INVALID;
 			modified = true;
@@ -308,28 +278,37 @@
 		s = Subsidy::AllocateItem();
 		if (s == NULL) goto no_add;
 
-		n = 1000;
+		uint n = 1000;
 		do {
+			FoundRoute fr;
 			FindSubsidyPassengerRoute(&fr);
 			if (fr.distance <= 70) {
 				s->cargo_type = CT_PASSENGERS;
-				s->from = ((Town*)fr.from)->index;
-				s->to = ((Town*)fr.to)->index;
+				s->src_type = s->dst_type = ST_TOWN;
+				s->src = ((Town *)fr.from)->index;
+				s->dst = ((Town *)fr.to)->index;
 				goto add_subsidy;
 			}
 			FindSubsidyCargoRoute(&fr);
 			if (fr.distance <= 70) {
 				s->cargo_type = fr.cargo;
-				s->from = ((Industry*)fr.from)->index;
+				s->src_type = ST_INDUSTRY;
+				s->src = ((Industry *)fr.from)->index;
 				{
 					const CargoSpec *cs = CargoSpec::Get(fr.cargo);
-					s->to = (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index;
+					if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) {
+						s->dst_type = ST_INDUSTRY;
+						s->dst = ((Industry *)fr.to)->index;
+					} else {
+						s->dst_type = ST_TOWN;
+						s->dst = ((Town *)fr.to)->index;
+					}
 				}
 	add_subsidy:
 				if (!CheckSubsidyDuplicate(s)) {
 					s->age = 0;
 					Pair reftype = SetupSubsidyDecodeParam(s, 0);
-					AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->from, (NewsReferenceType)reftype.b, s->to);
+					AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst);
 					AI::BroadcastNewEvent(new AIEventSubsidyOffer(s->Index()));
 					modified = true;
 					break;
@@ -351,8 +330,8 @@
 	FOR_ALL_SUBSIDIES(s) {
 		if (s->cargo_type == cargo_type &&
 				s->IsAwarded() &&
-				s->from == from->index &&
-				s->to == to->index) {
+				s->src == from->index &&
+				s->dst == to->index) {
 			return true;
 		}
 	}
@@ -363,9 +342,9 @@
 			/* 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->from)->xy;
+				xy = Town::Get(s->src)->xy;
 			} else {
-				xy = Industry::Get(s->from)->xy;
+				xy = Industry::Get(s->src)->xy;
 			}
 			if (DistanceMax(xy, from->xy) > 9) continue;
 
@@ -375,11 +354,11 @@
 				case TE_MAIL:
 				case TE_GOODS:
 				case TE_FOOD:
-					xy = Town::Get(s->to)->xy;
+					xy = Town::Get(s->dst)->xy;
 					break;
 
 				default:
-					xy = Industry::Get(s->to)->xy;
+					xy = Industry::Get(s->dst)->xy;
 					break;
 			}
 			if (DistanceMax(xy, to->xy) > 9) continue;
--- a/src/subsidy_base.h
+++ b/src/subsidy_base.h
@@ -13,10 +13,12 @@
 
 /** 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
-	uint16 from;        ///< Index of source. Either TownID, IndustryID or StationID, when awarded
-	uint16 to;          ///< Index of destination. Either TownID, IndustryID or StationID, when awarded
+	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
 
 	/**
 	 * Tests whether this subsidy has been awarded to someone
--- a/src/subsidy_func.h
+++ b/src/subsidy_func.h
@@ -12,9 +12,7 @@
 #include "company_type.h"
 
 Pair SetupSubsidyDecodeParam(const struct Subsidy *s, bool mode);
-void DeleteSubsidyWithTown(TownID index);
-void DeleteSubsidyWithIndustry(IndustryID index);
-void DeleteSubsidyWithStation(StationID index);
+void DeleteSubsidyWith(SourceType type, SourceID index);
 bool CheckSubsidised(const Station *from, const Station *to, CargoID cargo_type, CompanyID company);
 void SubsidyMonthlyHandler();
 
--- a/src/subsidy_gui.cpp
+++ b/src/subsidy_gui.cpp
@@ -78,32 +78,27 @@
 
 	void HandleClick(const Subsidy *s)
 	{
-		TownEffect te = CargoSpec::Get(s->cargo_type)->town_effect;
+		/* determine src coordinate for subsidy and try to scroll to it */
 		TileIndex xy;
-
-		/* determine from coordinate for subsidy and try to scroll to it */
-		uint offs = s->from;
-		if (s->IsAwarded()) {
-			xy = Station::Get(offs)->xy;
-		} else if (te == TE_PASSENGERS || te == TE_MAIL) {
-			xy = Town::Get(offs)->xy;
-		} else {
-			xy = Industry::Get(offs)->xy;
+		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();
 		}
 
 		if (_ctrl_pressed || !ScrollMainWindowToTile(xy)) {
 			if (_ctrl_pressed) ShowExtraViewPortWindow(xy);
 
-			/* otherwise determine to coordinate for subsidy and scroll to it */
-			offs = s->to;
-			if (s->IsAwarded()) {
-				xy = Station::Get(offs)->xy;
-			} else if (te == TE_PASSENGERS || te == TE_MAIL || te == TE_GOODS || te == TE_FOOD) {
-				xy = Town::Get(offs)->xy;
-			} else {
-				xy = Industry::Get(offs)->xy;
+			/* otherwise determine dst coordinate for subsidy and scroll to it */
+			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 {
@@ -155,7 +150,7 @@
 		FOR_ALL_SUBSIDIES(s) {
 			if (s->IsAwarded()) {
 				SetupSubsidyDecodeParam(s, 1);
-				SetDParam(3, Station::Get(s->to)->owner);
+				SetDParam(3, Station::Get(s->dst)->owner);
 				SetDParam(4, _date - ymd.day + 768 - s->age * 32);
 
 				/* Displays the two connected stations */
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -98,7 +98,7 @@
 		}
 	}
 
-	DeleteSubsidyWithTown(this->index);
+	DeleteSubsidyWith(ST_TOWN, this->index);
 
 	MarkWholeScreenDirty();
 }