summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command.cpp2
-rw-r--r--src/command_type.h1
-rw-r--r--src/lang/english.txt10
-rw-r--r--src/saveload/saveload.cpp2
-rw-r--r--src/settings.cpp11
-rw-r--r--src/settings_gui.cpp1
-rw-r--r--src/settings_type.h3
-rw-r--r--src/table/settings.h4
-rw-r--r--src/toolbar_gui.cpp9
-rw-r--r--src/town_cmd.cpp54
-rw-r--r--src/town_gui.cpp22
-rw-r--r--src/town_type.h12
12 files changed, 107 insertions, 24 deletions
diff --git a/src/command.cpp b/src/command.cpp
index 8cc6ad77c..cb97886d2 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -295,7 +295,7 @@ static const Command _command_proc_table[] = {
{CmdSellShareInCompany, 0}, // CMD_SELL_SHARE_IN_COMPANY
{CmdBuyCompany, 0}, // CMD_BUY_COMANY
- {CmdFoundTown, CMD_NO_TEST | CMD_OFFLINE}, // CMD_FOUND_TOWN
+ {CmdFoundTown, CMD_NO_TEST}, // CMD_FOUND_TOWN; founding random town can fail only in exec run
{CmdRenameTown, CMD_SERVER}, // CMD_RENAME_TOWN
{CmdDoTownAction, 0}, // CMD_DO_TOWN_ACTION
diff --git a/src/command_type.h b/src/command_type.h
index 8ac3786a1..a5a7bf1a6 100644
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -243,7 +243,6 @@ enum {
CMD_BUY_COMPANY, ///< buy a company which is bankrupt
CMD_FOUND_TOWN, ///< found a town
-
CMD_RENAME_TOWN, ///< rename a town
CMD_DO_TOWN_ACTION, ///< do a action from the town detail window (like advertises or bribe)
diff --git a/src/lang/english.txt b/src/lang/english.txt
index cd5e77ce4..66c3bc4d8 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -368,7 +368,9 @@ STR_MAP_MENU_EXTRA_VIEW_PORT :Extra viewport
STR_MAP_MENU_SIGN_LIST :Sign list
############ range for town menu starts, yet the town directory is shown in the map menu in the scenario editor
STR_TOWN_MENU_TOWN_DIRECTORY :Town directory
-############ both ranges ends here
+############ end of the 'Display map' dropdown
+STR_TOWN_MENU_FOUND_TOWN :Found town
+############ end of the 'Town' dropdown
############ range for subsidies menu starts
STR_SUBSIDIES_MENU_SUBSIDIES :Subsidies
@@ -760,6 +762,8 @@ STR_NEWS_COMPANY_LAUNCH_DESCRIPTION :{BIGFONT}{BLACK
STR_NEWS_MERGER_TAKEOVER_TITLE :{BIGFONT}{BLACK}{RAW_STRING} has been taken over by {RAW_STRING}!
STR_PRESIDENT_NAME_MANAGER :{BLACK}{PRESIDENTNAME}{}(Manager)
+STR_NEWS_NEW_TOWN :{BLACK}{BIGFONT}{RAW_STRING} sponsored construction of new town {TOWN}!
+
STR_NEWS_INDUSTRY_CONSTRUCTION :{BIGFONT}{BLACK}New {STRING} under construction near {TOWN}!
STR_NEWS_INDUSTRY_PLANTED :{BIGFONT}{BLACK}New {STRING} being planted near {TOWN}!
@@ -1237,6 +1241,10 @@ STR_CONFIG_SETTING_TOWN_LAYOUT_3X3_GRID :3x3 grid
STR_CONFIG_SETTING_TOWN_LAYOUT_RANDOM :random
STR_CONFIG_SETTING_ALLOW_TOWN_ROADS :{LTBLUE}Towns are allowed to build roads: {ORANGE}{STRING1}
STR_CONFIG_SETTING_NOISE_LEVEL :{LTBLUE}Allow town controlled noise level for airports: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWN_FOUNDING :{LTBLUE}Founding towns in game: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :forbidden
+STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :allowed
+STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :allowed, custom town layout
STR_CONFIG_SETTING_TOOLBAR_POS :{LTBLUE}Position of main toolbar: {ORANGE}{STRING1}
STR_CONFIG_SETTING_TOOLBAR_POS_LEFT :Left
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp
index 76025aee7..cbf24248b 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -47,7 +47,7 @@
#include "saveload_internal.h"
-extern const uint16 SAVEGAME_VERSION = 127;
+extern const uint16 SAVEGAME_VERSION = 128;
SavegameType _savegame_type; ///< type of savegame we are loading
diff --git a/src/settings.cpp b/src/settings.cpp
index 2ea624c33..f45adbe2d 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -753,6 +753,17 @@ static bool DragSignalsDensityChanged(int32)
return true;
}
+static bool TownFoundingChanged(int32 p1)
+{
+ if (_game_mode != GM_EDITOR && _settings_game.economy.found_town == TF_FORBIDDEN) {
+ DeleteWindowById(WC_FOUND_TOWN, 0);
+ return true;
+ }
+ InvalidateWindowData(WC_FOUND_TOWN, 0);
+ 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 f3d7a08c3..6b172f2d9 100644
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -1298,6 +1298,7 @@ static SettingEntry _settings_economy_towns[] = {
SettingEntry("economy.exclusive_rights"),
SettingEntry("economy.town_layout"),
SettingEntry("economy.allow_town_roads"),
+ SettingEntry("economy.found_town"),
SettingEntry("economy.mod_road_rebuild"),
SettingEntry("economy.town_growth_rate"),
SettingEntry("economy.larger_towns"),
diff --git a/src/settings_type.h b/src/settings_type.h
index 1ad632436..02e997f61 100644
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -327,8 +327,9 @@ struct EconomySettings {
uint8 town_growth_rate; ///< town growth rate
uint8 larger_towns; ///< the number of cities to build. These start off larger and grow twice as fast
uint8 initial_city_size; ///< multiplier for the initial size of the cities compared to towns
- TownLayoutByte town_layout; ///< select town layout
+ TownLayoutByte town_layout; ///< select town layout, @see TownLayout
bool allow_town_roads; ///< towns are allowed to build roads (always allowed when generating world / in SE)
+ TownFoundingByte found_town; ///< town founding, @see TownFounding
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)
};
diff --git a/src/table/settings.h b/src/table/settings.h
index 623ed658d..045721de2 100644
--- a/src/table/settings.h
+++ b/src/table/settings.h
@@ -23,6 +23,7 @@ static bool UpdateConsists(int32 p1);
static bool CheckInterval(int32 p1);
static bool TrainAccelerationModelChanged(int32 p1);
static bool DragSignalsDensityChanged(int32);
+static bool TownFoundingChanged(int32 p1);
static bool DifficultyReset(int32 level);
static bool DifficultyChange(int32);
static bool DifficultyNoiseChange(int32 i);
@@ -364,8 +365,9 @@ const SettingDesc _settings[] = {
SDT_BOOL(GameSettings, construction.longbridges, 0,NN, true, STR_CONFIG_SETTING_LONGBRIDGES, NULL),
SDT_BOOL(GameSettings, construction.signal_side, N,NN, true, STR_CONFIG_SETTING_SIGNALSIDE, RedrawScreen),
SDT_BOOL(GameSettings, station.never_expire_airports, 0,NN, false, STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS, NULL),
- SDT_CONDVAR(GameSettings, economy.town_layout, SLE_UINT8, 59, SL_MAX_VERSION, 0,MS,TL_ORIGINAL,TL_BEGIN,NUM_TLS-1,1, STR_CONFIG_SETTING_TOWN_LAYOUT, NULL),
+ SDT_CONDVAR(GameSettings, economy.town_layout, SLE_UINT8, 59, SL_MAX_VERSION, 0,MS,TL_ORIGINAL,TL_BEGIN,NUM_TLS - 1, 1, STR_CONFIG_SETTING_TOWN_LAYOUT, TownFoundingChanged),
SDT_CONDBOOL(GameSettings, economy.allow_town_roads, 113, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_ALLOW_TOWN_ROADS, NULL),
+ SDT_CONDVAR(GameSettings, economy.found_town, SLE_UINT8,128, SL_MAX_VERSION, 0,MS,TF_FORBIDDEN,TF_BEGIN,TF_END - 1, 1, STR_CONFIG_SETTING_TOWN_FOUNDING, TownFoundingChanged),
SDT_VAR(GameSettings, vehicle.train_acceleration_model, SLE_UINT8, 0,MS, 0, 0, 1, 1, STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL, TrainAccelerationModelChanged),
SDT_BOOL(GameSettings, pf.forbid_90_deg, 0, 0, false, STR_CONFIG_SETTING_FORBID_90_DEG, NULL),
diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp
index 369a532e0..8c258db74 100644
--- a/src/toolbar_gui.cpp
+++ b/src/toolbar_gui.cpp
@@ -405,12 +405,17 @@ static void MenuClickMap(int index)
static void ToolbarTownClick(Window *w)
{
- PopupMainToolbMenu(w, TBN_TOWNDIRECTORY, STR_TOWN_MENU_TOWN_DIRECTORY, 1);
+ PopupMainToolbMenu(w, TBN_TOWNDIRECTORY, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 1 : 2);
}
static void MenuClickTown(int index)
{
- ShowTownDirectory();
+ switch (index) {
+ case 0: ShowTownDirectory(); break;
+ case 1: // setting could be changed when the dropdown was open
+ if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow();
+ break;
+ }
}
/* --- Subidies button menu --- */
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index 30c4806b1..3257ef54f 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -1458,7 +1458,7 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize
int x = (int)size * 16 + 3;
if (size == TS_RANDOM) x = (Random() & 0xF) + 8;
- if (city) x *= _settings_game.economy.initial_city_size;
+ if (city && _game_mode == GM_EDITOR) x *= _settings_game.economy.initial_city_size;
t->num_houses += x;
UpdateTownRadius(t);
@@ -1515,9 +1515,8 @@ static bool IsUniqueTownName(const char *name)
return true;
}
-/** Create a new town.
- * This obviously only works in the scenario editor. Function not removed
- * as it might be possible in the future to fund your own town :)
+/**
+ * Create a new town.
* @param tile coordinates where town is built
* @param flags type of operation
* @param p1 0..1 size of the town (@see TownSize)
@@ -1530,9 +1529,6 @@ static bool IsUniqueTownName(const char *name)
*/
CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- /* Only in the scenario editor */
- if (_game_mode != GM_EDITOR) return CMD_ERROR;
-
TownSize size = (TownSize)GB(p1, 0, 2);
bool city = HasBit(p1, 2);
TownLayout layout = (TownLayout)GB(p1, 3, 3);
@@ -1543,6 +1539,16 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
if (size > TS_RANDOM) return CMD_ERROR;
if (layout > TL_RANDOM) return CMD_ERROR;
+ /* Some things are allowed only in the scenario editor */
+ if (_game_mode != GM_EDITOR) {
+ if (_settings_game.economy.found_town == TF_FORBIDDEN) return CMD_ERROR;
+ if (size == TS_LARGE) return CMD_ERROR;
+ if (random) return CMD_ERROR;
+ if (_settings_game.economy.found_town != TF_CUSTOM_LAYOUT && layout != _settings_game.economy.town_layout) {
+ return CMD_ERROR;
+ }
+ }
+
if (StrEmpty(text)) {
/* If supplied name is empty, townnameparts has to generate unique automatic name */
if (!VerifyTownName(townnameparts, &par)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
@@ -1555,10 +1561,23 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
/* Allocate town struct */
if (!Town::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_TOWNS);
- CommandCost cost(EXPENSES_OTHER);
if (!random) {
- cost = TownCanBePlacedHere(tile);
- if (CmdFailed(cost)) return cost;
+ CommandCost ret = TownCanBePlacedHere(tile);
+ if (CmdFailed(ret)) return ret;
+ }
+
+ static const byte price_mult[][TS_RANDOM + 1] = {{ 15, 25, 40, 25 }, { 20, 35, 55, 35 }};
+ /* multidimensional arrays have to have defined length of non-first dimension */
+ assert_compile(lengthof(price_mult[0]) == 4);
+
+ CommandCost cost(EXPENSES_OTHER, _price[PR_BUILD_INDUSTRY]);
+ byte mult = price_mult[city][size];
+
+ cost.MultiplyCost(mult);
+
+ if (cost.GetCost() > GetAvailableMoneyForCommand()) {
+ _additional_cash_required = cost.GetCost();
+ return CommandCost(EXPENSES_OTHER);
}
/* Create the town */
@@ -1579,10 +1598,25 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
}
UpdateNearestTownForRoadTiles(false);
_generating_world = false;
+
if (t != NULL && !StrEmpty(text)) {
t->name = strdup(text);
t->UpdateVirtCoord();
}
+
+ if (_game_mode != GM_EDITOR) {
+ /* 't' can't be NULL since 'random' is false outside scenedit */
+ assert(!random);
+ char company_name[MAX_LENGTH_COMPANY_NAME_BYTES];
+ SetDParam(0, _current_company);
+ GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
+
+ char *cn = strdup(company_name);
+ SetDParamStr(0, cn);
+ SetDParam(1, t->index);
+
+ AddNewsItem(STR_NEWS_NEW_TOWN, NS_INDUSTRY_OPEN, NR_TILE, tile, NR_NONE, UINT32_MAX, cn);
+ }
}
return cost;
}
diff --git a/src/town_gui.cpp b/src/town_gui.cpp
index cbf033115..b1fea3616 100644
--- a/src/town_gui.cpp
+++ b/src/town_gui.cpp
@@ -991,7 +991,7 @@ public:
this->InitNested(desc, window_number);
InitializeTextBuffer(&this->text, this->edit_str_buf, this->edit_str_size, MAX_LENGTH_TOWN_NAME_PIXELS);
this->RandomTownName();
- this->UpdateButtons();
+ this->UpdateButtons(true);
}
void RandomTownName()
@@ -1010,8 +1010,15 @@ public:
this->SetWidgetDirty(TSEW_TOWNNAME_EDITBOX);
}
- void UpdateButtons()
+ void UpdateButtons(bool check_availability)
{
+ if (check_availability && _game_mode != GM_EDITOR) {
+ this->SetWidgetsDisabledState(true, TSEW_RANDOMTOWN, TSEW_MANYRANDOMTOWNS, TSEW_SIZE_LARGE, WIDGET_LIST_END);
+ this->SetWidgetsDisabledState(_settings_game.economy.found_town != TF_CUSTOM_LAYOUT,
+ TSEW_LAYOUT_ORIGINAL, TSEW_LAYOUT_BETTER, TSEW_LAYOUT_GRID2, TSEW_LAYOUT_GRID3, TSEW_LAYOUT_RANDOM, WIDGET_LIST_END);
+ if (_settings_game.economy.found_town != TF_CUSTOM_LAYOUT) town_layout = _settings_game.economy.town_layout;
+ }
+
for (int i = TSEW_SIZE_SMALL; i <= TSEW_SIZE_RANDOM; i++) {
this->SetWidgetLoweredState(i, i == TSEW_SIZE_SMALL + this->town_size);
}
@@ -1080,7 +1087,7 @@ public:
case TSEW_SIZE_SMALL: case TSEW_SIZE_MEDIUM: case TSEW_SIZE_LARGE: case TSEW_SIZE_RANDOM:
this->town_size = (TownSize)(widget - TSEW_SIZE_SMALL);
- this->UpdateButtons();
+ this->UpdateButtons(false);
break;
case TSEW_CITY:
@@ -1092,7 +1099,7 @@ public:
case TSEW_LAYOUT_ORIGINAL: case TSEW_LAYOUT_BETTER: case TSEW_LAYOUT_GRID2:
case TSEW_LAYOUT_GRID3: case TSEW_LAYOUT_RANDOM:
this->town_layout = (TownLayout)(widget - TSEW_LAYOUT_ORIGINAL);
- this->UpdateButtons();
+ this->UpdateButtons(false);
break;
}
}
@@ -1124,7 +1131,12 @@ public:
virtual void OnPlaceObjectAbort()
{
this->RaiseButtons();
- this->UpdateButtons();
+ this->UpdateButtons(false);
+ }
+
+ virtual void OnInvalidateData(int)
+ {
+ this->UpdateButtons(true);
}
};
diff --git a/src/town_type.h b/src/town_type.h
index dd2220b66..266e95214 100644
--- a/src/town_type.h
+++ b/src/town_type.h
@@ -87,10 +87,20 @@ enum TownLayout {
NUM_TLS, ///< Number of town layouts
};
-
/** It needs to be 8bits, because we save and load it as such */
typedef SimpleTinyEnumT<TownLayout, byte> TownLayoutByte; // typedefing-enumification of TownLayout
+/** Town founding setting values */
+enum TownFounding {
+ TF_BEGIN = 0, ///< Used for iterations and limit testing
+ TF_FORBIDDEN = 0, ///< Forbidden
+ TF_ALLOWED, ///< Allowed
+ TF_CUSTOM_LAYOUT, ///< Allowed, with custom town layout
+ TF_END, ///< Used for iterations and limit testing
+};
+/** It needs to be 8bits, because we save and load it as such */
+typedef SimpleTinyEnumT<TownFounding, byte> TownFoundingByte;
+
enum {
MAX_LENGTH_TOWN_NAME_BYTES = 31, ///< The maximum length of a town name in bytes including '\0'
MAX_LENGTH_TOWN_NAME_PIXELS = 130, ///< The maximum length of a town name in pixels