|
@@ -64,6 +64,8 @@
|
|
|
|
|
|
#include "safeguards.h"
|
|
|
|
|
|
#include "company_func.h"
|
|
|
|
|
|
/**
|
|
|
* Static instance of FlowStat::SharesMap.
|
|
|
* Note: This instance is created on task start.
|
|
@@ -238,23 +240,9 @@ static bool FindNearIndustryName(TileInd
|
|
|
return !sni->indtypes[indtype];
|
|
|
}
|
|
|
|
|
|
static StringID GenerateStationName(Station *st, TileIndex tile, StationNaming name_class)
|
|
|
/** Fetch the available station names. Patchpack moves this code from GenerateStationName. Should be easy to see what was moved if you do a diff :) */
|
|
|
static void FetchAvailableStationNames(uint32& free_names, bool* indtypes, Station* st, const Town* t)
|
|
|
{
|
|
|
static const uint32 _gen_station_name_bits[] = {
|
|
|
0, // STATIONNAMING_RAIL
|
|
|
0, // STATIONNAMING_ROAD
|
|
|
1U << M(STR_SV_STNAME_AIRPORT), // STATIONNAMING_AIRPORT
|
|
|
1U << M(STR_SV_STNAME_OILFIELD), // STATIONNAMING_OILRIG
|
|
|
1U << M(STR_SV_STNAME_DOCKS), // STATIONNAMING_DOCK
|
|
|
1U << M(STR_SV_STNAME_HELIPORT), // STATIONNAMING_HELIPORT
|
|
|
};
|
|
|
|
|
|
const Town *t = st->town;
|
|
|
uint32 free_names = UINT32_MAX;
|
|
|
|
|
|
bool indtypes[NUM_INDUSTRYTYPES];
|
|
|
memset(indtypes, 0, sizeof(indtypes));
|
|
|
|
|
|
for (const Station *s : Station::Iterate()) {
|
|
|
if (s != st && s->town == t) {
|
|
|
if (s->indtype != IT_INVALID) {
|
|
@@ -278,6 +266,56 @@ static StringID GenerateStationName(Stat
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** Callback proc for CircularTileSearch */
|
|
|
static bool FindNearPatchpackIndustryName(TileIndex tile, void *user_data)
|
|
|
{
|
|
|
/* Is this an industry tile? If not, skip it */
|
|
|
if (!IsTileType(tile, MP_INDUSTRY)) return false;
|
|
|
|
|
|
uint32 free_names = UINT32_MAX;
|
|
|
bool indtypes[NUM_INDUSTRYTYPES];
|
|
|
memset(indtypes, 0, sizeof(indtypes));
|
|
|
FetchAvailableStationNames(free_names, indtypes, (Station*)user_data, Industry::GetByTile(tile)->town);
|
|
|
|
|
|
IndustryType indtype = GetIndustryType(tile);
|
|
|
|
|
|
return !indtypes[indtype];
|
|
|
}
|
|
|
|
|
|
/** Generates station names */
|
|
|
static StringID GenerateStationName(Station *st, TileIndex tile, StationNaming name_class)
|
|
|
{
|
|
|
if (_settings_game.construction.name_stations_based_on_industries == 2)
|
|
|
{
|
|
|
/** I love having this as an in-game patch setting. DEM SETTINGS */
|
|
|
TileIndex indtile = tile;
|
|
|
if (CircularTileSearch(&indtile, 7, FindNearPatchpackIndustryName, (void*)st)) {
|
|
|
IndustryType indtype = GetIndustryType(indtile);
|
|
|
const IndustrySpec *indsp = GetIndustrySpec(indtype);
|
|
|
st->indtype = indtype;
|
|
|
st->town = Industry::GetByTile(indtile)->town;
|
|
|
return STR_SV_STNAME_FALLBACK;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static const uint32 _gen_station_name_bits[] = {
|
|
|
0, // STATIONNAMING_RAIL
|
|
|
0, // STATIONNAMING_ROAD
|
|
|
1U << M(STR_SV_STNAME_AIRPORT), // STATIONNAMING_AIRPORT
|
|
|
1U << M(STR_SV_STNAME_OILFIELD), // STATIONNAMING_OILRIG
|
|
|
1U << M(STR_SV_STNAME_DOCKS), // STATIONNAMING_DOCK
|
|
|
1U << M(STR_SV_STNAME_HELIPORT), // STATIONNAMING_HELIPORT
|
|
|
};
|
|
|
|
|
|
const Town *t = st->town;
|
|
|
|
|
|
/* Fetch a list of available station names so we know which ones have already been used and are unavailable (including industry newGRF names) */
|
|
|
uint32 free_names = UINT32_MAX;
|
|
|
bool indtypes[NUM_INDUSTRYTYPES];
|
|
|
memset(indtypes, 0, sizeof(indtypes));
|
|
|
FetchAvailableStationNames(free_names, indtypes, st, t);
|
|
|
|
|
|
TileIndex indtile = tile;
|
|
|
StationNameInformation sni = { free_names, indtypes };
|
|
@@ -286,7 +324,7 @@ static StringID GenerateStationName(Stat
|
|
|
IndustryType indtype = GetIndustryType(indtile);
|
|
|
const IndustrySpec *indsp = GetIndustrySpec(indtype);
|
|
|
/* STR_NULL means it only disables oil rig/mines */
|
|
|
if (indsp->station_name != STR_NULL) {
|
|
|
if (indsp->station_name != STR_NULL && (_settings_game.construction.name_stations_based_on_industries == 1)) {
|
|
|
st->indtype = indtype;
|
|
|
return STR_SV_STNAME_FALLBACK;
|
|
|
}
|
|
@@ -843,7 +881,7 @@ CommandCost CheckBuildableTile(TileIndex
|
|
|
*/
|
|
|
static CommandCost CheckFlatLandAirport(AirportTileTableIterator tile_iter, DoCommandFlag flags)
|
|
|
{
|
|
|
CommandCost cost(EXPENSES_CONSTRUCTION);
|
|
|
CommandCost cost(EXPENSES_T_AIRCRAFT_CON);
|
|
|
int allowed_z = -1;
|
|
|
|
|
|
for (; tile_iter != INVALID_TILE; ++tile_iter) {
|
|
@@ -875,7 +913,7 @@ static CommandCost CheckFlatLandAirport(
|
|
|
*/
|
|
|
static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag flags, Axis axis, StationID *station, RailType rt, std::vector<Train *> &affected_vehicles, StationClassID spec_class, byte spec_index, byte plat_len, byte numtracks)
|
|
|
{
|
|
|
CommandCost cost(EXPENSES_CONSTRUCTION);
|
|
|
CommandCost cost(EXPENSES_T_TRAIN_CON);
|
|
|
int allowed_z = -1;
|
|
|
uint invalid_dirs = 5 << axis;
|
|
|
|
|
@@ -961,7 +999,7 @@ static CommandCost CheckFlatLandRailStat
|
|
|
*/
|
|
|
static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadType rt)
|
|
|
{
|
|
|
CommandCost cost(EXPENSES_CONSTRUCTION);
|
|
|
CommandCost cost(EXPENSES_T_ROAD_CON);
|
|
|
int allowed_z = -1;
|
|
|
|
|
|
for (TileIndex cur_tile : tile_area) {
|
|
@@ -1552,7 +1590,7 @@ CommandCost RemoveFromRailBaseStation(Ti
|
|
|
{
|
|
|
/* Count of the number of tiles removed */
|
|
|
int quantity = 0;
|
|
|
CommandCost total_cost(EXPENSES_CONSTRUCTION);
|
|
|
CommandCost total_cost(EXPENSES_T_TRAIN_CON);
|
|
|
/* Accumulator for the errors seen during clearing. If no errors happen,
|
|
|
* and the quantity is 0 there is no station. Otherwise it will be one
|
|
|
* of the other error that got accumulated. */
|
|
@@ -1721,7 +1759,7 @@ CommandCost RemoveRailStation(T *st, DoC
|
|
|
|
|
|
assert(ta.w != 0 && ta.h != 0);
|
|
|
|
|
|
CommandCost cost(EXPENSES_CONSTRUCTION);
|
|
|
CommandCost cost(EXPENSES_T_TRAIN_CON);
|
|
|
/* clear all areas of the station */
|
|
|
for (TileIndex tile : ta) {
|
|
|
/* only remove tiles that are actually train station tiles */
|
|
@@ -1853,7 +1891,7 @@ CommandCost CmdBuildRoadStop(DoCommandFl
|
|
|
bool is_truck_stop = stop_type != ROADSTOP_BUS;
|
|
|
|
|
|
/* Total road stop cost. */
|
|
|
CommandCost cost(EXPENSES_CONSTRUCTION, roadstop_area.w * roadstop_area.h * _price[is_truck_stop ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS]);
|
|
|
CommandCost cost(EXPENSES_T_ROAD_CON, roadstop_area.w * roadstop_area.h * _price[is_truck_stop ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS]);
|
|
|
StationID est = INVALID_STATION;
|
|
|
ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << axis : 1 << ddir, is_drive_through, is_truck_stop, axis, &est, rt);
|
|
|
if (ret.Failed()) return ret;
|
|
@@ -2045,7 +2083,7 @@ static CommandCost RemoveRoadStop(TileIn
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price[is_truck ? PR_CLEAR_STATION_TRUCK : PR_CLEAR_STATION_BUS]);
|
|
|
return CommandCost(EXPENSES_T_ROAD_CON, _price[is_truck ? PR_CLEAR_STATION_TRUCK : PR_CLEAR_STATION_BUS]);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2070,7 +2108,7 @@ CommandCost CmdRemoveRoadStop(DoCommandF
|
|
|
|
|
|
TileArea roadstop_area(tile, width, height);
|
|
|
|
|
|
CommandCost cost(EXPENSES_CONSTRUCTION);
|
|
|
CommandCost cost(EXPENSES_T_ROAD_CON);
|
|
|
CommandCost last_error(STR_ERROR_THERE_IS_NO_STATION);
|
|
|
bool had_success = false;
|
|
|
|
|
@@ -2350,7 +2388,7 @@ static CommandCost RemoveAirport(TileInd
|
|
|
|
|
|
tile = st->airport.tile;
|
|
|
|
|
|
CommandCost cost(EXPENSES_CONSTRUCTION);
|
|
|
CommandCost cost(EXPENSES_T_AIRCRAFT_CON);
|
|
|
|
|
|
for (const Aircraft *a : Aircraft::Iterate()) {
|
|
|
if (!a->IsNormalAircraft()) continue;
|
|
@@ -2496,7 +2534,7 @@ CommandCost CmdBuildDock(DoCommandFlag f
|
|
|
|
|
|
if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
|
|
|
|
|
CommandCost cost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_STATION_DOCK]);
|
|
|
CommandCost cost(EXPENSES_T_SHIP_CON, _price[PR_BUILD_STATION_DOCK]);
|
|
|
ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
|
|
|
if (ret.Failed()) return ret;
|
|
|
cost.AddCost(ret);
|
|
@@ -2696,7 +2734,7 @@ static CommandCost RemoveDock(TileIndex
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_STATION_DOCK]);
|
|
|
return CommandCost(EXPENSES_T_SHIP_CON, _price[PR_CLEAR_STATION_DOCK]);
|
|
|
}
|
|
|
|
|
|
#include "table/station_land.h"
|
|
@@ -2994,7 +3032,6 @@ draw_default_foundation:
|
|
|
}
|
|
|
|
|
|
if (HasStationRail(ti->tile) && HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
|
|
|
|
|
|
if (IsRoadStop(ti->tile)) {
|
|
|
RoadType road_rt = GetRoadTypeRoad(ti->tile);
|
|
|
RoadType tram_rt = GetRoadTypeTram(ti->tile);
|
|
@@ -3565,6 +3602,64 @@ static void UpdateStationRating(Station
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// station dilapidation
|
|
|
{
|
|
|
if (_settings_game.economy.dilapidation_max_amount > 0) {
|
|
|
bool dilapidation_calc = false;
|
|
|
uint16 dilapidation_pop = 0;
|
|
|
uint pop_count = st->goods[CT_PASSENGERS].cargo.AvailableCount();
|
|
|
if (Company::IsValidID(st->owner)) {
|
|
|
if ((st->facilities & FACIL_TRAIN) != 0) {
|
|
|
dilapidation_calc = true;
|
|
|
if (_settings_game.economy.dilapidation_pop_rail > dilapidation_pop) {
|
|
|
dilapidation_pop = _settings_game.economy.dilapidation_pop_rail;
|
|
|
}
|
|
|
}
|
|
|
if (((st->facilities & FACIL_BUS_STOP) != 0) || ((st->facilities & FACIL_TRUCK_STOP) != 0)) {
|
|
|
dilapidation_calc = true;
|
|
|
if (_settings_game.economy.dilapidation_pop_road > dilapidation_pop) {
|
|
|
dilapidation_pop = _settings_game.economy.dilapidation_pop_road;
|
|
|
}
|
|
|
}
|
|
|
if ((st->facilities & FACIL_DOCK) != 0) {
|
|
|
dilapidation_calc = true;
|
|
|
if (_settings_game.economy.dilapidation_pop_water > dilapidation_pop) {
|
|
|
dilapidation_pop = _settings_game.economy.dilapidation_pop_water;
|
|
|
}
|
|
|
}
|
|
|
if ((st->facilities & FACIL_AIRPORT) != 0) {
|
|
|
dilapidation_calc = true;
|
|
|
if (_settings_game.economy.dilapidation_pop_air > dilapidation_pop) {
|
|
|
dilapidation_pop = _settings_game.economy.dilapidation_pop_air;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (dilapidation_calc && pop_count > (uint)dilapidation_pop) {
|
|
|
// increase the dilapidation, preventing overflow
|
|
|
uint16 top_boundary = 65535 - _settings_game.economy.dilapidation_increase;
|
|
|
if (st->dilapidation >= top_boundary) {
|
|
|
st->dilapidation = 65535;
|
|
|
}
|
|
|
else {
|
|
|
st->dilapidation += _settings_game.economy.dilapidation_increase;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// decrease the dilapidation, preventing underflow
|
|
|
if (st->dilapidation <= _settings_game.economy.dilapidation_decrease) {
|
|
|
st->dilapidation = 0;
|
|
|
}
|
|
|
else {
|
|
|
st->dilapidation -= _settings_game.economy.dilapidation_decrease;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (st->dilapidation > _settings_game.economy.dilapidation_max_amount) {
|
|
|
st->dilapidation = _settings_game.economy.dilapidation_max_amount;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
StationID index = st->index;
|
|
|
if (waiting_changed) {
|
|
|
SetWindowDirty(WC_STATION_VIEW, index); // update whole window
|
|
@@ -3803,6 +3898,40 @@ void OnTick_Station()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** Charges player for dilapidation at station */
|
|
|
void ChargePlayerForDilapidation(Station *st)
|
|
|
{
|
|
|
if (st->dilapidation > 0 && Company::IsValidID(st->owner)) {
|
|
|
uint32 dilapidation_fine = 0;
|
|
|
if ((st->facilities & FACIL_TRAIN) != 0) {
|
|
|
if (_settings_game.economy.dilapidation_fine_rail > dilapidation_fine) {
|
|
|
dilapidation_fine = _settings_game.economy.dilapidation_fine_rail;
|
|
|
}
|
|
|
}
|
|
|
if (((st->facilities & FACIL_BUS_STOP) != 0) || ((st->facilities & FACIL_TRUCK_STOP) != 0)) {
|
|
|
if (_settings_game.economy.dilapidation_fine_road > dilapidation_fine) {
|
|
|
dilapidation_fine = _settings_game.economy.dilapidation_fine_road;
|
|
|
}
|
|
|
}
|
|
|
if ((st->facilities & FACIL_DOCK) != 0) {
|
|
|
if (_settings_game.economy.dilapidation_fine_water > dilapidation_fine) {
|
|
|
dilapidation_fine = _settings_game.economy.dilapidation_fine_water;
|
|
|
}
|
|
|
}
|
|
|
if ((st->facilities & FACIL_AIRPORT) != 0) {
|
|
|
if (_settings_game.economy.dilapidation_fine_air > dilapidation_fine) {
|
|
|
dilapidation_fine = _settings_game.economy.dilapidation_fine_air;
|
|
|
}
|
|
|
}
|
|
|
Money actual_fine = dilapidation_fine;
|
|
|
actual_fine *= st->dilapidation;
|
|
|
actual_fine *= (_economy.inflation_prices >> 16);
|
|
|
if (actual_fine > 0) {
|
|
|
SubtractMoneyFromCompanyFract(st->owner, CommandCost(EXPENSES_T_DILAPIDATION, actual_fine << 8));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** Monthly loop for stations. */
|
|
|
void StationMonthlyLoop()
|
|
|
{
|
|
@@ -3812,6 +3941,7 @@ void StationMonthlyLoop()
|
|
|
SB(ge->status, GoodsEntry::GES_LAST_MONTH, 1, GB(ge->status, GoodsEntry::GES_CURRENT_MONTH, 1));
|
|
|
ClrBit(ge->status, GoodsEntry::GES_CURRENT_MONTH);
|
|
|
}
|
|
|
ChargePlayerForDilapidation(st);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -4302,11 +4432,11 @@ static CommandCost TerraformTile_Station
|
|
|
DiagDirection direction = AxisToDiagDir(GetRailStationAxis(tile));
|
|
|
if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
|
|
|
if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
|
|
|
return CommandCost(EXPENSES_T_TRAIN_CON, _price[PR_BUILD_FOUNDATION]);
|
|
|
}
|
|
|
|
|
|
case STATION_AIRPORT:
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
|
|
|
return CommandCost(EXPENSES_T_AIRCRAFT_CON, _price[PR_BUILD_FOUNDATION]);
|
|
|
|
|
|
case STATION_TRUCK:
|
|
|
case STATION_BUS: {
|
|
@@ -4315,7 +4445,7 @@ static CommandCost TerraformTile_Station
|
|
|
if (IsDriveThroughStopTile(tile)) {
|
|
|
if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
|
|
|
}
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
|
|
|
return CommandCost(EXPENSES_T_ROAD_CON, _price[PR_BUILD_FOUNDATION]);
|
|
|
}
|
|
|
|
|
|
default: break;
|