32#include "table/strings.h"
45 assert(!this->IsAwarded());
47 this->awarded = company;
51 std::string company_name =
GetString(STR_COMPANY_NAME);
60 reftype.first, this->src, reftype.second, this->dst
87 SetDParam(parameter_offset + 1, STR_INDUSTRY_NAME);
91 SetDParam(parameter_offset + 1, STR_TOWN_NAME);
93 default: NOT_REACHED();
100 SetDParam(parameter_offset + 4, STR_INDUSTRY_NAME);
104 SetDParam(parameter_offset + 4, STR_TOWN_NAME);
106 default: NOT_REACHED();
115 return std::pair<NewsReferenceType, NewsReferenceType>(reftype1, reftype2);
129 default: NOT_REACHED();
156 if ((s->src_type == type && s->src == index) || (s->dst_type == type && s->dst == index)) {
180 if (s->cargo_type == cargo &&
181 s->src_type == src_type && s->src == src &&
182 s->dst_type == dst_type && s->dst == dst) {
333 AddProducedCargo(tile, town_cargo_produced);
339 town_cargo_produced[cs->Index()] = 0;
342 uint8_t cargo_count = town_cargo_produced.GetCount();
345 if (cargo_count == 0)
return false;
351 if (town_cargo_produced[cid] > 0) {
352 if (cargo_number == 0)
break;
383 if (src_ind ==
nullptr)
return false;
390 int num_cargos = std::ranges::count_if(src_ind->
produced, [](
const auto &p) { return IsValidCargoID(p.cargo); });
391 if (num_cargos == 0)
return false;
394 auto it = std::begin(src_ind->
produced);
395 for (; it != std::end(src_ind->
produced); ++it) {
397 if (cargo_num == 0)
break;
399 assert(it != std::end(src_ind->
produced));
402 trans = it->history[LAST_MONTH].PctTransported();
403 total = it->history[LAST_MONTH].production;
442 AddAcceptedCargo(tile, town_cargo_accepted,
nullptr);
447 if (town_cargo_accepted[cid] < 8)
return false;
449 dst = dst_town->
index;
456 if (dst_ind ==
nullptr)
return false;
461 dst = dst_ind->
index;
465 default: NOT_REACHED();
469 if (src_type == dst_type && src == dst)
return false;
485 bool modified =
false;
488 if (--s->remaining == 0) {
489 if (!s->IsAwarded()) {
521 bool passenger_subsidy =
false;
522 bool town_subsidy =
false;
523 bool industry_subsidy =
false;
533 }
while (!passenger_subsidy && n--);
534 }
else if (random_chance == 2) {
540 }
while (!town_subsidy && n--);
541 }
else if (random_chance == 3) {
547 }
while (!industry_subsidy && n--);
550 modified |= passenger_subsidy || town_subsidy || industry_subsidy;
575 default:
return false;
580 std::vector<const Town *> towns_near;
581 if (!st->
rect.IsEmpty()) {
585 if (s->cargo_type != cargo_type || s->src_type != src_type || s->src != src)
continue;
586 if (s->IsAwarded() && s->awarded != company)
continue;
591 const Town *t = Town::GetByTile(tile);
598 bool subsidised =
false;
603 if (s->cargo_type == cargo_type && s->src_type == src_type && s->src == src && (!s->IsAwarded() || s->awarded == company)) {
604 switch (s->dst_type) {
607 if (s->dst == i.industry->index) {
608 assert(i.industry->part_of_subsidy &
POS_DST);
610 if (!s->IsAwarded()) s->AwardTo(company);
615 for (
const Town *tp : towns_near) {
616 if (s->dst == tp->index) {
617 assert(tp->cache.part_of_subsidy &
POS_DST);
619 if (!s->IsAwarded()) s->AwardTo(company);
Base functions for all AIs.
uint8_t CargoID
Cargo slots to indicate a cargo type within a game.
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
uint16_t SourceID
Contains either industry ID, town ID or company ID (or INVALID_SOURCE)
static const SourceID INVALID_SOURCE
Invalid/unknown index of source.
static const CargoID NUM_CARGO
Maximum number of cargo types in a game.
SourceType
Types of cargo source and destination.
@ Industry
Source/destination is an industry.
@ Town
Source/destination is a town.
@ TPE_PASSENGERS
Cargo behaves passenger-like for production.
static void BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company=MAX_COMPANIES)
Broadcast a new event to all active AIs.
Iterator to iterate over all tiles belonging to a bitmaptilearea.
Common return value for all commands.
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
An interval timer will fire every interval, and will continue to fire until it is deleted.
static constexpr int MONTHS_IN_YEAR
months per year
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
DoCommandFlag
List of flags for a command.
@ DC_EXEC
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.
Owner
Enum for all companies/owners.
@ INVALID_COMPANY
An invalid company.
@ 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.
@ DT_MANUAL
Manual distribution. No link graph calculations are run.
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Functions related to news.
void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1=NR_NONE, uint32_t ref1=UINT32_MAX, NewsReferenceType reftype2=NR_NONE, uint32_t ref2=UINT32_MAX, std::unique_ptr< NewsAllocatedData > &&data=nullptr)
Add a new newsitem to be shown.
@ NT_SUBSIDIES
News about subsidies (announcements, expirations, acceptance)
NewsReferenceType
References to objects in news.
@ NR_TOWN
Reference town. Scroll to town when clicking on the news.
@ NR_INDUSTRY
Reference industry. Scroll to industry when clicking on the news. Delete news when industry is delete...
@ NR_NONE
Empty reference.
@ NF_NORMAL
Normal news item. (Newspaper with text only)
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.
Base classes/functions for stations.
Definition of base types and functions in a cross-platform compatible way.
Functions related to low-level strings.
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Functions related to OTTD's strings.
StationRect rect
NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions.
Class for storing amounts of cargo.
Specification of a cargo type.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
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.
uint16_t subsidy_duration
duration of subsidies
uint8_t subsidy_multiplier
payment multiplier for subsidized deliveries
DifficultySettings difficulty
settings related to the difficulty
LinkGraphSettings linkgraph
settings for link graph calculations
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
DistributionType distribution_mail
distribution type for mail
DistributionType distribution_default
distribution type for all other goods
DistributionType distribution_pax
distribution type for passengers
DistributionType distribution_armoured
distribution type for armoured cargo class
Represents the covered area of e.g.
OrthogonalTileArea & Expand(int rad)
Expand a tile area by rad tiles in each direction, keeping within map bounds.
Tindex index
Index of this pool item.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Titem * Get(size_t index)
Returns Titem with given index.
Base class for all pools.
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.
SourceType dst_type
Destination of subsidised path (SourceType::Industry or SourceType::Town)
SourceType src_type
Source of subsidised path (SourceType::Industry or SourceType::Town)
CompanyID awarded
Subsidy is awarded to this company; INVALID_COMPANY if it's not awarded to anyone.
CargoID cargo_type
Cargo type involved in this subsidy, INVALID_CARGO for invalid subsidy.
uint16_t remaining
Remaining months when this subsidy is valid.
SourceID src
Index of source. Either TownID or IndustryID.
SourceID dst
Index of destination. Either TownID or IndustryID.
uint32_t population
Current population of people.
PartOfSubsidy 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 IntervalTimer< TimerGameEconomy > _economy_subsidies_monthly({TimerGameEconomy::MONTH, TimerGameEconomy::Priority::SUBSIDY}, [](auto) { bool modified=false;for(Subsidy *s :Subsidy::Iterate()) { if(--s->remaining==0) { if(!s->IsAwarded()) { std::pair< NewsReferenceType, NewsReferenceType > reftype=SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn);AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst);AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index));Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index));} else { if(s->awarded==_local_company) { std::pair< NewsReferenceType, NewsReferenceType > reftype=SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::NewsWithdrawn);AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NT_SUBSIDIES, NF_NORMAL, reftype.first, s->src, reftype.second, s->dst);} 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;} else if(_settings_game.linkgraph.distribution_pax !=DT_MANUAL &&_settings_game.linkgraph.distribution_mail !=DT_MANUAL &&_settings_game.linkgraph.distribution_armoured !=DT_MANUAL &&_settings_game.linkgraph.distribution_default !=DT_MANUAL) { return;} bool passenger_subsidy=false;bool town_subsidy=false;bool industry_subsidy=false;int random_chance=RandomRange(16);if(random_chance< 2 &&_settings_game.linkgraph.distribution_pax==DT_MANUAL) { 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.
static void SetPartOfSubsidyFlag(SourceType type, SourceID index, PartOfSubsidy flag)
Sets a flag indicating that given town/industry is part of subsidised route.
SubsidyPool _subsidy_pool("Subsidy")
Pool for the subsidies.
bool FindSubsidyIndustryCargoRoute()
Tries to create a cargo subsidy with an industry as source.
void CreateSubsidy(CargoID cid, SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
Creates a subsidy with the given parameters.
bool FindSubsidyPassengerRoute()
Tries to create a passenger subsidy between two towns.
bool FindSubsidyTownCargoRoute()
Tries to create a cargo subsidy with a town as source.
bool CheckSubsidised(CargoID cargo_type, CompanyID company, SourceType src_type, SourceID src, const Station *st)
Tests whether given delivery is subsidised and possibly awards the subsidy to delivering company.
std::pair< NewsReferenceType, NewsReferenceType > SetupSubsidyDecodeParam(const Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset)
Setup the string parameters for printing the subsidy at the screen, and compute the news reference fo...
void DeleteSubsidyWith(SourceType type, SourceID index)
Delete the subsidies associated with a given cargo source type and id.
void RebuildSubsidisedSourceAndDestinationCache()
Perform a full rebuild of the subsidies cache.
static bool CheckSubsidyDuplicate(CargoID cargo, SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
Check whether a specific subsidy already exists.
CommandCost CmdCreateSubsidy(DoCommandFlag flags, CargoID cid, SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
Create a new subsidy.
bool FindSubsidyCargoDestination(CargoID cid, SourceType src_type, SourceID src)
Tries to find a suitable destination for the given source and cargo.
static bool CheckSubsidyDistance(SourceType src_type, SourceID src, SourceType dst_type, SourceID dst)
Checks if the source and destination of a subsidy are inside the distance limit.
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 ~=...
SubsidyDecodeParamType
Types of subsidy news messages, which determine how the date is printed and whether to use singular o...
@ NewsAwarded
News item for an awarded subsidy.
@ NewsWithdrawn
News item for a subsidy offer withdrawn, or expired subsidy.
@ NewsOffered
News item for an offered subsidy.
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?
@ POS_SRC
bit 0 set -> town/industry is source of subsidised path
@ POS_DST
bit 1 set -> town/industry is destination of subsidised path
Generic 'commands' that can be performed on all tiles.
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
@ MP_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: