32#include "table/strings.h"
48 default: NOT_REACHED();
61 default: NOT_REACHED();
76 std::string company_name =
GetString(STR_COMPANY_NAME, company);
95 switch (source.
type) {
98 default: NOT_REACHED();
124 if (s->src == source || s->dst == source) {
146 if (s->cargo_type == cargo && s->src == src && s->dst == dst) {
289 town_cargo_produced[cs->Index()] = 0;
292 uint8_t cargo_count = town_cargo_produced.
GetCount();
295 if (cargo_count == 0)
return false;
300 for (cargo_type = 0; cargo_type <
NUM_CARGO; cargo_type++) {
301 if (town_cargo_produced[cargo_type] > 0) {
302 if (cargo_number == 0)
break;
326 if (src_ind ==
nullptr)
return false;
333 int num_cargos = std::ranges::count_if(src_ind->
produced, [](
const auto &p) { return IsValidCargoType(p.cargo); });
334 if (num_cargos == 0)
return false;
337 auto it = std::begin(src_ind->
produced);
338 for (; it != std::end(src_ind->
produced); ++it) {
340 if (cargo_num == 0)
break;
342 assert(it != std::end(src_ind->
produced));
344 cargo_type = it->cargo;
345 trans = it->history[LAST_MONTH].PctTransported();
346 total = it->history[LAST_MONTH].production;
373 CargoTypes always_accepted{};
382 if (town_cargo_accepted[cargo_type] < 8)
return false;
384 dst.SetIndex(dst_town->index);
391 if (dst_ind ==
nullptr)
return false;
396 dst.SetIndex(dst_ind->index);
400 default: NOT_REACHED();
404 if (src == dst)
return false;
420 bool modified =
false;
423 if (--s->remaining == 0) {
424 if (!s->IsAwarded()) {
451 bool passenger_subsidy =
false;
452 bool town_subsidy =
false;
453 bool industry_subsidy =
false;
457 if (random_chance < 2) {
463 }
while (!passenger_subsidy && n--);
464 }
else if (random_chance == 2) {
470 }
while (!town_subsidy && n--);
471 }
else if (random_chance == 3) {
477 }
while (!industry_subsidy && n--);
480 modified |= passenger_subsidy || town_subsidy || industry_subsidy;
496 if (!src.IsValid())
return false;
504 default:
return false;
509 std::vector<const Town *> towns_near;
510 if (!st->
rect.IsEmpty()) {
514 if (s->cargo_type != cargo_type || s->src != src)
continue;
515 if (s->IsAwarded() && s->awarded != company)
continue;
520 const Town *t = Town::GetByTile(tile);
527 bool subsidised =
false;
532 if (s->cargo_type == cargo_type && s->src == src && (!s->IsAwarded() || s->awarded == company)) {
533 switch (s->dst.type) {
536 if (s->dst.ToIndustryID() == i.industry->index) {
539 if (!s->IsAwarded()) s->AwardTo(company);
544 for (
const Town *tp : towns_near) {
545 if (s->dst.ToTownID() == tp->index) {
548 if (!s->IsAwarded()) s->AwardTo(company);
Base functions for all AIs.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
@ TPE_PASSENGERS
Cargo behaves passenger-like for production.
static void BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company=CompanyID::Invalid())
Broadcast a new event to all active AIs.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Iterator to iterate over all tiles belonging to a bitmaptilearea.
Common return value for all commands.
Container for an encoded string, created by GetEncodedString.
static void NewEvent(class ScriptEvent *event)
Queue a new event for the game script.
An interval timer will fire every interval, and will continue to fire until it is deleted.
static constexpr int MONTHS_IN_YEAR
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Execute
execute the given command
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
Some simple functions to help with accessing containers.
bool include(Container &container, typename Container::const_reference &item)
Helper function to append an item to a container if it is not already contained.
Base functions for all Games.
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Functions related to news.
void AddNewsItem(EncodedString &&headline, NewsType type, NewsStyle style, NewsFlags flags, NewsReference ref1={}, NewsReference ref2={}, std::unique_ptr< NewsAllocatedData > &&data=nullptr, AdviceType advice_type=AdviceType::Invalid)
Add a new newsitem to be shown.
@ Subsidies
News about subsidies (announcements, expirations, acceptance).
@ Normal
Normal news item. (Newspaper with text only).
std::variant< std::monostate, TileIndex, VehicleID, StationID, IndustryID, TownID, EngineID > NewsReference
References to objects in news.
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Pseudo random number generator.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
bool Chance16(const uint32_t a, const uint32_t b, const std::source_location location=std::source_location::current())
Flips a coin with given probability.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
@ Industry
Source/destination is an industry.
@ Town
Source/destination is a town.
Base classes/functions for stations.
Definition of base types and functions in a cross-platform compatible way.
Functions related to low-level strings.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
StationRect rect
NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions.
Class for storing amounts of cargo.
uint GetCount() const
Get the amount of cargos that have an amount.
Specification of a cargo type.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
StringID name
Name of this type of cargo.
static std::array< std::vector< const CargoSpec * >, NUM_TPE > town_production_cargoes
List of cargo specs for each Town Product Effect.
Defines the internal data of a functional industry.
static Industry * GetRandom()
Return a random valid industry.
bool IsCargoAccepted() const
Test if this industry accepts any cargo.
ProducedCargoes produced
produced cargo slots
OrthogonalTileArea & Expand(int rad)
Expand a tile area by rad tiles in each direction, keeping within map bounds.
static Pool::IterateWrapper< Town > Iterate(size_t from=0)
static Industry * Get(auto index)
static bool CanAllocateItem(size_t n=1)
static bool IsValidID(auto index)
static T * Create(Targs &&... args)
A location from where cargo can come from (or go to).
static constexpr SourceID Invalid
Invalid/unknown index of source.
SourceID id
Index of industry/town/HQ, Source::Invalid if unknown/invalid.
StringID GetFormat() const
Get the format string for a subsidy Source.
NewsReference GetNewsReference() const
Get the NewsReference for a subsidy Source.
SourceType type
Type of source_id.
IndustryList industries_near
Cached list of industries near the station that can accept cargo,.
BitmapTileArea catchment_tiles
NOSAVE: Set of individual tiles covered by catchment area.
Struct about subsidies, offered and awarded.
bool IsAwarded() const
Tests whether this subsidy has been awarded to someone.
CargoType cargo_type
Cargo type involved in this subsidy, INVALID_CARGO for invalid subsidy.
CompanyID awarded
Subsidy is awarded to this company; CompanyID::Invalid() if it's not awarded to anyone.
void AwardTo(CompanyID company)
Marks subsidy as awarded, creates news and AI event.
Source dst
Destination of subsidised path.
Source src
Source of subsidised path.
uint16_t remaining
Remaining months when this subsidy is valid.
uint32_t population
Current population of people.
PartsOfSubsidy part_of_subsidy
Is this town a source/destination of a subsidy?
TileIndex xy
town center tile
static Town * GetRandom()
Return a random valid town.
TownCache cache
Container for all cacheable data.
static bool CheckSubsidyDuplicate(CargoType cargo, Source src, Source dst)
Check whether a specific subsidy already exists.
CommandCost CmdCreateSubsidy(DoCommandFlags flags, CargoType cargo_type, Source src, Source dst)
Create a new subsidy.
static bool CheckSubsidyDistance(Source src, Source dst)
Checks if the source and destination of a subsidy are inside the distance limit.
static void SetPartOfSubsidyFlag(Source source, PartOfSubsidy flag)
Sets a flag indicating that given town/industry is part of subsidised route.
static const IntervalTimer< TimerGameEconomy > _economy_subsidies_monthly({TimerGameEconomy::Trigger::Month, TimerGameEconomy::Priority::Subsidy}, [](auto) { bool modified=false;for(Subsidy *s :Subsidy::Iterate()) { if(--s->remaining==0) { if(!s->IsAwarded()) { const CargoSpec *cs=CargoSpec::Get(s->cargo_type);EncodedString headline=GetEncodedString(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, cs->name, s->src.GetFormat(), s->src.id, s->dst.GetFormat(), s->dst.id);AddNewsItem(std::move(headline), NewsType::Subsidies, NewsStyle::Normal, {}, s->src.GetNewsReference(), s->dst.GetNewsReference());AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index));Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index));} else { if(s->awarded==_local_company) { const CargoSpec *cs=CargoSpec::Get(s->cargo_type);EncodedString headline=GetEncodedString(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, cs->name, s->src.GetFormat(), s->src.id, s->dst.GetFormat(), s->dst.id);AddNewsItem(std::move(headline), NewsType::Subsidies, NewsStyle::Normal, {}, s->src.GetNewsReference(), s->dst.GetNewsReference());} AI::BroadcastNewEvent(new ScriptEventSubsidyExpired(s->index));Game::NewEvent(new ScriptEventSubsidyExpired(s->index));} delete s;modified=true;} } if(modified) { RebuildSubsidisedSourceAndDestinationCache();} else if(_settings_game.difficulty.subsidy_duration==0) { return;} bool passenger_subsidy=false;bool town_subsidy=false;bool industry_subsidy=false;int random_chance=RandomRange(16);if(random_chance< 2) { int n=1000;do { passenger_subsidy=FindSubsidyPassengerRoute();} while(!passenger_subsidy &&n--);} else if(random_chance==2) { int n=1000;do { town_subsidy=FindSubsidyTownCargoRoute();} while(!town_subsidy &&n--);} else if(random_chance==3) { int n=1000;do { industry_subsidy=FindSubsidyIndustryCargoRoute();} while(!industry_subsidy &&n--);} modified|=passenger_subsidy||town_subsidy||industry_subsidy;if(modified) InvalidateWindowData(WC_SUBSIDIES_LIST, 0);})
Perform the economy monthly update of open subsidies, and try to create a new one.
SubsidyPool _subsidy_pool("Subsidy")
Pool for the subsidies.
bool FindSubsidyIndustryCargoRoute()
Tries to create a cargo subsidy with an industry as source.
bool FindSubsidyPassengerRoute()
Tries to create a passenger subsidy between two towns.
void DeleteSubsidyWith(Source source)
Delete the subsidies associated with a given cargo source type and id.
bool FindSubsidyTownCargoRoute()
Tries to create a cargo subsidy with a town as source.
bool FindSubsidyCargoDestination(CargoType cargo_type, Source src)
Tries to find a suitable destination for the given source and cargo.
void RebuildSubsidisedSourceAndDestinationCache()
Perform a full rebuild of the subsidies cache.
bool CheckSubsidised(CargoType cargo_type, CompanyID company, Source src, const Station *st)
Tests whether given delivery is subsidised and possibly awards the subsidy to delivering company.
void CreateSubsidy(CargoType cargo_type, Source src, Source dst)
Creates a subsidy with the given parameters.
static const uint SUBSIDY_MAX_DISTANCE
Max. length of subsidised route (DistanceManhattan).
static const uint SUBSIDY_CARGO_MIN_POPULATION
Min. population of destination town for cargo route.
static const uint SUBSIDY_TOWN_CARGO_RADIUS
Extent of a tile area around town center when scanning for town cargo acceptance and production (6 ~=...
static const uint SUBSIDY_PAX_MIN_POPULATION
Min. population of towns for subsidised pax route.
static const uint SUBSIDY_MAX_PCT_TRANSPORTED
Subsidy will be created only for towns/industries with less % transported.
static const uint SUBSIDY_OFFER_MONTHS
Constants related to subsidies.
Command definitions related to subsidies.
Functions related to subsidies.
PartOfSubsidy
What part of a subsidy is something?
@ Destination
town/industry is destination of subsidised path
@ Source
town/industry is source of subsidised path
Generic 'commands' that can be performed on all tiles.
void AddProducedCargo(TileIndex tile, CargoArray &produced)
Obtain the produced cargo of a tile.
void AddAcceptedCargo(TileIndex tile, CargoArray &acceptance, CargoTypes &always_accepted)
Obtain cargo acceptance of a tile.
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
@ House
A house by a town.
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Definition of Interval and OneShot timers.
Definition of the game-economy-timer.
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Window functions not directly related to making/drawing windows.
@ WC_SUBSIDIES_LIST
Subsidies list; Window numbers: