@@ -21,6 +21,7 @@
#include "industry_type.h"
#include "company_type.h"
#include "station_type.h"
#include "station_func.h"
void ResetPriceBaseMultipliers();
void SetPriceBaseMultiplier(Price price, int factor);
@@ -35,7 +36,7 @@ int UpdateCompanyRatingAndValue(Company
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, SourceType source_type, SourceID source_id);
uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations);
void PrepareUnload(Vehicle *front_v);
void LoadUnloadStation(Station *st);
@@ -507,6 +507,8 @@ static void TransportIndustryGoods(TileI
const IndustrySpec *indspec = GetIndustrySpec(i->type);
bool moved_cargo = false;
StationFinder stations(i->xy, i->width, i->height);
for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
uint cw = min(i->produced_cargo_waiting[j], 255);
if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) {
@@ -517,7 +519,7 @@ static void TransportIndustryGoods(TileI
i->this_month_production[j] += cw;
uint am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[j], cw, ST_INDUSTRY, i->index);
uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
i->this_month_transported[j] += am;
moved_cargo |= (am != 0);
@@ -3009,7 +3009,20 @@ void FindStationsAroundTiles(TileIndex t
}
uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount, SourceType source_type, SourceID source_id)
/**
* Run a tile loop to find stations around a tile, on demand. Cache the result for further requests
* @return pointer to a StationList containing all stations found
*/
const StationList *StationFinder::GetStations()
{
if (this->tile != INVALID_TILE) {
FindStationsAroundTiles(this->tile, this->x_extent, this->y_extent, &this->stations);
this->tile = INVALID_TILE;
return &this->stations;
uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
/* Return if nothing to do. Also the rounding below fails for 0. */
if (amount == 0) return 0;
@@ -3019,9 +3032,7 @@ uint MoveGoodsToStation(TileIndex tile,
uint best_rating1 = 0; // rating of st1
uint best_rating2 = 0; // rating of st2
StationList all_stations;
FindStationsAroundTiles(tile, w, h, &all_stations);
for (Station **st_iter = all_stations.Begin(); st_iter != all_stations.End(); ++st_iter) {
for (Station * const *st_iter = all_stations->Begin(); st_iter != all_stations->End(); ++st_iter) {
Station *st = *st_iter;
/* Is the station reserved exclusively for somebody else? */
@@ -19,11 +19,9 @@
#include "tile_type.h"
#include "cargo_type.h"
#include "vehicle_type.h"
#include "core/smallvec_type.hpp"
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius);
typedef SmallVector<Station*, 1> StationList;
void FindStationsAroundTiles(TileIndex tile, int w_prod, int h_prod, StationList *stations);
void ShowStationViewWindow(StationID station);
@@ -13,6 +13,7 @@
#define STATION_TYPE_H
#include "core/enum_type.hpp"
typedef uint16 StationID;
@@ -115,4 +116,27 @@ struct TileArea {
uint8 h; ///< The height of the area
};
/** List of stations */
typedef SmallVector<Station *, 2> StationList;
* Structure contains cached list of stations nearby. The list
* is created upon first call to GetStations()
class StationFinder {
StationList stations; ///< List of stations nearby
TileIndex tile; ///< Northern tile of producer, INVALID_TILE when # stations is valid
int x_extent; ///< Width of producer
int y_extent; ///< Height of producer
public:
* Constructs StationFinder
* @param t northern tile
* @param dx width of producer
* @param dy height of producer
StationFinder(TileIndex t, int dx, int dy) : tile(t), x_extent(dx), y_extent(dy) {}
const StationList *GetStations();
#endif /* STATION_TYPE_H */
@@ -465,6 +465,8 @@ static void TileLoop_Town(TileIndex tile
Town *t = Town::GetByTile(tile);
uint32 r = Random();
StationFinder stations(tile, 1, 1);
if (HasBit(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) {
for (uint i = 0; i < 256; i++) {
uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, r, house_id, t, tile);
@@ -477,7 +479,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, ST_TOWN, t->index);
uint moved = MoveGoodsToStation(cargo, amt, ST_TOWN, t->index, stations.GetStations());
const CargoSpec *cs = CargoSpec::Get(cargo);
switch (cs->town_effect) {
@@ -501,7 +503,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, ST_TOWN, t->index);
t->new_act_pass += MoveGoodsToStation(CT_PASSENGERS, amt, ST_TOWN, t->index, stations.GetStations());
if (GB(r, 8, 8) < hs->mail_generation) {
@@ -509,7 +511,7 @@ static void TileLoop_Town(TileIndex tile
t->new_max_mail += amt;
t->new_act_mail += MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt, ST_TOWN, t->index);
t->new_act_mail += MoveGoodsToStation(CT_MAIL, amt, ST_TOWN, t->index, stations.GetStations());
@@ -344,12 +344,14 @@ static void TileLoop_Unmovable(TileIndex
uint level = GetCompanyHQSize(tile) + 1;
assert(level < 6);
StationFinder stations(tile, 2, 2);
uint r = Random();
/* Top town buildings generate 250, so the top HQ type makes 256. */
if (GB(r, 0, 8) < (256 / 4 / (6 - level))) {
uint amt = GB(r, 0, 8) / 8 / 4 + 1;
MoveGoodsToStation(tile, 2, 2, CT_PASSENGERS, amt, ST_HEADQUARTERS, GetTileOwner(tile));
MoveGoodsToStation(CT_PASSENGERS, amt, ST_HEADQUARTERS, GetTileOwner(tile), stations.GetStations());
/* Top town building generates 90, HQ can make up to 196. The
@@ -358,7 +360,7 @@ static void TileLoop_Unmovable(TileIndex
if (GB(r, 8, 8) < (196 / 4 / (6 - level))) {
uint amt = GB(r, 8, 8) / 8 / 4 + 1;
MoveGoodsToStation(tile, 2, 2, CT_MAIL, amt, ST_HEADQUARTERS, GetTileOwner(tile));
MoveGoodsToStation(CT_MAIL, amt, ST_HEADQUARTERS, GetTileOwner(tile), stations.GetStations());
Status change: