Changeset - r23420:9c4e5ff5cf11
[Not reviewed]
master
0 14 0
PeterN - 5 years ago 2019-03-08 18:30:44
peter@fuzzle.org
Feature: Industries with neutral stations (e.g. Oil Rig) only supply/accept cargo to/from their neutral station. (#7234)

This change is a controlled by a game setting, located under Environment ->
Industries which allows toggling the behaviour. It defaults to enabled.

"Company stations can serve industries with attached neutral stations"

When enabled, industries with attached neutral station (such as Oil Rigs) may
also be served by company-owned stations built nearby. This is the traditional
behaviour.

When disabled, these industries may only be served by their neutral station.
Any nearby company-owned stations won't be able to serve them, nor will the
neutral station serve anything else other than the industry.
14 files changed with 81 insertions and 4 deletions:
0 comments (0 inline, 0 general)
src/economy.cpp
Show inline comments
 
@@ -1039,24 +1039,29 @@ static uint DeliverGoodsToIndustry(const
 
	 * This fails in three cases:
 
	 *  1) The station accepts the cargo because there are enough houses around it accepting the cargo.
 
	 *  2) The industries in the catchment area temporarily reject the cargo, and the daily station loop has not yet updated station acceptance.
 
	 *  3) The results of callbacks CBID_INDUSTRY_REFUSE_CARGO and CBID_INDTILE_CARGO_ACCEPTANCE are inconsistent. (documented behaviour)
 
	 */
 

	
 
	uint accepted = 0;
 

	
 
	for (uint i = 0; i < st->industries_near.Length() && num_pieces != 0; i++) {
 
		Industry *ind = st->industries_near[i];
 
		if (ind->index == source) continue;
 

	
 
		if (!_settings_game.station.serve_neutral_industries) {
 
			/* If this industry is only served by its neutral station, check it's us. */
 
			if (ind->neutral_station != NULL && ind->neutral_station != st) continue;
 
		}
 

	
 
		uint cargo_index;
 
		for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
 
			if (cargo_type == ind->accepts_cargo[cargo_index]) break;
 
		}
 
		/* Check if matching cargo has been found */
 
		if (cargo_index >= lengthof(ind->accepts_cargo)) continue;
 

	
 
		/* Check if industry temporarily refuses acceptance */
 
		if (IndustryTemporarilyRefusesCargo(ind, cargo_type)) continue;
 

	
 
		/* Insert the industry into _cargo_delivery_destinations, if not yet contained */
 
		_cargo_delivery_destinations.Include(ind);
src/industry.h
Show inline comments
 
@@ -9,47 +9,49 @@
 

	
 
/** @file industry.h Base of all industries. */
 

	
 
#ifndef INDUSTRY_H
 
#define INDUSTRY_H
 

	
 
#include <algorithm>
 
#include "newgrf_storage.h"
 
#include "subsidy_type.h"
 
#include "industry_map.h"
 
#include "industrytype.h"
 
#include "tilearea_type.h"
 
#include "station_base.h"
 

	
 

	
 
typedef Pool<Industry, IndustryID, 64, 64000> IndustryPool;
 
extern IndustryPool _industry_pool;
 

	
 
/**
 
 * Production level maximum, minimum and default values.
 
 * It is not a value been really used in order to change, but rather an indicator
 
 * of how the industry is behaving.
 
 */
 
enum ProductionLevels {
 
	PRODLEVEL_CLOSURE = 0x00,  ///< signal set to actually close the industry
 
	PRODLEVEL_MINIMUM = 0x04,  ///< below this level, the industry is set to be closing
 
	PRODLEVEL_DEFAULT = 0x10,  ///< default level set when the industry is created
 
	PRODLEVEL_MAXIMUM = 0x80,  ///< the industry is running at full speed
 
};
 

	
 
/**
 
 * Defines the internal data of a functional industry.
 
 */
 
struct Industry : IndustryPool::PoolItem<&_industry_pool> {
 
	TileArea location;                                     ///< Location of the industry
 
	Town *town;                                            ///< Nearest town
 
	Station *neutral_station;                              ///< Associated neutral station
 
	CargoID produced_cargo[INDUSTRY_NUM_OUTPUTS];          ///< 16 production cargo slots
 
	uint16 produced_cargo_waiting[INDUSTRY_NUM_OUTPUTS];   ///< amount of cargo produced per cargo
 
	uint16 incoming_cargo_waiting[INDUSTRY_NUM_INPUTS];    ///< incoming cargo waiting to be processed
 
	byte production_rate[INDUSTRY_NUM_OUTPUTS];            ///< production rate for each cargo
 
	byte prod_level;                                       ///< general production level
 
	CargoID accepts_cargo[INDUSTRY_NUM_INPUTS];            ///< 16 input cargo slots
 
	uint16 this_month_production[INDUSTRY_NUM_OUTPUTS];    ///< stats of this month's production per cargo
 
	uint16 this_month_transported[INDUSTRY_NUM_OUTPUTS];   ///< stats of this month's transport per cargo
 
	byte last_month_pct_transported[INDUSTRY_NUM_OUTPUTS]; ///< percentage transported per cargo in the last full month
 
	uint16 last_month_production[INDUSTRY_NUM_OUTPUTS];    ///< total units produced per cargo in the last full month
 
	uint16 last_month_transported[INDUSTRY_NUM_OUTPUTS];   ///< total units transported per cargo in the last full month
 
	uint16 counter;                                        ///< used for animation and/or production (if available cargo)
src/industry_cmd.cpp
Show inline comments
 
@@ -508,36 +508,42 @@ static CommandCost ClearTile_Industry(Ti
 
/**
 
 * Move produced cargo from industry to nearby stations.
 
 * @param tile Industry tile
 
 * @return true if any cargo was moved.
 
 */
 
static bool TransportIndustryGoods(TileIndex tile)
 
{
 
	Industry *i = Industry::GetByTile(tile);
 
	const IndustrySpec *indspec = GetIndustrySpec(i->type);
 
	bool moved_cargo = false;
 

	
 
	StationFinder stations(i->location);
 
	StationList neutral;
 

	
 
	if (i->neutral_station != NULL && !_settings_game.station.serve_neutral_industries) {
 
		/* Industry has a neutral station. Use it and ignore any other nearby stations. */
 
		*neutral.Append() = i->neutral_station;
 
	}
 

	
 
	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) {
 
			i->produced_cargo_waiting[j] -= cw;
 

	
 
			/* fluctuating economy? */
 
			if (EconomyIsInRecession()) cw = (cw + 1) / 2;
 

	
 
			i->this_month_production[j] += cw;
 

	
 
			uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
 
			uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, neutral.Length() != 0 ? &neutral : stations.GetStations());
 
			i->this_month_transported[j] += am;
 

	
 
			moved_cargo |= (am != 0);
 
		}
 
	}
 

	
 
	return moved_cargo;
 
}
 

	
 

	
 
static void AnimateTile_Industry(TileIndex tile)
 
{
src/lang/english.txt
Show inline comments
 
@@ -1175,24 +1175,26 @@ STR_CONFIG_SETTING_TRAIN_REVERSING_HELPT
 
STR_CONFIG_SETTING_DISASTERS                                    :Disasters: {STRING2}
 
STR_CONFIG_SETTING_DISASTERS_HELPTEXT                           :Toggle disasters which may occasionally block or destroy vehicles or infrastructure
 
STR_CONFIG_SETTING_CITY_APPROVAL                                :Town council's attitude towards area restructuring: {STRING2}
 
STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT                       :Choose how much noise and environmental damage by companies affect their town rating and further construction actions in their area
 

	
 
STR_CONFIG_SETTING_MAX_HEIGHTLEVEL                              :Maximum map height: {STRING2}
 
STR_CONFIG_SETTING_MAX_HEIGHTLEVEL_HELPTEXT                     :Set the maximum allowed height for mountains on the map
 
STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN                            :{WHITE}You can't set the maximum map height to this value. At least one mountain on the map is higher
 
STR_CONFIG_SETTING_AUTOSLOPE                                    :Allow landscaping under buildings, tracks, etc.: {STRING2}
 
STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT                           :Allow landscaping under buildings and tracks without removing them
 
STR_CONFIG_SETTING_CATCHMENT                                    :Allow more realistically sized catchment areas: {STRING2}
 
STR_CONFIG_SETTING_CATCHMENT_HELPTEXT                           :Have differently sized catchment areas for different types of stations and airports
 
STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES                     :Company stations can serve industries with attached neutral stations: {STRING2}
 
STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT            :When enabled, industries with attached stations (such as Oil Rigs) may also be served by company owned stations built nearby. When disabled, these industries may only be served by their attached stations. Any nearby company stations won't be able to serve them, nor will the attached station serve anything else other than the industry
 
STR_CONFIG_SETTING_EXTRADYNAMITE                                :Allow removal of more town-owned roads, bridges and tunnels: {STRING2}
 
STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT                       :Make it easier to remove town-owned infrastructure and buildings
 
STR_CONFIG_SETTING_TRAIN_LENGTH                                 :Maximum length of trains: {STRING2}
 
STR_CONFIG_SETTING_TRAIN_LENGTH_HELPTEXT                        :Set the maximum length of trains
 
STR_CONFIG_SETTING_TILE_LENGTH                                  :{COMMA} tile{P 0 "" s}
 
STR_CONFIG_SETTING_SMOKE_AMOUNT                                 :Amount of vehicle smoke/sparks: {STRING2}
 
STR_CONFIG_SETTING_SMOKE_AMOUNT_HELPTEXT                        :Set how much smoke or how many sparks are emitted by vehicles
 
STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL                     :Train acceleration model: {STRING2}
 
STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT            :Select the physics model for train acceleration. The "original" model penalises slopes equally for all vehicles. The "realistic" model penalises slopes and curves depending on various properties of the consist, like length and tractive effort
 
STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL              :Road vehicle acceleration model: {STRING2}
 
STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_HELPTEXT     :Select the physics model for road vehicle acceleration. The "original" model penalises slopes equally for all vehicles. The "realistic" model penalises slopes depending on various properties of the engine, for example 'tractive effort'
 
STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS                        :Slope steepness for trains: {STRING2}
src/saveload/afterload.cpp
Show inline comments
 
@@ -3076,24 +3076,43 @@ bool AfterLoadGame()
 
			} else {
 
				/* On lower half of lock */
 
				s->z_pos = GetTileZ(s->tile) * (int)TILE_HEIGHT;
 
			}
 
		}
 
	}
 

	
 
	if (IsSavegameVersionBefore(SLV_TOWN_CARGOGEN)) {
 
		/* Ensure the original cargo generation mode is used */
 
		_settings_game.economy.town_cargogen_mode = TCGM_ORIGINAL;
 
	}
 

	
 
	if (IsSavegameVersionBefore(SLV_SERVE_NEUTRAL_INDUSTRIES)) {
 
		/* Ensure the original neutral industry/station behaviour is used */
 
		_settings_game.station.serve_neutral_industries = true;
 

	
 
		/* Link oil rigs to their industry and back. */
 
		Station *st;
 
		FOR_ALL_STATIONS(st) {
 
			if (IsTileType(st->xy, MP_STATION) && IsOilRig(st->xy)) {
 
				/* Industry tile is always adjacent during construction by TileDiffXY(0, 1) */
 
				st->industry = Industry::GetByTile(st->xy + TileDiffXY(0, 1));
 
				st->industry->neutral_station = st;
 
			}
 
		}
 
	} else {
 
		/* Link neutral station back to industry, as this is not saved. */
 
		Industry *ind;
 
		FOR_ALL_INDUSTRIES(ind) if (ind->neutral_station != NULL) ind->neutral_station->industry = ind;
 
	}
 

	
 
	/* Station acceptance is some kind of cache */
 
	if (IsSavegameVersionBefore(SLV_127)) {
 
		Station *st;
 
		FOR_ALL_STATIONS(st) UpdateStationAcceptance(st, false);
 
	}
 

	
 
	/* Road stops is 'only' updating some caches */
 
	AfterLoadRoadStops();
 
	AfterLoadLabelMaps();
 
	AfterLoadCompanyStats();
 
	AfterLoadStoryBook();
 

	
