diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index f874993826..016f26028d 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -719,6 +719,10 @@ RelativePath=".\..\src\strings.cpp" > + + @@ -1443,6 +1447,14 @@ RelativePath=".\..\src\strings_type.h" > + + + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index ec1db4894f..3ca3c8363d 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -716,6 +716,10 @@ RelativePath=".\..\src\strings.cpp" > + + @@ -1440,6 +1444,14 @@ RelativePath=".\..\src\strings_type.h" > + + + + diff --git a/source.list b/source.list index 83ad09ed62..bb05a91da7 100644 --- a/source.list +++ b/source.list @@ -74,6 +74,7 @@ spritecache.cpp station.cpp string.cpp strings.cpp +subsidy.cpp texteff.cpp tgp.cpp #if HAVE_THREAD @@ -291,6 +292,8 @@ string_func.h string_type.h strings_func.h strings_type.h +subsidy_func.h +subsidy_type.h tar_type.h terraform_gui.h textbuf_gui.h diff --git a/src/ai/api/ai_subsidy.cpp b/src/ai/api/ai_subsidy.cpp index 4ffdbac2a8..d8804a8282 100644 --- a/src/ai/api/ai_subsidy.cpp +++ b/src/ai/api/ai_subsidy.cpp @@ -4,7 +4,7 @@ #include "ai_subsidy.hpp" #include "ai_date.hpp" -#include "../../economy_func.h" +#include "../../subsidy_type.h" #include "../../station_base.h" #include "../../cargotype.h" diff --git a/src/ai/api/ai_subsidylist.cpp b/src/ai/api/ai_subsidylist.cpp index 8e5d96ad9a..cfda16e9a3 100644 --- a/src/ai/api/ai_subsidylist.cpp +++ b/src/ai/api/ai_subsidylist.cpp @@ -4,7 +4,7 @@ #include "ai_subsidylist.hpp" #include "ai_subsidy.hpp" -#include "../../economy_func.h" +#include "../../subsidy_type.h" AISubsidyList::AISubsidyList() { diff --git a/src/date.cpp b/src/date.cpp index 2f297591d8..46cf235821 100644 --- a/src/date.cpp +++ b/src/date.cpp @@ -163,6 +163,7 @@ extern void EnginesMonthlyLoop(); extern void TownsMonthlyLoop(); extern void IndustryMonthlyLoop(); extern void StationMonthlyLoop(); +extern void SubsidyMonthlyLoop(); extern void CompaniesYearlyLoop(); extern void VehiclesYearlyLoop(); @@ -249,6 +250,7 @@ void IncreaseDate() InvalidateWindowClasses(WC_CHEATS); CompaniesMonthlyLoop(); + SubsidyMonthlyLoop(); EnginesMonthlyLoop(); TownsMonthlyLoop(); IndustryMonthlyLoop(); diff --git a/src/economy.cpp b/src/economy.cpp index 0f90b8bdcb..90732b78b2 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -33,6 +33,7 @@ #include "autoreplace_func.h" #include "company_gui.h" #include "signs_base.h" +#include "subsidy_func.h" #include "table/strings.h" #include "table/sprites.h" @@ -87,7 +88,6 @@ const ScoreInfo _score_info[] = { int _score_part[MAX_COMPANIES][SCORE_END]; Economy _economy; -Subsidy _subsidies[MAX_COMPANIES]; Prices _price; uint16 _price_frac[NUM_PRICES]; Money _cargo_payment_rates[NUM_CARGO]; @@ -857,274 +857,6 @@ Money GetPriceByIndex(uint8 index) return ((Money*)&_price)[index]; } - -Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode) -{ - TileIndex tile; - TileIndex tile2; - Pair tp; - - /* if mode is false, use the singular form */ - const CargoSpec *cs = GetCargo(s->cargo_type); - SetDParam(0, mode ? cs->name : cs->name_single); - - if (s->age < 12) { - if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL) { - SetDParam(1, STR_INDUSTRY); - SetDParam(2, s->from); - tile = Industry::Get(s->from)->xy; - - if (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD) { - SetDParam(4, STR_INDUSTRY); - SetDParam(5, s->to); - tile2 = Industry::Get(s->to)->xy; - } else { - SetDParam(4, STR_TOWN); - SetDParam(5, s->to); - tile2 = Town::Get(s->to)->xy; - } - } else { - SetDParam(1, STR_TOWN); - SetDParam(2, s->from); - tile = Town::Get(s->from)->xy; - - SetDParam(4, STR_TOWN); - SetDParam(5, s->to); - tile2 = Town::Get(s->to)->xy; - } - } else { - SetDParam(1, s->from); - tile = Station::Get(s->from)->xy; - - SetDParam(2, s->to); - tile2 = Station::Get(s->to)->xy; - } - - tp.a = tile; - tp.b = tile2; - - return tp; -} - -void DeleteSubsidyWithTown(TownID index) -{ - Subsidy *s; - - for (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type != CT_INVALID && s->age < 12) { - const CargoSpec *cs = GetCargo(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 (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type != CT_INVALID && s->age < 12) { - const CargoSpec *cs = GetCargo(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) -{ - Subsidy *s; - bool dirty = false; - - for (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type != CT_INVALID && s->age >= 12 && - (s->from == index || s->to == index)) { - s->cargo_type = CT_INVALID; - dirty = true; - } - } - - if (dirty) - InvalidateWindow(WC_SUBSIDIES_LIST, 0); -} - -struct FoundRoute { - uint distance; - CargoID cargo; - void *from; - void *to; -}; - -static void FindSubsidyPassengerRoute(FoundRoute *fr) -{ - Town *from, *to; - - fr->distance = UINT_MAX; - - fr->from = from = GetRandomTown(); - if (from == NULL || from->population < 400) return; - - fr->to = to = GetRandomTown(); - if (from == to || to == NULL || to->population < 400 || to->pct_pass_transported > 42) - return; - - fr->distance = DistanceManhattan(from->xy, to->xy); -} - -static void FindSubsidyCargoRoute(FoundRoute *fr) -{ - Industry *i; - int trans, total; - CargoID cargo; - - fr->distance = UINT_MAX; - - fr->from = i = GetRandomIndustry(); - if (i == NULL) return; - - /* Randomize cargo type */ - if (HasBit(Random(), 0) && i->produced_cargo[1] != CT_INVALID) { - cargo = i->produced_cargo[1]; - trans = i->last_month_pct_transported[1]; - total = i->last_month_production[1]; - } else { - cargo = i->produced_cargo[0]; - trans = i->last_month_pct_transported[0]; - total = i->last_month_production[0]; - } - - /* Quit if no production in this industry - * or if the cargo type is passengers - * or if the pct transported is already large enough */ - if (total == 0 || trans > 42 || cargo == CT_INVALID) return; - - const CargoSpec *cs = GetCargo(cargo); - if (cs->town_effect == TE_PASSENGERS) return; - - fr->cargo = cargo; - - if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) { - /* The destination is a town */ - Town *t = GetRandomTown(); - - /* Only want big towns */ - if (t == NULL || t->population < 900) return; - - fr->distance = DistanceManhattan(i->xy, t->xy); - fr->to = t; - } else { - /* The destination is an industry */ - Industry *i2 = GetRandomIndustry(); - - /* The industry must accept the cargo */ - if (i2 == NULL || i == i2 || - (cargo != i2->accepts_cargo[0] && - cargo != i2->accepts_cargo[1] && - cargo != i2->accepts_cargo[2])) { - return; - } - fr->distance = DistanceManhattan(i->xy, i2->xy); - fr->to = i2; - } -} - -static bool CheckSubsidyDuplicate(Subsidy *s) -{ - const Subsidy *ss; - - for (ss = _subsidies; ss != endof(_subsidies); ss++) { - if (s != ss && - ss->from == s->from && - ss->to == s->to && - ss->cargo_type == s->cargo_type) { - s->cargo_type = CT_INVALID; - return true; - } - } - return false; -} - - -static void SubsidyMonthlyHandler() -{ - Subsidy *s; - Pair pair; - Station *st; - uint n; - FoundRoute fr; - bool modified = false; - - for (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type == CT_INVALID) continue; - - if (s->age == 12 - 1) { - pair = SetupSubsidyDecodeParam(s, 1); - AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NS_SUBSIDIES, pair.a, pair.b); - s->cargo_type = CT_INVALID; - modified = true; - AI::BroadcastNewEvent(new AIEventSubsidyOfferExpired(s - _subsidies)); - } else if (s->age == 2 * 12 - 1) { - st = Station::Get(s->to); - if (st->owner == _local_company) { - pair = SetupSubsidyDecodeParam(s, 1); - AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, pair.a, pair.b); - } - s->cargo_type = CT_INVALID; - modified = true; - AI::BroadcastNewEvent(new AIEventSubsidyExpired(s - _subsidies)); - } else { - s->age++; - } - } - - /* 25% chance to go on */ - if (Chance16(1, 4)) { - /* Find a free slot*/ - s = _subsidies; - while (s->cargo_type != CT_INVALID) { - if (++s == endof(_subsidies)) - goto no_add; - } - - n = 1000; - do { - FindSubsidyPassengerRoute(&fr); - if (fr.distance <= 70) { - s->cargo_type = CT_PASSENGERS; - s->from = ((Town*)fr.from)->index; - s->to = ((Town*)fr.to)->index; - goto add_subsidy; - } - FindSubsidyCargoRoute(&fr); - if (fr.distance <= 70) { - s->cargo_type = fr.cargo; - s->from = ((Industry*)fr.from)->index; - { - const CargoSpec *cs = GetCargo(fr.cargo); - s->to = (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index; - } - add_subsidy: - if (!CheckSubsidyDuplicate(s)) { - s->age = 0; - pair = SetupSubsidyDecodeParam(s, 0); - AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, pair.a, pair.b); - AI::BroadcastNewEvent(new AIEventSubsidyOffer(s - _subsidies)); - modified = true; - break; - } - } - } while (n--); - } -no_add:; - if (modified) - InvalidateWindow(WC_SUBSIDIES_LIST, 0); -} - Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type) { const CargoSpec *cs = GetCargo(cargo_type); @@ -1173,7 +905,6 @@ Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, C return BigMulS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21); } - struct FindIndustryToDeliverData { const Rect *rect; ///< Station acceptance rectangle CargoID cargo_type; ///< Cargo type that was delivered @@ -1273,73 +1004,6 @@ static void DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, int nu } } -static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type) -{ - Subsidy *s; - TileIndex xy; - Pair pair; - - /* check if there is an already existing subsidy that applies to us */ - for (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type == cargo_type && - s->age >= 12 && - s->from == from->index && - s->to == to->index) { - return true; - } - } - - /* check if there's a new subsidy that applies.. */ - for (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type == cargo_type && s->age < 12) { - /* Check distance from source */ - const CargoSpec *cs = GetCargo(cargo_type); - if (cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) { - xy = Town::Get(s->from)->xy; - } else { - xy = Industry::Get(s->from)->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->to)->xy; - break; - - default: - xy = Industry::Get(s->to)->xy; - break; - } - if (DistanceMax(xy, to->xy) > 9) continue; - - /* Found a subsidy, change the values to indicate that it's in use */ - s->age = 12; - s->from = from->index; - s->to = to->index; - - /* Add a news item */ - pair = SetupSubsidyDecodeParam(s, 0); - InjectDParam(1); - - SetDParam(0, _current_company); - AddNewsItem( - STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier, - NS_SUBSIDIES, - pair.a, pair.b - ); - AI::BroadcastNewEvent(new AIEventSubsidyAwarded(s - _subsidies)); - - InvalidateWindow(WC_SUBSIDIES_LIST, 0); - return true; - } - } - return false; -} - /** * Delivers goods to industries/towns and calculates the payment * @param num_pieces amount of cargo delivered @@ -1826,7 +1490,6 @@ void CompaniesMonthlyLoop() /* Reset the _current_company flag */ _current_company = OWNER_NONE; HandleEconomyFluctuations(); - SubsidyMonthlyHandler(); } static void DoAcquireCompany(Company *c) diff --git a/src/economy_func.h b/src/economy_func.h index 8bbb4a7ccb..73d5f7e836 100644 --- a/src/economy_func.h +++ b/src/economy_func.h @@ -22,7 +22,6 @@ void ResetEconomy(); extern const ScoreInfo _score_info[]; extern int _score_part[MAX_COMPANIES][SCORE_END]; extern Economy _economy; -extern Subsidy _subsidies[MAX_COMPANIES]; /* Prices and also the fractional part. */ extern Prices _price; extern uint16 _price_frac[NUM_PRICES]; @@ -30,10 +29,6 @@ extern Money _cargo_payment_rates[NUM_CARGO]; extern uint16 _cargo_payment_rates_frac[NUM_CARGO]; int UpdateCompanyRatingAndValue(Company *c, bool update); -Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode); -void DeleteSubsidyWithTown(TownID index); -void DeleteSubsidyWithIndustry(IndustryID index); -void DeleteSubsidyWithStation(StationID index); void StartupIndustryDailyChanges(bool init_counter); Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type); diff --git a/src/economy_type.h b/src/economy_type.h index 7559612dc0..415e173732 100644 --- a/src/economy_type.h +++ b/src/economy_type.h @@ -23,14 +23,6 @@ struct Economy { uint32 industry_daily_increment; ///< The value which will increment industry_daily_change_counter. Computed value. NOSAVE }; -struct Subsidy { - CargoID cargo_type; - byte age; - /* from and to can either be TownID, StationID or IndustryID */ - uint16 from; - uint16 to; -}; - enum ScoreID { SCORE_BEGIN = 0, SCORE_VEHICLES = 0, diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 902bc90972..ecb2a3c23f 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -34,6 +34,7 @@ #include "effectvehicle_func.h" #include "ai/ai.hpp" #include "core/pool_func.hpp" +#include "subsidy_func.h" #include "table/strings.h" #include "table/industry_land.h" diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 080ea6c902..37860ba16e 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -11,6 +11,7 @@ #include "../ship.h" #include "../train.h" #include "../signs_base.h" +#include "../subsidy_type.h" #include "../debug.h" #include "../depot_base.h" #include "../newgrf_config.h" diff --git a/src/saveload/subsidy_sl.cpp b/src/saveload/subsidy_sl.cpp index dca315f96e..7ff23e6f8e 100644 --- a/src/saveload/subsidy_sl.cpp +++ b/src/saveload/subsidy_sl.cpp @@ -3,7 +3,7 @@ /** @file subsidy_sl.cpp Code handling saving and loading of subsidies */ #include "../stdafx.h" -#include "../economy_func.h" +#include "../subsidy_type.h" #include "saveload.h" diff --git a/src/station.cpp b/src/station.cpp index c3a3c4e385..b8946aeb42 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -20,6 +20,7 @@ #include "aircraft.h" #include "vehicle_gui.h" #include "settings_type.h" +#include "subsidy_func.h" #include "core/pool_func.hpp" #include "table/strings.h" diff --git a/src/subsidy.cpp b/src/subsidy.cpp new file mode 100644 index 0000000000..2ee28c720e --- /dev/null +++ b/src/subsidy.cpp @@ -0,0 +1,354 @@ +/* $Id$ */ + +/** @file subsidy.cpp Handling of subsidies. */ + +#include "stdafx.h" +#include "company_func.h" +#include "industry.h" +#include "map_func.h" +#include "town.h" +#include "news_func.h" +#include "ai/ai.hpp" +#include "station_base.h" +#include "cargotype.h" +#include "strings_func.h" +#include "window_func.h" +#include "subsidy_type.h" + +#include "table/strings.h" + +Subsidy _subsidies[MAX_COMPANIES]; + +Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode) +{ + TileIndex tile; + TileIndex tile2; + Pair tp; + + /* if mode is false, use the singular form */ + const CargoSpec *cs = GetCargo(s->cargo_type); + SetDParam(0, mode ? cs->name : cs->name_single); + + if (s->age < 12) { + if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL) { + SetDParam(1, STR_INDUSTRY); + SetDParam(2, s->from); + tile = Industry::Get(s->from)->xy; + + if (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD) { + SetDParam(4, STR_INDUSTRY); + SetDParam(5, s->to); + tile2 = Industry::Get(s->to)->xy; + } else { + SetDParam(4, STR_TOWN); + SetDParam(5, s->to); + tile2 = Town::Get(s->to)->xy; + } + } else { + SetDParam(1, STR_TOWN); + SetDParam(2, s->from); + tile = Town::Get(s->from)->xy; + + SetDParam(4, STR_TOWN); + SetDParam(5, s->to); + tile2 = Town::Get(s->to)->xy; + } + } else { + SetDParam(1, s->from); + tile = Station::Get(s->from)->xy; + + SetDParam(2, s->to); + tile2 = Station::Get(s->to)->xy; + } + + tp.a = tile; + tp.b = tile2; + + return tp; +} + +void DeleteSubsidyWithTown(TownID index) +{ + Subsidy *s; + + for (s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != CT_INVALID && s->age < 12) { + const CargoSpec *cs = GetCargo(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 (s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != CT_INVALID && s->age < 12) { + const CargoSpec *cs = GetCargo(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) +{ + Subsidy *s; + bool dirty = false; + + for (s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != CT_INVALID && s->age >= 12 && + (s->from == index || s->to == index)) { + s->cargo_type = CT_INVALID; + dirty = true; + } + } + + if (dirty) + InvalidateWindow(WC_SUBSIDIES_LIST, 0); +} + +struct FoundRoute { + uint distance; + CargoID cargo; + void *from; + void *to; +}; + +static void FindSubsidyPassengerRoute(FoundRoute *fr) +{ + Town *from, *to; + + fr->distance = UINT_MAX; + + fr->from = from = GetRandomTown(); + if (from == NULL || from->population < 400) return; + + fr->to = to = GetRandomTown(); + if (from == to || to == NULL || to->population < 400 || to->pct_pass_transported > 42) + return; + + fr->distance = DistanceManhattan(from->xy, to->xy); +} + +static void FindSubsidyCargoRoute(FoundRoute *fr) +{ + Industry *i; + int trans, total; + CargoID cargo; + + fr->distance = UINT_MAX; + + fr->from = i = GetRandomIndustry(); + if (i == NULL) return; + + /* Randomize cargo type */ + if (HasBit(Random(), 0) && i->produced_cargo[1] != CT_INVALID) { + cargo = i->produced_cargo[1]; + trans = i->last_month_pct_transported[1]; + total = i->last_month_production[1]; + } else { + cargo = i->produced_cargo[0]; + trans = i->last_month_pct_transported[0]; + total = i->last_month_production[0]; + } + + /* Quit if no production in this industry + * or if the cargo type is passengers + * or if the pct transported is already large enough */ + if (total == 0 || trans > 42 || cargo == CT_INVALID) return; + + const CargoSpec *cs = GetCargo(cargo); + if (cs->town_effect == TE_PASSENGERS) return; + + fr->cargo = cargo; + + if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) { + /* The destination is a town */ + Town *t = GetRandomTown(); + + /* Only want big towns */ + if (t == NULL || t->population < 900) return; + + fr->distance = DistanceManhattan(i->xy, t->xy); + fr->to = t; + } else { + /* The destination is an industry */ + Industry *i2 = GetRandomIndustry(); + + /* The industry must accept the cargo */ + if (i2 == NULL || i == i2 || + (cargo != i2->accepts_cargo[0] && + cargo != i2->accepts_cargo[1] && + cargo != i2->accepts_cargo[2])) { + return; + } + fr->distance = DistanceManhattan(i->xy, i2->xy); + fr->to = i2; + } +} + +static bool CheckSubsidyDuplicate(Subsidy *s) +{ + const Subsidy *ss; + + for (ss = _subsidies; ss != endof(_subsidies); ss++) { + if (s != ss && + ss->from == s->from && + ss->to == s->to && + ss->cargo_type == s->cargo_type) { + s->cargo_type = CT_INVALID; + return true; + } + } + return false; +} + + +void SubsidyMonthlyLoop() +{ + Subsidy *s; + Pair pair; + Station *st; + uint n; + FoundRoute fr; + bool modified = false; + + for (s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type == CT_INVALID) continue; + + if (s->age == 12 - 1) { + pair = SetupSubsidyDecodeParam(s, 1); + AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NS_SUBSIDIES, pair.a, pair.b); + s->cargo_type = CT_INVALID; + modified = true; + AI::BroadcastNewEvent(new AIEventSubsidyOfferExpired(s - _subsidies)); + } else if (s->age == 2 * 12 - 1) { + st = Station::Get(s->to); + if (st->owner == _local_company) { + pair = SetupSubsidyDecodeParam(s, 1); + AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, pair.a, pair.b); + } + s->cargo_type = CT_INVALID; + modified = true; + AI::BroadcastNewEvent(new AIEventSubsidyExpired(s - _subsidies)); + } else { + s->age++; + } + } + + /* 25% chance to go on */ + if (Chance16(1, 4)) { + /* Find a free slot*/ + s = _subsidies; + while (s->cargo_type != CT_INVALID) { + if (++s == endof(_subsidies)) + goto no_add; + } + + n = 1000; + do { + FindSubsidyPassengerRoute(&fr); + if (fr.distance <= 70) { + s->cargo_type = CT_PASSENGERS; + s->from = ((Town*)fr.from)->index; + s->to = ((Town*)fr.to)->index; + goto add_subsidy; + } + FindSubsidyCargoRoute(&fr); + if (fr.distance <= 70) { + s->cargo_type = fr.cargo; + s->from = ((Industry*)fr.from)->index; + { + const CargoSpec *cs = GetCargo(fr.cargo); + s->to = (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index; + } + add_subsidy: + if (!CheckSubsidyDuplicate(s)) { + s->age = 0; + pair = SetupSubsidyDecodeParam(s, 0); + AddNewsItem(STR_NEWS_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, pair.a, pair.b); + AI::BroadcastNewEvent(new AIEventSubsidyOffer(s - _subsidies)); + modified = true; + break; + } + } + } while (n--); + } +no_add:; + if (modified) + InvalidateWindow(WC_SUBSIDIES_LIST, 0); +} + +bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type) +{ + Subsidy *s; + TileIndex xy; + Pair pair; + + /* check if there is an already existing subsidy that applies to us */ + for (s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type == cargo_type && + s->age >= 12 && + s->from == from->index && + s->to == to->index) { + return true; + } + } + + /* check if there's a new subsidy that applies.. */ + for (s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type == cargo_type && s->age < 12) { + /* Check distance from source */ + const CargoSpec *cs = GetCargo(cargo_type); + if (cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) { + xy = Town::Get(s->from)->xy; + } else { + xy = Industry::Get(s->from)->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->to)->xy; + break; + + default: + xy = Industry::Get(s->to)->xy; + break; + } + if (DistanceMax(xy, to->xy) > 9) continue; + + /* Found a subsidy, change the values to indicate that it's in use */ + s->age = 12; + s->from = from->index; + s->to = to->index; + + /* Add a news item */ + pair = SetupSubsidyDecodeParam(s, 0); + InjectDParam(1); + + SetDParam(0, _current_company); + AddNewsItem( + STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier, + NS_SUBSIDIES, + pair.a, pair.b + ); + AI::BroadcastNewEvent(new AIEventSubsidyAwarded(s - _subsidies)); + + InvalidateWindow(WC_SUBSIDIES_LIST, 0); + return true; + } + } + return false; +} diff --git a/src/subsidy_func.h b/src/subsidy_func.h new file mode 100644 index 0000000000..608dadfed5 --- /dev/null +++ b/src/subsidy_func.h @@ -0,0 +1,22 @@ +/* $Id$ */ + +/** @file subsidy_func.h Functions related to subsidies. */ + +#ifndef SUBSIDY_FUNC_H +#define SUBSIDY_FUNC_H + +#include "core/geometry_type.hpp" +#include "station_type.h" +#include "town_type.h" +#include "industry_type.h" +#include "company_type.h" +#include "subsidy_type.h" + +Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode); +void DeleteSubsidyWithTown(TownID index); +void DeleteSubsidyWithIndustry(IndustryID index); +void DeleteSubsidyWithStation(StationID index); +bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type); +void SubsidyMonthlyHandler(); + +#endif /* SUBSIDY_FUNC_H */ diff --git a/src/subsidy_gui.cpp b/src/subsidy_gui.cpp index 8d666fca1c..14ae1348ad 100644 --- a/src/subsidy_gui.cpp +++ b/src/subsidy_gui.cpp @@ -14,6 +14,7 @@ #include "viewport_func.h" #include "gfx_func.h" #include "gui.h" +#include "subsidy_func.h" #include "table/strings.h" diff --git a/src/subsidy_type.h b/src/subsidy_type.h new file mode 100644 index 0000000000..bec1a2cd48 --- /dev/null +++ b/src/subsidy_type.h @@ -0,0 +1,21 @@ +/* $Id$ */ + +/** @file subsidy_type.h Types related to subsidies. */ + +#ifndef SUBSIDY_TYPE_H +#define SUBSIDY_TYPE_H + +#include "cargo_type.h" +#include "company_type.h" + +struct Subsidy { + CargoID cargo_type; + byte age; + /* from and to can either be TownID, StationID or IndustryID */ + uint16 from; + uint16 to; +}; + +extern Subsidy _subsidies[MAX_COMPANIES]; + +#endif /* SUBSIDY_TYPE_H */ diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 825ef33f13..4dcd3dcd3c 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -40,6 +40,7 @@ #include "functions.h" #include "animated_tile_func.h" #include "date_func.h" +#include "subsidy_func.h" #include "core/smallmap_type.hpp" #include "core/pool_func.hpp"