summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichi_cc <michi_cc@openttd.org>2011-12-03 23:40:46 +0000
committermichi_cc <michi_cc@openttd.org>2011-12-03 23:40:46 +0000
commitd3b7b89493e025654d218fb77da095649b4f6ba2 (patch)
tree6667e4164c5c8bda4c1b7092376872b315c65610
parentf98312eb77e12cfa45de40a1b4e8359160b0d9ff (diff)
downloadopenttd-d3b7b89493e025654d218fb77da095649b4f6ba2.tar.xz
(svn r23415) -Feature: Infrastructure maintenance costs.
-rw-r--r--src/company_gui.cpp86
-rw-r--r--src/core/math_func.cpp30
-rw-r--r--src/core/math_func.hpp2
-rw-r--r--src/economy.cpp34
-rw-r--r--src/economy_type.h5
-rw-r--r--src/lang/english.txt3
-rw-r--r--src/newgrf.cpp9
-rw-r--r--src/newgrf_airport.h1
-rw-r--r--src/rail.h28
-rw-r--r--src/road_func.h14
-rw-r--r--src/saveload/saveload.cpp3
-rw-r--r--src/settings.cpp11
-rw-r--r--src/settings_gui.cpp1
-rw-r--r--src/settings_type.h1
-rw-r--r--src/station.cpp19
-rw-r--r--src/station_func.h13
-rw-r--r--src/table/airport_defaults.h34
-rw-r--r--src/table/pricebase.h5
-rw-r--r--src/table/railtypes.h12
-rw-r--r--src/table/settings.ini9
-rw-r--r--src/water.h12
21 files changed, 300 insertions, 32 deletions
diff --git a/src/company_gui.cpp b/src/company_gui.cpp
index f20014100..20ff13667 100644
--- a/src/company_gui.cpp
+++ b/src/company_gui.cpp
@@ -34,6 +34,9 @@
#include "rail.h"
#include "engine_base.h"
#include "window_func.h"
+#include "road_func.h"
+#include "water.h"
+#include "station_func.h"
#include "table/strings.h"
@@ -1624,6 +1627,8 @@ enum CompanyInfrastructureWindowWidgets {
CIW_WIDGET_WATER_COUNT,
CIW_WIDGET_STATION_DESC,
CIW_WIDGET_STATION_COUNT,
+ CIW_WIDGET_TOTAL_DESC,
+ CIW_WIDGET_TOTAL,
};
static const NWidgetPart _nested_company_infrastructure_widgets[] = {
@@ -1651,6 +1656,10 @@ static const NWidgetPart _nested_company_infrastructure_widgets[] = {
NWidget(WWT_EMPTY, COLOUR_GREY, CIW_WIDGET_STATION_DESC), SetMinimalTextLines(3, 0), SetFill(1, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, CIW_WIDGET_STATION_COUNT), SetMinimalTextLines(3, 0), SetFill(0, 1),
EndContainer(),
+ NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
+ NWidget(WWT_EMPTY, COLOUR_GREY, CIW_WIDGET_TOTAL_DESC), SetFill(1, 0),
+ NWidget(WWT_EMPTY, COLOUR_GREY, CIW_WIDGET_TOTAL), SetFill(0, 1),
+ EndContainer(),
EndContainer(),
EndContainer(),
};
@@ -1663,6 +1672,8 @@ struct CompanyInfrastructureWindow : Window
RailTypes railtypes; ///< Valid railtypes.
RoadTypes roadtypes; ///< Valid roadtypes.
+ uint total_width; ///< String width of the total cost line.
+
CompanyInfrastructureWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
{
this->UpdateRailRoadTypes();
@@ -1697,6 +1708,27 @@ struct CompanyInfrastructureWindow : Window
}
}
+ /** Get total infrastructure maintenance cost. */
+ Money GetTotalMaintenanceCost() const
+ {
+ const Company *c = Company::Get((CompanyID)this->window_number);
+ Money total;
+
+ for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
+ if (HasBit(this->railtypes, rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt]);
+ }
+ total += SignalMaintenanceCost(c->infrastructure.signal);
+
+ if (HasBit(this->roadtypes, ROADTYPE_ROAD)) total += RoadMaintenanceCost(ROADTYPE_ROAD, c->infrastructure.road[ROADTYPE_ROAD]);
+ if (HasBit(this->roadtypes, ROADTYPE_TRAM)) total += RoadMaintenanceCost(ROADTYPE_TRAM, c->infrastructure.road[ROADTYPE_TRAM]);
+
+ total += CanalMaintenanceCost(c->infrastructure.water);
+ total += StationMaintenanceCost(c->infrastructure.station);
+ total += AirportMaintenanceCost(c->index);
+
+ return total;
+ }
+
virtual void SetStringParameters(int widget) const
{
switch (widget) {
@@ -1749,22 +1781,42 @@ struct CompanyInfrastructureWindow : Window
case CIW_WIDGET_RAIL_COUNT:
case CIW_WIDGET_ROAD_COUNT:
case CIW_WIDGET_WATER_COUNT:
- case CIW_WIDGET_STATION_COUNT: {
+ case CIW_WIDGET_STATION_COUNT:
+ case CIW_WIDGET_TOTAL: {
/* Find the maximum count that is displayed. */
uint32 max_val = 100000; // Some random number to reserve enough space.
+ Money max_cost = 100000; // Some random number to reserve enough space.
for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
max_val = max(max_val, c->infrastructure.rail[rt]);
+ max_cost = max(max_cost, RailMaintenanceCost(rt, c->infrastructure.rail[rt]));
}
max_val = max(max_val, c->infrastructure.signal);
+ max_cost = max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
max_val = max(max_val, c->infrastructure.road[rt]);
+ max_cost = max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt]));
}
max_val = max(max_val, c->infrastructure.water);
+ max_cost = max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
max_val = max(max_val, c->infrastructure.station);
+ max_cost = max(max_cost, StationMaintenanceCost(c->infrastructure.station));
max_val = max(max_val, c->infrastructure.airport);
+ max_cost = max(max_cost, AirportMaintenanceCost(c->index));
SetDParam(0, max_val);
- size->width = max(size->width, GetStringBoundingBox(STR_WHITE_COMMA).width + 15); // Reserve some wiggle room.
+ SetDParam(1, max_cost * 12); // Convert to per year
+ size->width = max(size->width, GetStringBoundingBox(_settings_game.economy.infrastructure_maintenance ? STR_COMPANY_INFRASTRUCTURE_VIEW_COST : STR_WHITE_COMMA).width + 20); // Reserve some wiggle room.
+
+ if (_settings_game.economy.infrastructure_maintenance) {
+ SetDParam(0, this->GetTotalMaintenanceCost());
+ this->total_width = GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL).width + 20;
+ size->width = max(size->width, this->total_width);
+ }
+
+ /* Set height of the total line. */
+ if (widget == CIW_WIDGET_TOTAL) {
+ size->height = _settings_game.economy.infrastructure_maintenance ? max(size->height, EXP_LINESPACE + FONT_HEIGHT_NORMAL) : 0;
+ }
break;
}
}
@@ -1803,12 +1855,14 @@ struct CompanyInfrastructureWindow : Window
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
if (HasBit(this->railtypes, rt)) {
SetDParam(0, c->infrastructure.rail[rt]);
- DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA);
+ SetDParam(1, RailMaintenanceCost(rt, c->infrastructure.rail[rt]) * 12); // Convert to per year
+ DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, _settings_game.economy.infrastructure_maintenance ? STR_COMPANY_INFRASTRUCTURE_VIEW_COST : STR_WHITE_COMMA);
}
}
if (this->railtypes != RAILTYPES_NONE) {
SetDParam(0, c->infrastructure.signal);
- DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA);
+ SetDParam(1, SignalMaintenanceCost(c->infrastructure.signal) * 12); // Convert to per year
+ DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, _settings_game.economy.infrastructure_maintenance ? STR_COMPANY_INFRASTRUCTURE_VIEW_COST : STR_WHITE_COMMA);
}
break;
@@ -1828,11 +1882,13 @@ struct CompanyInfrastructureWindow : Window
case CIW_WIDGET_ROAD_COUNT:
if (HasBit(this->roadtypes, ROADTYPE_ROAD)) {
SetDParam(0, c->infrastructure.road[ROADTYPE_ROAD]);
- DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA);
+ SetDParam(1, RoadMaintenanceCost(ROADTYPE_ROAD, c->infrastructure.road[ROADTYPE_ROAD]) * 12); // Convert to per year
+ DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, _settings_game.economy.infrastructure_maintenance ? STR_COMPANY_INFRASTRUCTURE_VIEW_COST : STR_WHITE_COMMA);
}
if (HasBit(this->roadtypes, ROADTYPE_TRAM)) {
SetDParam(0, c->infrastructure.road[ROADTYPE_TRAM]);
- DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA);
+ SetDParam(1, RoadMaintenanceCost(ROADTYPE_TRAM, c->infrastructure.road[ROADTYPE_TRAM]) * 12); // Convert to per year
+ DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, _settings_game.economy.infrastructure_maintenance ? STR_COMPANY_INFRASTRUCTURE_VIEW_COST : STR_WHITE_COMMA);
}
break;
@@ -1843,7 +1899,17 @@ struct CompanyInfrastructureWindow : Window
case CIW_WIDGET_WATER_COUNT:
SetDParam(0, c->infrastructure.water);
- DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA);
+ SetDParam(1, CanalMaintenanceCost(c->infrastructure.water) * 12); // Convert to per year
+ DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, _settings_game.economy.infrastructure_maintenance ? STR_COMPANY_INFRASTRUCTURE_VIEW_COST : STR_WHITE_COMMA);
+ break;
+
+ case CIW_WIDGET_TOTAL:
+ if (_settings_game.economy.infrastructure_maintenance) {
+ GfxFillRect(r.left, y, r.left + this->total_width, y, PC_WHITE);
+ y += EXP_LINESPACE;
+ SetDParam(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
+ DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL);
+ }
break;
case CIW_WIDGET_STATION_DESC:
@@ -1854,9 +1920,11 @@ struct CompanyInfrastructureWindow : Window
case CIW_WIDGET_STATION_COUNT:
SetDParam(0, c->infrastructure.station);
- DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA);
+ SetDParam(1, StationMaintenanceCost(c->infrastructure.station) * 12); // Convert to per year
+ DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, _settings_game.economy.infrastructure_maintenance ? STR_COMPANY_INFRASTRUCTURE_VIEW_COST : STR_WHITE_COMMA);
SetDParam(0, c->infrastructure.airport);
- DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA);
+ SetDParam(1, AirportMaintenanceCost(c->index) * 12); // Convert to per year
+ DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, _settings_game.economy.infrastructure_maintenance ? STR_COMPANY_INFRASTRUCTURE_VIEW_COST : STR_WHITE_COMMA);
break;
}
}
diff --git a/src/core/math_func.cpp b/src/core/math_func.cpp
index 7f0630a97..2b8ca3309 100644
--- a/src/core/math_func.cpp
+++ b/src/core/math_func.cpp
@@ -46,3 +46,33 @@ int GreatestCommonDivisor(int a, int b)
return a;
}
+
+/**
+ * Compute the integer square root.
+ * @param num Radicand.
+ * @return Rounded integer square root.
+ * @note Algorithm taken from http://en.wikipedia.org/wiki/Methods_of_computing_square_roots
+ */
+uint32 IntSqrt(uint32 num)
+{
+ uint32 res = 0;
+ uint32 bit = 1UL << 30; // Second to top bit number.
+
+ /* 'bit' starts at the highest power of four <= the argument. */
+ while (bit > num) bit >>= 2;
+
+ while (bit != 0) {
+ if (num >= res + bit) {
+ num -= res + bit;
+ res = (res >> 1) + bit;
+ } else {
+ res >>= 1;
+ }
+ bit >>= 2;
+ }
+
+ /* Arithmetic rounding to nearest integer. */
+ if (num > res) res++;
+
+ return res;
+}
diff --git a/src/core/math_func.hpp b/src/core/math_func.hpp
index 19f2f53d6..92893ed31 100644
--- a/src/core/math_func.hpp
+++ b/src/core/math_func.hpp
@@ -346,4 +346,6 @@ static FORCEINLINE int RoundDivSU(int a, uint b)
}
}
+uint32 IntSqrt(uint32 num);
+
#endif /* MATH_FUNC_HPP */
diff --git a/src/economy.cpp b/src/economy.cpp
index ada4fc227..9fa2e11de 100644
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -46,6 +46,7 @@
#include "core/pool_func.hpp"
#include "newgrf.h"
#include "core/backup_type.hpp"
+#include "water.h"
#include "table/strings.h"
#include "table/pricebase.h"
@@ -584,17 +585,39 @@ static void CompaniesGenStatistics()
Station *st;
Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
- FOR_ALL_STATIONS(st) {
- cur_company.Change(st->owner);
- CommandCost cost(EXPENSES_PROPERTY, _price[PR_STATION_VALUE] >> 1);
- SubtractMoneyFromCompany(cost);
+ Company *c;
+
+ if (!_settings_game.economy.infrastructure_maintenance) {
+ FOR_ALL_STATIONS(st) {
+ cur_company.Change(st->owner);
+ CommandCost cost(EXPENSES_PROPERTY, _price[PR_STATION_VALUE] >> 1);
+ SubtractMoneyFromCompany(cost);
+ }
+ } else {
+ /* Improved monthly infrastructure costs. */
+ FOR_ALL_COMPANIES(c) {
+ cur_company.Change(c->index);
+
+ CommandCost cost(EXPENSES_PROPERTY);
+ for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
+ if (c->infrastructure.rail[rt] != 0) cost.AddCost(RailMaintenanceCost(rt, c->infrastructure.rail[rt]));
+ }
+ cost.AddCost(SignalMaintenanceCost(c->infrastructure.signal));
+ for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
+ if (c->infrastructure.road[rt] != 0) cost.AddCost(RoadMaintenanceCost(rt, c->infrastructure.road[rt]));
+ }
+ cost.AddCost(CanalMaintenanceCost(c->infrastructure.water));
+ cost.AddCost(StationMaintenanceCost(c->infrastructure.station));
+ cost.AddCost(AirportMaintenanceCost(c->index));
+
+ SubtractMoneyFromCompany(cost);
+ }
}
cur_company.Restore();
/* Only run the economic statics and update company stats every 3rd month (1st of quarter). */
if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month)) return;
- Company *c;
FOR_ALL_COMPANIES(c) {
memmove(&c->old_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0]));
c->old_economy[0] = c->cur_economy;
@@ -713,6 +736,7 @@ void RecomputePrices()
SetWindowClassesDirty(WC_BUILD_VEHICLE);
SetWindowClassesDirty(WC_REPLACE_VEHICLE);
SetWindowClassesDirty(WC_VEHICLE_DETAILS);
+ SetWindowClassesDirty(WC_COMPANY_INFRASTRUCTURE);
InvalidateWindowData(WC_PAYMENT_RATES, 0);
}
diff --git a/src/economy_type.h b/src/economy_type.h
index 644bb6a55..82a4e2cfa 100644
--- a/src/economy_type.h
+++ b/src/economy_type.h
@@ -132,6 +132,11 @@ enum Price {
PR_CLEAR_AQUEDUCT,
PR_BUILD_LOCK,
PR_CLEAR_LOCK,
+ PR_INFRASTRUCTURE_RAIL,
+ PR_INFRASTRUCTURE_ROAD,
+ PR_INFRASTRUCTURE_WATER,
+ PR_INFRASTRUCTURE_STATION,
+ PR_INFRASTRUCTURE_AIRPORT,
PR_END,
INVALID_PRICE = 0xFF
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 96d67d420..cc80abe3d 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1156,6 +1156,7 @@ STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD :{LTBLUE}Allow d
STR_CONFIG_SETTING_ADJACENT_STATIONS :{LTBLUE}Allow building adjacent stations: {ORANGE}{STRING}
STR_CONFIG_SETTING_DYNAMIC_ENGINES :{LTBLUE}Enable multiple NewGRF engine sets: {ORANGE}{STRING}
STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Changing this setting is not possible when there are vehicles
+STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE :{LTBLUE}Infrastructure maintenance: {ORANGE}{STRING1}
STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS :{LTBLUE}Airports never expire: {ORANGE}{STRING1}
@@ -2788,6 +2789,8 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS :{WHITE}Canals
STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT :{GOLD}Stations:
STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS :{WHITE}Station tiles
STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS :{WHITE}Airports
+STR_COMPANY_INFRASTRUCTURE_VIEW_COST :{WHITE}{1:CURRENCY_LONG}/yr ({0:COMMA})
+STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENCY_LONG}/yr
# Industry directory
STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Industries
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index 5a2175737..49e8cf3eb 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -3635,6 +3635,10 @@ static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, B
_string_to_grf_mapping[&as->name] = _cur.grffile->grfid;
break;
+ case 0x11: // Maintenance cost factor
+ as->maintenance_cost = buf->ReadWord();
+ break;
+
default:
ret = CIR_UNKNOWN;
break;
@@ -3941,6 +3945,10 @@ static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteR
_string_to_grf_mapping[&rti->strings.name] = _cur.grffile->grfid;
break;
+ case 0x1C: // Maintenance cost factor
+ rti->maintenance_multiplier = buf->ReadWord();
+ break;
+
default:
ret = CIR_UNKNOWN;
break;
@@ -3984,6 +3992,7 @@ static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, Byte
case 0x13: // Construction cost
case 0x14: // Speed limit
case 0x1B: // Name of railtype
+ case 0x1C: // Maintenance cost factor
buf->ReadWord();
break;
diff --git a/src/newgrf_airport.h b/src/newgrf_airport.h
index d0ec38c05..b00c3667c 100644
--- a/src/newgrf_airport.h
+++ b/src/newgrf_airport.h
@@ -76,6 +76,7 @@ struct AirportSpec {
TTDPAirportType ttd_airport_type; ///< ttdpatch airport type (Small/Large/Helipad/Oilrig)
AirportClassID cls_id; ///< the class to which this airport type belongs
SpriteID preview_sprite; ///< preview sprite for this airport
+ uint16 maintenance_cost; ///< maintenance cost mulltiplier
/* Newgrf data */
bool enabled; ///< entity still avaible (by default true).newgrf can disable it, though
struct GRFFileProps grf_prop; ///< properties related the the grf file
diff --git a/src/rail.h b/src/rail.h
index 54b5c27b6..43672d058 100644
--- a/src/rail.h
+++ b/src/rail.h
@@ -20,6 +20,7 @@
#include "slope_type.h"
#include "strings_type.h"
#include "date_type.h"
+#include "core/math_func.hpp"
/** Railtype flags. */
enum RailTypeFlags {
@@ -189,6 +190,11 @@ struct RailtypeInfo {
uint16 cost_multiplier;
/**
+ * Cost multiplier for maintenance of this rail type
+ */
+ uint16 maintenance_multiplier;
+
+ /**
* Acceleration type of this rail type
*/
uint8 acceleration_type;
@@ -363,6 +369,28 @@ static inline Money RailConvertCost(RailType from, RailType to)
return rebuildcost;
}
+/**
+ * Calculates the maintenance cost of a number of track bits.
+ * @param railtype The railtype to get the cost of.
+ * @param num Number of track bits.
+ * @return Total cost.
+ */
+static inline Money RailMaintenanceCost(RailType railtype, uint32 num)
+{
+ assert(railtype < RAILTYPE_END);
+ return (_price[PR_INFRASTRUCTURE_RAIL] * GetRailTypeInfo(railtype)->maintenance_multiplier * num * (1 + IntSqrt(num))) >> 11; // 4 bits fraction for the multiplier and 7 bits scaling.
+}
+
+/**
+ * Calculates the maintenance cost of a number of signals.
+ * @param num Number of signals.
+ * @return Total cost.
+ */
+static inline Money SignalMaintenanceCost(uint32 num)
+{
+ return (_price[PR_INFRASTRUCTURE_RAIL] * 15 * num * (1 + IntSqrt(num))) >> 8; // 1 bit fraction for the multiplier and 7 bits scaling.
+}
+
void DrawTrainDepotSprite(int x, int y, int image, RailType railtype);
int TicksToLeaveDepot(const Train *v);
diff --git a/src/road_func.h b/src/road_func.h
index 2f286730f..126ab5c82 100644
--- a/src/road_func.h
+++ b/src/road_func.h
@@ -17,6 +17,7 @@
#include "direction_type.h"
#include "company_type.h"
#include "tile_type.h"
+#include "economy_func.h"
/**
* Iterate through each set RoadType in a RoadTypes value.
@@ -148,6 +149,19 @@ static inline RoadBits AxisToRoadBits(Axis a)
return a == AXIS_X ? ROAD_X : ROAD_Y;
}
+
+/**
+ * Calculates the maintenance cost of a number of road bits.
+ * @param roadtype Road type to get the cost for.
+ * @param num Number of road bits.
+ * @return Total cost.
+ */
+static inline Money RoadMaintenanceCost(RoadType roadtype, uint32 num)
+{
+ assert(roadtype < ROADTYPE_END);
+ return (_price[PR_INFRASTRUCTURE_ROAD] * (roadtype == ROADTYPE_TRAM ? 3 : 2) * num * (1 + IntSqrt(num))) >> 9; // 2 bits fraction for the multiplier and 7 bits scaling.
+}
+
bool HasRoadTypesAvail(const CompanyID company, const RoadTypes rts);
bool ValParamRoadType(const RoadType rt);
RoadTypes GetCompanyRoadtypes(const CompanyID company);
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp
index 8de4773a3..c603f5843 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -230,8 +230,9 @@
* 163 22767
* 164 23290
* 165 23304
+ * 166 23415
*/
-extern const uint16 SAVEGAME_VERSION = 165; ///< Current savegame version of OpenTTD.
+extern const uint16 SAVEGAME_VERSION = 166; ///< Current savegame version of OpenTTD.
SavegameType _savegame_type; ///< type of savegame we are loading
diff --git a/src/settings.cpp b/src/settings.cpp
index 8a9d0548a..a72bf5874 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -946,6 +946,17 @@ static bool RedrawTownAuthority(int32 p1)
return true;
}
+/**
+ * Invalidate the company infrastructure details window after a infrastructure maintenance setting change.
+ * @param p1 Unused.
+ * @return Always true.
+ */
+static bool InvalidateCompanyInfrastructureWindow(int32 p1)
+{
+ InvalidateWindowClassesData(WC_COMPANY_INFRASTRUCTURE);
+ return true;
+}
+
/*
* A: competitors
* B: competitor start time. Deprecated since savegame version 110.
diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp
index c11e22093..4a4282ea7 100644
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -1492,6 +1492,7 @@ static SettingEntry _settings_economy[] = {
SettingEntry("economy.inflation"),
SettingEntry("economy.smooth_economy"),
SettingEntry("economy.feeder_payment_share"),
+ SettingEntry("economy.infrastructure_maintenance"),
};
/** Economy sub-page */
static SettingsPage _settings_economy_page = {_settings_economy, lengthof(_settings_economy)};
diff --git a/src/settings_type.h b/src/settings_type.h
index b1d622844..6562cb365 100644
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -416,6 +416,7 @@ struct EconomySettings {
bool station_noise_level; ///< build new airports when the town noise level is still within accepted limits
uint16 town_noise_population[3]; ///< population to base decision on noise evaluation (@see town_council_tolerance)
bool allow_town_level_crossings; ///< towns are allowed to build level crossings
+ bool infrastructure_maintenance; ///< enable monthly maintenance fee for owner infrastructure
};
/** Settings related to stations. */
diff --git a/src/station.cpp b/src/station.cpp
index a3df6fe74..5fc2bbdf5 100644
--- a/src/station.cpp
+++ b/src/station.cpp
@@ -523,3 +523,22 @@ StationRect& StationRect::operator = (const Rect &src)
this->bottom = src.bottom;
return *this;
}
+
+/**
+ * Calculates the maintenance cost of all airports of a company.
+ * @param owner Company.
+ * @return Total cost.
+ */
+Money AirportMaintenanceCost(Owner owner)
+{
+ Money total_cost = 0;
+
+ const Station *st;
+ FOR_ALL_STATIONS(st) {
+ if (st->owner == owner && (st->facilities & FACIL_AIRPORT)) {
+ total_cost += _price[PR_INFRASTRUCTURE_AIRPORT] * st->airport.GetSpec()->maintenance_cost;
+ }
+ }
+ /* 3 bits fraction for the maintenance cost factor. */
+ return total_cost >> 3;
+}
diff --git a/src/station_func.h b/src/station_func.h
index 0fe5b2f84..8f2901745 100644
--- a/src/station_func.h
+++ b/src/station_func.h
@@ -18,6 +18,7 @@
#include "road_type.h"
#include "cargo_type.h"
#include "company_type.h"
+#include "economy_func.h"
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius);
@@ -46,4 +47,16 @@ bool IsStationTileElectrifiable(TileIndex tile);
void UpdateAirportsNoise();
+/**
+ * Calculates the maintenance cost of a number of station tiles.
+ * @param num Number of station tiles.
+ * @return Total cost.
+ */
+static inline Money StationMaintenanceCost(uint32 num)
+{
+ return (_price[PR_INFRASTRUCTURE_STATION] * num * (1 + IntSqrt(num))) >> 7; // 7 bits scaling.
+}
+
+Money AirportMaintenanceCost(Owner owner);
+
#endif /* STATION_FUNC_H */
diff --git a/src/table/airport_defaults.h b/src/table/airport_defaults.h
index f4b4cd4be..01a55ce89 100644
--- a/src/table/airport_defaults.h
+++ b/src/table/airport_defaults.h
@@ -381,36 +381,36 @@ static Direction _default_airports_rotation[] = {
#undef MKEND
/** General AirportSpec definition. */
-#define AS_GENERIC(fsm, att, rot, att_len, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year, ttdpatch_type, class_id, name, preview, enabled) \
- {fsm, att, rot, att_len, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year, name, ttdpatch_type, class_id, preview, enabled, GRFFileProps(AT_INVALID)}
+#define AS_GENERIC(fsm, att, rot, att_len, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year, maint_cost, ttdpatch_type, class_id, name, preview, enabled) \
+ {fsm, att, rot, att_len, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year, name, ttdpatch_type, class_id, preview, maint_cost, enabled, GRFFileProps(AT_INVALID)}
/** AirportSpec definition for airports without any depot. */
-#define AS_ND(ap_name, size_x, size_y, min_year, max_year, catchment, noise, ttdpatch_type, class_id, name, preview) \
+#define AS_ND(ap_name, size_x, size_y, min_year, max_year, catchment, noise, maint_cost, ttdpatch_type, class_id, name, preview) \
AS_GENERIC(&_airportfta_##ap_name, _tile_table_##ap_name, _default_airports_rotation, lengthof(_tile_table_##ap_name), NULL, 0, \
- size_x, size_y, noise, catchment, min_year, max_year, ttdpatch_type, class_id, name, preview, true)
+ size_x, size_y, noise, catchment, min_year, max_year, maint_cost, ttdpatch_type, class_id, name, preview, true)
/** AirportSpec definition for airports with at least one depot. */
-#define AS(ap_name, size_x, size_y, min_year, max_year, catchment, noise, ttdpatch_type, class_id, name, preview) \
+#define AS(ap_name, size_x, size_y, min_year, max_year, catchment, noise, maint_cost, ttdpatch_type, class_id, name, preview) \
AS_GENERIC(&_airportfta_##ap_name, _tile_table_##ap_name, _default_airports_rotation, lengthof(_tile_table_##ap_name), _airport_depots_##ap_name, lengthof(_airport_depots_##ap_name), \
- size_x, size_y, noise, catchment, min_year, max_year, ttdpatch_type, class_id, name, preview, true)
+ size_x, size_y, noise, catchment, min_year, max_year, maint_cost, ttdpatch_type, class_id, name, preview, true)
/* The helidepot and helistation have ATP_TTDP_SMALL because they are at ground level */
extern const AirportSpec _origin_airport_specs[] = {
- AS(country, 4, 3, 0, 1959, 4, 3, ATP_TTDP_SMALL, APC_SMALL, STR_AIRPORT_SMALL, SPR_AIRPORT_PREVIEW_SMALL),
- AS(city, 6, 6, 1955, MAX_YEAR, 5, 5, ATP_TTDP_LARGE, APC_LARGE, STR_AIRPORT_CITY, SPR_AIRPORT_PREVIEW_LARGE),
- AS_ND(heliport, 1, 1, 1963, MAX_YEAR, 4, 1, ATP_TTDP_HELIPORT, APC_HELIPORT, STR_AIRPORT_HELIPORT, SPR_AIRPORT_PREVIEW_HELIPORT),
- AS(metropolitan, 6, 6, 1980, MAX_YEAR, 6, 8, ATP_TTDP_LARGE, APC_LARGE, STR_AIRPORT_METRO, SPR_AIRPORT_PREVIEW_METROPOLITAN),
- AS(international, 7, 7, 1990, MAX_YEAR, 8, 17, ATP_TTDP_LARGE, APC_HUB, STR_AIRPORT_INTERNATIONAL, SPR_AIRPORT_PREVIEW_INTERNATIONAL),
- AS(commuter, 5, 4, 1983, MAX_YEAR, 4, 4, ATP_TTDP_SMALL, APC_SMALL, STR_AIRPORT_COMMUTER, SPR_AIRPORT_PREVIEW_COMMUTER),
- AS(helidepot, 2, 2, 1976, MAX_YEAR, 4, 2, ATP_TTDP_SMALL, APC_HELIPORT, STR_AIRPORT_HELIDEPOT, SPR_AIRPORT_PREVIEW_HELIDEPOT),
- AS(intercontinental, 9, 11, 2002, MAX_YEAR, 10, 25, ATP_TTDP_LARGE, APC_HUB, STR_AIRPORT_INTERCONTINENTAL, SPR_AIRPORT_PREVIEW_INTERCONTINENTAL),
- AS(helistation, 4, 2, 1980, MAX_YEAR, 4, 3, ATP_TTDP_SMALL, APC_HELIPORT, STR_AIRPORT_HELISTATION, SPR_AIRPORT_PREVIEW_HELISTATION),
- AS_GENERIC(&_airportfta_oilrig, NULL, _default_airports_rotation, 0, NULL, 0, 1, 1, 0, 4, 0, 0, ATP_TTDP_OILRIG, APC_HELIPORT, STR_NULL, 0, false),
+ AS(country, 4, 3, 0, 1959, 4, 3, 7, ATP_TTDP_SMALL, APC_SMALL, STR_AIRPORT_SMALL, SPR_AIRPORT_PREVIEW_SMALL),
+ AS(city, 6, 6, 1955, MAX_YEAR, 5, 5, 24, ATP_TTDP_LARGE, APC_LARGE, STR_AIRPORT_CITY, SPR_AIRPORT_PREVIEW_LARGE),
+ AS_ND(heliport, 1, 1, 1963, MAX_YEAR, 4, 1, 4, ATP_TTDP_HELIPORT, APC_HELIPORT, STR_AIRPORT_HELIPORT, SPR_AIRPORT_PREVIEW_HELIPORT),
+ AS(metropolitan, 6, 6, 1980, MAX_YEAR, 6, 8, 28, ATP_TTDP_LARGE, APC_LARGE, STR_AIRPORT_METRO, SPR_AIRPORT_PREVIEW_METROPOLITAN),
+ AS(international, 7, 7, 1990, MAX_YEAR, 8, 17, 42, ATP_TTDP_LARGE, APC_HUB, STR_AIRPORT_INTERNATIONAL, SPR_AIRPORT_PREVIEW_INTERNATIONAL),
+ AS(commuter, 5, 4, 1983, MAX_YEAR, 4, 4, 20, ATP_TTDP_SMALL, APC_SMALL, STR_AIRPORT_COMMUTER, SPR_AIRPORT_PREVIEW_COMMUTER),
+ AS(helidepot, 2, 2, 1976, MAX_YEAR, 4, 2, 7, ATP_TTDP_SMALL, APC_HELIPORT, STR_AIRPORT_HELIDEPOT, SPR_AIRPORT_PREVIEW_HELIDEPOT),
+ AS(intercontinental, 9, 11, 2002, MAX_YEAR, 10, 25, 72, ATP_TTDP_LARGE, APC_HUB, STR_AIRPORT_INTERCONTINENTAL, SPR_AIRPORT_PREVIEW_INTERCONTINENTAL),
+ AS(helistation, 4, 2, 1980, MAX_YEAR, 4, 3, 14, ATP_TTDP_SMALL, APC_HELIPORT, STR_AIRPORT_HELISTATION, SPR_AIRPORT_PREVIEW_HELISTATION),
+ AS_GENERIC(&_airportfta_oilrig, NULL, _default_airports_rotation, 0, NULL, 0, 1, 1, 0, 4, 0, 0, 0, ATP_TTDP_OILRIG, APC_HELIPORT, STR_NULL, 0, false),
};
assert_compile(NEW_AIRPORT_OFFSET == lengthof(_origin_airport_specs));
-AirportSpec AirportSpec::dummy = AS_GENERIC(&_airportfta_dummy, NULL, _default_airports_rotation, 0, NULL, 0, 0, 0, 0, 0, MIN_YEAR, MIN_YEAR, ATP_TTDP_LARGE, APC_BEGIN, STR_NULL, 0, false);
+AirportSpec AirportSpec::dummy = AS_GENERIC(&_airportfta_dummy, NULL, _default_airports_rotation, 0, NULL, 0, 0, 0, 0, 0, MIN_YEAR, MIN_YEAR, 0, ATP_TTDP_LARGE, APC_BEGIN, STR_NULL, 0, false);
#undef AS
#undef AS_ND
diff --git a/src/table/pricebase.h b/src/table/pricebase.h
index 84d23b3bd..ee62e9faf 100644
--- a/src/table/pricebase.h
+++ b/src/table/pricebase.h
@@ -76,5 +76,10 @@ extern const PriceBaseSpec _price_base_specs[] = {
{ 2000, PCAT_CONSTRUCTION, GSF_END, PR_CLEAR_BRIDGE }, ///< PR_CLEAR_AQUEDUCT
{ 7500, PCAT_CONSTRUCTION, GSF_END, PR_CLEAR_WATER }, ///< PR_BUILD_LOCK
{ 2000, PCAT_CONSTRUCTION, GSF_END, PR_CLEAR_WATER }, ///< PR_CLEAR_LOCK
+ { 12, PCAT_RUNNING, GSF_END, PR_BUILD_RAIL }, ///< PR_INFRASTRUCTURE_RAIL
+ { 10, PCAT_RUNNING, GSF_END, PR_BUILD_ROAD }, ///< PR_INFRASTRUCTURE_ROAD
+ { 8, PCAT_RUNNING, GSF_END, PR_BUILD_CANAL }, ///< PR_INFRASTRUCTURE_WATER
+ { 100, PCAT_RUNNING, GSF_END, PR_STATION_VALUE }, ///< PR_INFRASTRUCTURE_STATION
+ { 5000, PCAT_RUNNING, GSF_END, PR_BUILD_STATION_AIRPORT}, ///< PR_INFRASTRUCTURE_AIRPORT
};
assert_compile(lengthof(_price_base_specs) == PR_END);
diff --git a/src/table/railtypes.h b/src/table/railtypes.h
index 39e2b2862..065f78720 100644
--- a/src/table/railtypes.h
+++ b/src/table/railtypes.h
@@ -81,6 +81,9 @@ static const RailtypeInfo _original_railtypes[] = {
/* cost multiplier */
8,
+ /* maintenance cost multiplier */
+ 8,
+
/* acceleration type */
0,
@@ -175,6 +178,9 @@ static const RailtypeInfo _original_railtypes[] = {
/* cost multiplier */
12,
+ /* maintenance cost multiplier */
+ 12,
+
/* acceleration type */
0,
@@ -265,6 +271,9 @@ static const RailtypeInfo _original_railtypes[] = {
/* cost multiplier */
16,
+ /* maintenance cost multiplier */
+ 16,
+
/* acceleration type */
1,
@@ -355,6 +364,9 @@ static const RailtypeInfo _original_railtypes[] = {
/* cost multiplier */
24,
+ /* maintenance cost multiplier */
+ 24,
+
/* acceleration type */
2,
diff --git a/src/table/settings.ini b/src/table/settings.ini
index 48dc333bb..965eaeb17 100644
--- a/src/table/settings.ini
+++ b/src/table/settings.ini
@@ -39,6 +39,7 @@ static bool InvalidateNewGRFChangeWindows(int32 p1);
static bool InvalidateIndustryViewWindow(int32 p1);
static bool InvalidateAISettingsWindow(int32 p1);
static bool RedrawTownAuthority(int32 p1);
+static bool InvalidateCompanyInfrastructureWindow(int32 p1);
extern bool UpdateNewGRFConfigPalette(int32 p1);
static bool ZoomMinMaxChanged(int32 p1);
@@ -1237,6 +1238,14 @@ def = 4000
min = 800
max = 65535
+[SDT_BOOL]
+base = GameSettings
+var = economy.infrastructure_maintenance
+from = 166
+def = false
+str = STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE
+proc = InvalidateCompanyInfrastructureWindow
+
##
[SDT_VAR]
base = GameSettings
diff --git a/src/water.h b/src/water.h
index 56bd92fde..bf26cf90d 100644
--- a/src/water.h
+++ b/src/water.h
@@ -16,6 +16,8 @@
#include "company_type.h"
#include "slope_type.h"
#include "water_map.h"
+#include "economy_func.h"
+#include "core/math_func.hpp"
/**
* Describes the behaviour of a tile during flooding.
@@ -43,4 +45,14 @@ void MakeWaterKeepingClass(TileIndex tile, Owner o);
bool RiverModifyDesertZone(TileIndex tile, void *data);
+/**
+ * Calculates the maintenance cost of a number of canal tiles.
+ * @param num Number of canal tiles.
+ * @return Total cost.
+ */
+static inline Money CanalMaintenanceCost(uint32 num)
+{
+ return (_price[PR_INFRASTRUCTURE_WATER] * num * (1 + IntSqrt(num))) >> 6; // 6 bits scaling.
+}
+
#endif /* WATER_H */