src/saveload/industry_sl.cpp
Show inline comments
 
@@ -16,24 +16,25 @@
 
#include "newgrf_sl.h"
 

	
 
#include "../safeguards.h"
 

	
 
static OldPersistentStorage _old_ind_persistent_storage;
 

	
 
static const SaveLoad _industry_desc[] = {
 
	SLE_CONDVAR(Industry, location.tile,              SLE_FILE_U16 | SLE_VAR_U32,  SL_MIN_VERSION, SLV_6),
 
	SLE_CONDVAR(Industry, location.tile,              SLE_UINT32,                  SLV_6, SL_MAX_VERSION),
 
	    SLE_VAR(Industry, location.w,                 SLE_FILE_U8 | SLE_VAR_U16),
 
	    SLE_VAR(Industry, location.h,                 SLE_FILE_U8 | SLE_VAR_U16),
 
	    SLE_REF(Industry, town,                       REF_TOWN),
 
	SLE_CONDREF(Industry, neutral_station,            REF_STATION,                SLV_SERVE_NEUTRAL_INDUSTRIES, SL_MAX_VERSION),
 
	SLE_CONDNULL( 2, SL_MIN_VERSION, SLV_61),       ///< used to be industry's produced_cargo
 
	SLE_CONDARR(Industry, produced_cargo,             SLE_UINT8,   2,              SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, produced_cargo,             SLE_UINT8,  16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, incoming_cargo_waiting,     SLE_UINT16,  3,              SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, incoming_cargo_waiting,     SLE_UINT16, 16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, produced_cargo_waiting,     SLE_UINT16,  2,               SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, produced_cargo_waiting,     SLE_UINT16, 16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDARR(Industry, production_rate,            SLE_UINT8,   2,               SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, production_rate,            SLE_UINT8,  16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDNULL( 3, SL_MIN_VERSION, SLV_61),       ///< used to be industry's accepts_cargo
 
	SLE_CONDARR(Industry, accepts_cargo,              SLE_UINT8,   3,              SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, accepts_cargo,              SLE_UINT8,  16,             SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
src/saveload/saveload.h
Show inline comments
 
@@ -285,24 +285,26 @@ enum SaveLoadVersion : uint16 {
 
	SLV_EXTEND_RAILTYPES,                   ///< 200  PR#6805 Extend railtypes to 64, adding uint16 to map array.
 
	SLV_EXTEND_PERSISTENT_STORAGE,          ///< 201  PR#6885 Extend NewGRF persistant storages.
 
	SLV_EXTEND_INDUSTRY_CARGO_SLOTS,        ///< 202  PR#6867 Increase industry cargo slots to 16 in, 16 out
 
	SLV_SHIP_PATH_CACHE,                    ///< 203  PR#7072 Add path cache for ships
 
	SLV_SHIP_ROTATION,                      ///< 204  PR#7065 Add extra rotation stages for ships.
 

	
 
	SLV_GROUP_LIVERIES,                     ///< 205  PR#7108 Livery storage change and group liveries.
 
	SLV_SHIPS_STOP_IN_LOCKS,                ///< 206  PR#7150 Ship/lock movement changes.
 
	SLV_FIX_CARGO_MONITOR,                  ///< 207  PR#7175 v1.9  Cargo monitor data packing fix to support 64 cargotypes.
 
	SLV_TOWN_CARGOGEN,                      ///< 208  PR#6965 New algorithms for town building cargo generation.
 
	SLV_SHIP_CURVE_PENALTY,                 ///< 209  PR#7289 Configurable ship curve penalties.
 

	
 
	SLV_SERVE_NEUTRAL_INDUSTRIES,           ///< 210  PR#7234 Company stations can serve industries with attached neutral stations.
 

	
 
	SL_MAX_VERSION,                         ///< Highest possible saveload version
 
};
 

	
 
/** Save or load result codes. */
 
enum SaveOrLoadResult {
 
	SL_OK     = 0, ///< completed successfully
 
	SL_ERROR  = 1, ///< error that was caught before internal structures were modified
 
	SL_REINIT = 2, ///< error that was caught in the middle of updating game state, need to clear it. (can only happen during load)
 
};
 

	
 
/** Deals with the type of the savegame, independent of extension */
 
struct FileToSaveLoad {
src/settings_gui.cpp
Show inline comments
 
@@ -1734,24 +1734,25 @@ static SettingsContainer &GetSettingsTre
 
				towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
 
				towns->Add(new SettingEntry("economy.found_town"));
 
				towns->Add(new SettingEntry("economy.town_cargogen_mode"));
 
			}
 

	
 
			SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
 
			{
 
				industries->Add(new SettingEntry("construction.raw_industry_construction"));
 
				industries->Add(new SettingEntry("construction.industry_platform"));
 
				industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
 
				industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
 
				industries->Add(new SettingEntry("economy.smooth_economy"));
 
				industries->Add(new SettingEntry("station.serve_neutral_industries"));
 
			}
 

	
 
			SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
 
			{
 
				cdist->Add(new SettingEntry("linkgraph.recalc_time"));
 
				cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
 
				cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
 
				cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
 
				cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
 
				cdist->Add(new SettingEntry("linkgraph.distribution_default"));
 
				cdist->Add(new SettingEntry("linkgraph.accuracy"));
 
				cdist->Add(new SettingEntry("linkgraph.demand_distance"));
src/settings_type.h
Show inline comments
 
@@ -518,24 +518,25 @@ struct LinkGraphSettings {
 

	
 
	inline DistributionType GetDistributionType(CargoID cargo) const {
 
		if (IsCargoInClass(cargo, CC_PASSENGERS)) return this->distribution_pax;
 
		if (IsCargoInClass(cargo, CC_MAIL)) return this->distribution_mail;
 
		if (IsCargoInClass(cargo, CC_ARMOURED)) return this->distribution_armoured;
 
		return this->distribution_default;
 
	}
 
};
 

	
 
/** Settings related to stations. */
 
struct StationSettings {
 
	bool   modified_catchment;               ///< different-size catchment areas
 
	bool   serve_neutral_industries;         ///< company stations can serve industries with attached neutral stations
 
	bool   adjacent_stations;                ///< allow stations to be built directly adjacent to other stations
 
	bool   distant_join_stations;            ///< allow to join non-adjacent stations
 
	bool   never_expire_airports;            ///< never expire airports
 
	byte   station_spread;                   ///< amount a station may spread
 
};
 

	
 
/** Default settings for vehicles. */
 
struct VehicleDefaultSettings {
 
	bool   servint_ispercent;                ///< service intervals are in percents
 
	uint16 servint_trains;                   ///< service interval for trains
 
	uint16 servint_roadveh;                  ///< service interval for road vehicles
 
	uint16 servint_aircraft;                 ///< service interval for aircraft
src/station.cpp
Show inline comments
 
@@ -347,24 +347,30 @@ static bool FindIndustryToDeliver(TileIn
 
	return false;
 
}
 

	
 
/**
 
 * Recomputes Station::industries_near, list of industries possibly
 
 * accepting cargo in station's catchment radius
 
 */
 
void Station::RecomputeIndustriesNear()
 
{
 
	this->industries_near.Clear();
 
	if (this->rect.IsEmpty()) return;
 

	
 
	if (!_settings_game.station.serve_neutral_industries && this->industry != NULL) {
 
		/* Station is associated with an industry, so we only need to deliver to that industry. */
 
		*this->industries_near.Append() = this->industry;
 
		return;
 
	}
 

	
 
	RectAndIndustryVector riv = {
 
		this->GetCatchmentRect(),
 
		&this->industries_near
 
	};
 

	
 
	/* Compute maximum extent of acceptance rectangle wrt. station sign */
 
	TileIndex start_tile = this->xy;
 
	uint max_radius = max(
 
		max(DistanceManhattan(start_tile, TileXY(riv.rect.left,  riv.rect.top)), DistanceManhattan(start_tile, TileXY(riv.rect.left,  riv.rect.bottom))),
 
		max(DistanceManhattan(start_tile, TileXY(riv.rect.right, riv.rect.top)), DistanceManhattan(start_tile, TileXY(riv.rect.right, riv.rect.bottom)))
 
	);
 

	
src/station_base.h
Show inline comments
 
@@ -464,24 +464,25 @@ public:
 

	
 
	StationHadVehicleOfTypeByte had_vehicle_of_type;
 

	
 
	byte time_since_load;
 
	byte time_since_unload;
 

	
 
	byte last_vehicle_type;
 
	std::list<Vehicle *> loading_vehicles;
 
	GoodsEntry goods[NUM_CARGO];  ///< Goods at this station
 
	CargoTypes always_accepted;       ///< Bitmask of always accepted cargo types (by houses, HQs, industry tiles when industry doesn't accept cargo)
 

	
 
	IndustryVector industries_near; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry()
 
	Industry *industry;             ///< NOSAVE: Associated industry for neutral stations. (Rebuilt on load from Industry->st)
 

	
 
	Station(TileIndex tile = INVALID_TILE);
 
	~Station();
 

	
 
	void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
 

	
 
	void MarkTilesDirty(bool cargo_change) const;
 

	
 
	void UpdateVirtCoord();
 

	
 
	void AfterStationTileSetChange(bool adding, StationType type);
 

	
src/station_cmd.cpp
Show inline comments
 
@@ -497,65 +497,77 @@ CargoArray GetProductionAroundTiles(Tile
 
	 * everything except industries */
 
	TILE_AREA_LOOP(tile, ta) AddProducedCargo(tile, produced);
 

	
 
	/* Loop over the industries. They produce cargo for
 
	 * anything that is within 'rad' from their bounding
 
	 * box. As such if you have e.g. a oil well the tile
 
	 * area loop might not hit an industry tile while
 
	 * the industry would produce cargo for the station.
 
	 */
 
	const Industry *i;
 
	FOR_ALL_INDUSTRIES(i) {
 
		if (!ta.Intersects(i->location)) continue;
 
		/* Skip industry with neutral station */
 
		if (i->neutral_station != NULL && !_settings_game.station.serve_neutral_industries) continue;
 

	
 
		for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
 
			CargoID cargo = i->produced_cargo[j];
 
			if (cargo != CT_INVALID) produced[cargo]++;
 
		}
 
	}
 

	
 
	return produced;
 
}
 

	
 
/**
 
 * Get the acceptance of cargoes around the tile in 1/8.
 
 * @param tile Center of the search area
 
 * @param w X extent of area
 
 * @param h Y extent of area
 
 * @param rad Search radius in addition to given area
 
 * @param always_accepted bitmask of cargo accepted by houses and headquarters; can be NULL
 
 * @param ind Industry associated with neutral station (e.g. oil rig) or NULL
 
 */
 
CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted)
 
CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted, const Industry *ind)
 
{
 
	CargoArray acceptance;
 
	if (always_accepted != NULL) *always_accepted = 0;
 

	
 
	int x = TileX(tile);
 
	int y = TileY(tile);
 

	
 
	/* expand the region by rad tiles on each side
 
	 * while making sure that we remain inside the board. */
 
	int x2 = min(x + w + rad, MapSizeX());
 
	int y2 = min(y + h + rad, MapSizeY());
 
	int x1 = max(x - rad, 0);
 
	int y1 = max(y - rad, 0);
 

	
 
	assert(x1 < x2);
 
	assert(y1 < y2);
 
	assert(w > 0);
 
	assert(h > 0);
 

	
 
	for (int yc = y1; yc != y2; yc++) {
 
		for (int xc = x1; xc != x2; xc++) {
 
			TileIndex tile = TileXY(xc, yc);
 

	
 
			if (!_settings_game.station.serve_neutral_industries) {
 
				if (ind != NULL) {
 
					if (!IsTileType(tile, MP_INDUSTRY)) continue;
 
					if (Industry::GetByTile(tile) != ind) continue;
 
				} else {
 
					if (IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile)->neutral_station != NULL) continue;
 
				}
 
			}
 
			AddAcceptedCargo(tile, acceptance, always_accepted);
 
		}
 
	}
 

	
 
	return acceptance;
 
}
 

	
 
/**
 
 * Update the acceptance for a station.
 
 * @param st Station to update
 
 * @param show_msg controls whether to display a message that acceptance was changed.
 
 */
 
@@ -563,25 +575,26 @@ void UpdateStationAcceptance(Station *st
 
{
 
	/* old accepted goods types */
 
	CargoTypes old_acc = GetAcceptanceMask(st);
 

	
 
	/* And retrieve the acceptance. */
 
	CargoArray acceptance;
 
	if (!st->rect.IsEmpty()) {
 
		acceptance = GetAcceptanceAroundTiles(
 
			TileXY(st->rect.left, st->rect.top),
 
			st->rect.right  - st->rect.left + 1,
 
			st->rect.bottom - st->rect.top  + 1,
 
			st->GetCatchmentRadius(),
 
			&st->always_accepted
 
			&st->always_accepted,
 
			_settings_game.station.serve_neutral_industries ? NULL : st->industry
 
		);
 
	}
 

	
 
	/* Adjust in case our station only accepts fewer kinds of goods */
 
	for (CargoID i = 0; i < NUM_CARGO; i++) {
 
		uint amt = acceptance[i];
 

	
 
		/* Make sure the station can accept the goods type. */
 
		bool is_passengers = IsCargoInClass(i, CC_PASSENGERS);
 
		if ((!is_passengers && !(st->facilities & ~FACIL_BUS_STOP)) ||
 
				(is_passengers && !(st->facilities & ~FACIL_TRUCK_STOP))) {
 
			amt = 0;
 
@@ -3786,38 +3799,43 @@ void FindStationsAroundTiles(const TileA
 
{
 
	/* area to search = producer plus station catchment radius */
 
	uint max_rad = (_settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED);
 

	
 
	uint x = TileX(location.tile);
 
	uint y = TileY(location.tile);
 

	
 
	uint min_x = (x > max_rad) ? x - max_rad : 0;
 
	uint max_x = x + location.w + max_rad;
 
	uint min_y = (y > max_rad) ? y - max_rad : 0;
 
	uint max_y = y + location.h + max_rad;
 

	
 
	IndustryID ind = IsTileType(location.tile, MP_INDUSTRY) ? GetIndustryIndex(location.tile) : INVALID_INDUSTRY;
 

	
 
	if (min_x == 0 && _settings_game.construction.freeform_edges) min_x = 1;
 
	if (min_y == 0 && _settings_game.construction.freeform_edges) min_y = 1;
 
	if (max_x >= MapSizeX()) max_x = MapSizeX() - 1;
 
	if (max_y >= MapSizeY()) max_y = MapSizeY() - 1;
 

	
 
	for (uint cy = min_y; cy < max_y; cy++) {
 
		for (uint cx = min_x; cx < max_x; cx++) {
 
			TileIndex cur_tile = TileXY(cx, cy);
 
			if (!IsTileType(cur_tile, MP_STATION)) continue;
 

	
 
			Station *st = Station::GetByTile(cur_tile);
 
			/* st can be NULL in case of waypoints */
 
			if (st == NULL) continue;
 

	
 
			/* Check if neutral station is attached to us */
 
			if (!_settings_game.station.serve_neutral_industries && st->industry != NULL && st->industry->index != ind) continue;
 

	
 
			if (_settings_game.station.modified_catchment) {
 
				int rad = st->GetCatchmentRadius();
 
				int rad_x = cx - x;
 
				int rad_y = cy - y;
 

	
 
				if (rad_x < -rad || rad_x >= rad + location.w) continue;
 
				if (rad_y < -rad || rad_y >= rad + location.h) continue;
 
			}
 

	
 
			/* Insert the station in the set. This will fail if it has
 
			 * already been added.
 
			 */
 
@@ -3909,24 +3927,27 @@ void BuildOilRig(TileIndex tile)
 
{
 
	if (!Station::CanAllocateItem()) {
 
		DEBUG(misc, 0, "Can't allocate station for oilrig at 0x%X, reverting to oilrig only", tile);
 
		return;
 
	}
 

	
 
	Station *st = new Station(tile);
 
	st->town = ClosestTownFromTile(tile, UINT_MAX);
 

	
 
	st->string_id = GenerateStationName(st, tile, STATIONNAMING_OILRIG);
 

	
 
	assert(IsTileType(tile, MP_INDUSTRY));
 
	/* Mark industry as associated both ways */
 
	st->industry = Industry::GetByTile(tile);
 
	st->industry->neutral_station = st;
 
	DeleteAnimatedTile(tile);
 
	MakeOilrig(tile, st->index, GetWaterClass(tile));
 

	
 
	st->owner = OWNER_NONE;
 
	st->airport.type = AT_OILRIG;
 
	st->airport.Add(tile);
 
	st->dock_tile = tile;
 
	st->facilities = FACIL_AIRPORT | FACIL_DOCK;
 
	st->build_date = _date;
 

	
 
	st->rect.BeforeAddTile(tile, StationRect::ADD_FORCE);
 

	
src/station_func.h
Show inline comments
 
@@ -10,34 +10,35 @@
 
/** @file station_func.h Functions related to stations. */
 

	
 
#ifndef STATION_FUNC_H
 
#define STATION_FUNC_H
 

	
 
#include "sprite.h"
 
#include "rail_type.h"
 
#include "road_type.h"
 
#include "vehicle_type.h"
 
#include "economy_func.h"
 
#include "rail.h"
 
#include "linkgraph/linkgraph_type.h"
 
#include "industry_type.h"
 

	
 
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius);
 

	
 
void FindStationsAroundTiles(const TileArea &location, StationList *stations);
 

	
 
void ShowStationViewWindow(StationID station);
 
void UpdateAllStationVirtCoords();
 

	
 
CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad);
 
CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted = NULL);
 
CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted = NULL, const Industry *ind = NULL);
 

	
 
void UpdateStationAcceptance(Station *st, bool show_msg);
 

	
 
const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx);
 
void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image);
 

	
 
bool HasStationInUse(StationID station, bool include_company, CompanyID company);
 

	
 
void DeleteOilRig(TileIndex t);
 

	
 
/* Check if a rail station tile is traversable. */
 
bool IsStationTileBlocked(TileIndex tile);
src/table/settings.ini
Show inline comments
 
@@ -1212,24 +1212,33 @@ cat      = SC_EXPERT
 

	
 
[SDT_BOOL]
 
base     = GameSettings
 
var      = station.modified_catchment
 
def      = true
 
str      = STR_CONFIG_SETTING_CATCHMENT
 
strhelp  = STR_CONFIG_SETTING_CATCHMENT_HELPTEXT
 
proc     = StationCatchmentChanged
 
cat      = SC_EXPERT
 

	
 
[SDT_BOOL]
 
base     = GameSettings
 
var      = station.serve_neutral_industries
 
def      = true
 
from     = SLV_SERVE_NEUTRAL_INDUSTRIES
 
str      = STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES
 
strhelp  = STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT
 
proc     = StationCatchmentChanged
 

	
 
[SDT_BOOL]
 
base     = GameSettings
 
var      = order.gradual_loading
 
from     = SLV_40
 
guiflags = SGF_NO_NETWORK
 
def      = true
 
cat      = SC_EXPERT
 

	
 
[SDT_BOOL]
 
base     = GameSettings
 
var      = construction.road_stop_on_town_road
 
from     = SLV_47
 
def      = true
 
str      = STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD
0 comments (0 inline, 0 general)