diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -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 &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::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;