(svn r9667) -Feature: Add the concept of cities. A (configurable) proportion of towns can
authormaedhros
Wed, 18 Apr 2007 14:23:30 +0000
changeset 6486 7d2ae0a167fb
parent 6485 2c310cd45776
child 6487 beeeb8979e81
(svn r9667) -Feature: Add the concept of cities. A (configurable) proportion of towns can
start off larger, and will grow twice as quickly as other towns. They can also
be placed specifically in the scenario editor. Thanks to TheJosh for the
initial patch and the idea.
src/lang/english.txt
src/main_gui.cpp
src/openttd.cpp
src/saveload.cpp
src/settings.cpp
src/settings_gui.cpp
src/town.h
src/town_cmd.cpp
src/variables.h
--- a/src/lang/english.txt	Wed Apr 18 07:22:53 2007 +0000
+++ b/src/lang/english.txt	Wed Apr 18 14:23:30 2007 +0000
@@ -751,6 +751,7 @@
 STR_02A1_SMALL                                                  :{BLACK}Small
 STR_02A2_MEDIUM                                                 :{BLACK}Medium
 STR_02A3_LARGE                                                  :{BLACK}Large
+STR_SCENARIO_EDITOR_CITY                                        :{BLACK}City
 STR_02A4_SELECT_TOWN_SIZE                                       :{BLACK}Select town size
 STR_02A5_TOWN_SIZE                                              :{YELLOW}Town size:
 
@@ -1141,8 +1142,9 @@
 STR_CONFIG_PATCHES_TOWN_GROWTH_NORMAL                           :Normal
 STR_CONFIG_PATCHES_TOWN_GROWTH_FAST                             :Fast
 STR_CONFIG_PATCHES_TOWN_GROWTH_VERY_FAST                        :Very fast
-STR_CONFIG_PATCHES_LARGER_TOWNS                                 :{LTBLUE}Proportion of towns that will grow twice as fast: {ORANGE}1 in {STRING1}
-STR_CONFIG_PATCHES_LARGER_TOWNS_DISABLED                        :{LTBLUE}Proportion of towns that will grow twice as fast: {ORANGE}None
+STR_CONFIG_PATCHES_LARGER_TOWNS                                 :{LTBLUE}Proportion of towns that will become cities: {ORANGE}1 in {STRING1}
+STR_CONFIG_PATCHES_LARGER_TOWNS_DISABLED                        :{LTBLUE}Proportion of towns that will become cities: {ORANGE}None
+STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER                         :{LTBLUE}Initial city size multiplier: {ORANGE}{STRING1}
 
 STR_CONFIG_PATCHES_GUI                                          :{BLACK}Interface
 STR_CONFIG_PATCHES_CONSTRUCTION                                 :{BLACK}Construction
--- a/src/main_gui.cpp	Wed Apr 18 07:22:53 2007 +0000
+++ b/src/main_gui.cpp	Wed Apr 18 14:23:30 2007 +0000
@@ -51,7 +51,7 @@
 
 static byte _terraform_size = 1;
 RailType _last_built_railtype;
-static int _scengen_town_size = 2; // depress medium-sized towns per default
+static int _scengen_town_size = 1; // depress medium-sized towns per default
 
 extern void GenerateIndustries();
 extern bool GenerateTowns();
@@ -1406,7 +1406,9 @@
 
 static void PlaceProc_Town(TileIndex tile)
 {
-	DoCommandP(tile, _scengen_town_size, 0, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE));
+	uint32 size = min(_scengen_town_size, (int)TSM_CITY);
+	uint32 mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED;
+	DoCommandP(tile, size, mode, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE));
 }
 
 
@@ -1414,13 +1416,14 @@
 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                 STR_018B_CLOSE_WINDOW},
 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   147,     0,    13, STR_0233_TOWN_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
 {  WWT_STICKYBOX,   RESIZE_NONE,     7,   148,   159,     0,    13, 0x0,                      STR_STICKY_BUTTON},
-{      WWT_PANEL,   RESIZE_NONE,     7,     0,   159,    14,    81, 0x0,                      STR_NULL},
+{      WWT_PANEL,   RESIZE_NONE,     7,     0,   159,    14,    94, 0x0,                      STR_NULL},
 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   157,    16,    27, STR_0234_NEW_TOWN,        STR_0235_CONSTRUCT_NEW_TOWN},
 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   157,    29,    40, STR_023D_RANDOM_TOWN,     STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION},
 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   157,    42,    53, STR_MANY_RANDOM_TOWNS,    STR_RANDOM_TOWNS_TIP},
 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,    53,    68,    79, STR_02A1_SMALL,           STR_02A4_SELECT_TOWN_SIZE},
 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    54,   105,    68,    79, STR_02A2_MEDIUM,          STR_02A4_SELECT_TOWN_SIZE},
 {    WWT_TEXTBTN,   RESIZE_NONE,    14,   106,   157,    68,    79, STR_02A3_LARGE,           STR_02A4_SELECT_TOWN_SIZE},
+{    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   157,    81,    92, STR_SCENARIO_EDITOR_CITY, STR_02A4_SELECT_TOWN_SIZE},
 {      WWT_LABEL,   RESIZE_NONE,     7,     0,   147,    54,    67, STR_02A5_TOWN_SIZE,       STR_NULL},
 {   WIDGETS_END},
 };
@@ -1433,7 +1436,7 @@
 		break;
 
 	case WE_CREATE:
-		LowerWindowWidget(w, (_scengen_town_size - 1)+ 7);
+		LowerWindowWidget(w, _scengen_town_size + 7);
 		break;
 
 	case WE_CLICK:
@@ -1443,10 +1446,12 @@
 			break;
 		case 5: {// random town
 			Town *t;
+			uint size = min(_scengen_town_size, (int)TSM_CITY);
+			TownSizeMode mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED;
 
 			HandleButtonClick(w, 5);
 			_generating_world = true;
-			t = CreateRandomTown(20, _scengen_town_size);
+			t = CreateRandomTown(20, mode, size);
 			_generating_world = false;
 
 			if (t == NULL) {
@@ -1466,10 +1471,10 @@
 			break;
 		}
 
-		case 7: case 8: case 9:
-			RaiseWindowWidget(w, (_scengen_town_size - 1) + 7);
-			_scengen_town_size = (e->we.click.widget - 7) + 1;
-			LowerWindowWidget(w, (_scengen_town_size - 1) + 7);
+		case 7: case 8: case 9: case 10:
+			RaiseWindowWidget(w, _scengen_town_size + 7);
+			_scengen_town_size = e->we.click.widget - 7;
+			LowerWindowWidget(w, _scengen_town_size + 7);
 			SetWindowDirty(w);
 			break;
 		}
@@ -1485,14 +1490,14 @@
 		break;
 	case WE_ABORT_PLACE_OBJ:
 		RaiseWindowButtons(w);
-		LowerWindowWidget(w, (_scengen_town_size - 1) + 7);
+		LowerWindowWidget(w, _scengen_town_size + 7);
 		SetWindowDirty(w);
 		break;
 	}
 }
 
 static const WindowDesc _scen_edit_town_gen_desc = {
-	WDP_AUTO, WDP_AUTO, 160, 82,
+	WDP_AUTO, WDP_AUTO, 160, 95,
 	WC_SCEN_TOWN_GEN, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_scen_edit_town_gen_widgets,
--- a/src/openttd.cpp	Wed Apr 18 07:22:53 2007 +0000
+++ b/src/openttd.cpp	Wed Apr 18 14:23:30 2007 +0000
@@ -1913,6 +1913,19 @@
 		}
 	}
 
+	/* A patch option containing the proportion of towns that grow twice as
+	 * fast was added in version 54. From version 56 this is now saved in the
+	 * town as cities can be built specifically in the scenario editor. */
+	if (CheckSavegameVersion(56)) {
+		Town *t;
+
+		FOR_ALL_TOWNS(t) {
+			if (_patches.larger_towns != 0 && (t->index % _patches.larger_towns) == 0) {
+				t->larger_town = true;
+			}
+		}
+	}
+
 	return true;
 }
 
--- a/src/saveload.cpp	Wed Apr 18 07:22:53 2007 +0000
+++ b/src/saveload.cpp	Wed Apr 18 14:23:30 2007 +0000
@@ -28,7 +28,7 @@
 #include "variables.h"
 #include <setjmp.h>
 
-extern const uint16 SAVEGAME_VERSION = 55;
+extern const uint16 SAVEGAME_VERSION = 56;
 uint16 _sl_version;       ///< the major savegame version identifier
 byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 
--- a/src/settings.cpp	Wed Apr 18 07:22:53 2007 +0000
+++ b/src/settings.cpp	Wed Apr 18 14:23:30 2007 +0000
@@ -1394,8 +1394,9 @@
 	 SDT_VAR(Patches, ending_year,      SLE_INT32,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_ENDING_YEAR,  NULL),
 	SDT_BOOL(Patches, smooth_economy,             0, 0,  true,            STR_CONFIG_PATCHES_SMOOTH_ECONOMY,   NULL),
 	SDT_BOOL(Patches, allow_shares,               0, 0, false,            STR_CONFIG_PATCHES_ALLOW_SHARES,     NULL),
-	SDT_CONDVAR(Patches, town_growth_rate, SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0,   4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH,  NULL),
-	SDT_CONDVAR(Patches, larger_towns,     SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS, NULL),
+	SDT_CONDVAR(Patches, town_growth_rate,  SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0,   4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH,          NULL),
+	SDT_CONDVAR(Patches, larger_towns,      SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS,         NULL),
+	SDT_CONDVAR(Patches, initial_city_size, SLE_UINT8, 56, SL_MAX_VERSION, 0, 0,  2, 1,  10, 1, STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER, NULL),
 
 	/***************************************************************************/
 	/* AI section of the GUI-configure patches window */
--- a/src/settings_gui.cpp	Wed Apr 18 07:22:53 2007 +0000
+++ b/src/settings_gui.cpp	Wed Apr 18 14:23:30 2007 +0000
@@ -635,6 +635,7 @@
 	"allow_shares",
 	"town_growth_rate",
 	"larger_towns",
+	"initial_city_size",
 };
 
 static const char *_patches_ai[] = {
--- a/src/town.h	Wed Apr 18 07:22:53 2007 +0000
+++ b/src/town.h	Wed Apr 18 14:23:30 2007 +0000
@@ -141,6 +141,9 @@
 	/* Index in town array */
 	TownID index;
 
+	/* If this is a larger town, and should grow more quickly. */
+	bool larger_town;
+
 	/* NOSAVE: UpdateTownRadius updates this given the house count. */
 	uint16 radius[5];
 
@@ -181,6 +184,12 @@
 	const struct GRFFile *grffile;     ///< grf file that introduced this house
 };
 
+enum TownSizeMode {
+	TSM_RANDOM,
+	TSM_FIXED,
+	TSM_CITY
+};
+
 VARDEF HouseSpec _house_specs[HOUSE_MAX];
 
 uint32 GetWorldPopulation();
@@ -189,7 +198,7 @@
 void InitializeTown();
 void ShowTownViewWindow(TownID town);
 void ExpandTown(Town *t);
-Town *CreateRandomTown(uint attempts, uint size_mode);
+Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size);
 
 enum {
 	ROAD_REMOVE = 0,
--- a/src/town_cmd.cpp	Wed Apr 18 07:22:53 2007 +0000
+++ b/src/town_cmd.cpp	Wed Apr 18 14:23:30 2007 +0000
@@ -954,7 +954,16 @@
 	t->max_mail = t->population >> 4;
 }
 
-static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, uint size_mode)
+/**
+ * Does the actual town creation.
+ *
+ * @param t The town
+ * @param tile Where to put it
+ * @param townnameparts The town name
+ * @param size_mode How the size should be determined
+ * @param size Parameter for size determination
+ */
+static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSizeMode size_mode, uint size)
 {
 	int x, i;
 
@@ -1003,10 +1012,25 @@
 	UpdateTownVirtCoord(t);
 	_town_sort_dirty = true;
 
-	if (size_mode == 0) {
-		x = (Random() & 0xF) + 8;
-	} else {
-		x = (size_mode - 1) * 16 + 3;
+	/* Random town size. */
+	x = (Random() & 0xF) + 8;
+
+	switch (size_mode) {
+		default: NOT_REACHED();
+
+		case TSM_RANDOM:
+			t->larger_town = false;
+			break;
+
+		case TSM_FIXED:
+			x = size * 16 + 3;
+			t->larger_town = false;
+			break;
+
+		case TSM_CITY:
+			x *= _patches.initial_city_size;
+			t->larger_town = true;
+			break;
 	}
 
 	t->num_houses += x;
@@ -1051,8 +1075,8 @@
  * as it might be possible in the future to fund your own town :)
  * @param tile coordinates where town is built
  * @param flags type of operation
- * @param p1 size of the town (0 = random, 1 = small, 2 = medium, 3 = large)
- * @param p2 unused
+ * @param p1 size of the town (0 = small, 1 = medium, 2 = large)
+ * @param p2 size mode (@see TownSizeMode)
  */
 int32 CmdBuildTown(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
@@ -1061,6 +1085,7 @@
 
 	/* Only in the scenario editor */
 	if (_game_mode != GM_EDITOR) return CMD_ERROR;
+	if (p2 > TSM_CITY) return CMD_ERROR;
 
 	SET_EXPENSES_TYPE(EXPENSES_OTHER);
 
@@ -1088,13 +1113,13 @@
 	/* Create the town */
 	if (flags & DC_EXEC) {
 		_generating_world = true;
-		DoCreateTown(t, tile, townnameparts, p1);
+		DoCreateTown(t, tile, townnameparts, (TownSizeMode)p2, p1);
 		_generating_world = false;
 	}
 	return 0;
 }
 
-Town *CreateRandomTown(uint attempts, uint size_mode)
+Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size)
 {
 	TileIndex tile;
 	Town *t;
@@ -1118,7 +1143,7 @@
 		t = AllocateTown();
 		if (t == NULL) break;
 
-		DoCreateTown(t, tile, townnameparts, size_mode);
+		DoCreateTown(t, tile, townnameparts, mode, size);
 		return t;
 	} while (--attempts);
 	return NULL;
@@ -1130,17 +1155,20 @@
 {
 	uint num = 0;
 	uint n = ScaleByMapSize(_num_initial_towns[_opt.diff.number_towns] + (Random() & 7));
+	uint num_cities = _patches.larger_towns == 0 ? 0 : n / _patches.larger_towns;
 
 	SetGeneratingWorldProgress(GWP_TOWN, n);
 
 	do {
 		IncreaseGeneratingWorldProgress(GWP_TOWN);
 		/* try 20 times to create a random-sized town for the first loop. */
-		if (CreateRandomTown(20, 0) != NULL) num++;
+		TownSizeMode mode = num_cities > 0 ? TSM_CITY : TSM_RANDOM;
+		if (CreateRandomTown(20, mode, _patches.initial_city_size) != NULL) num++;
+		if (num_cities > 0) num_cities--;
 	} while (--n);
 
 	/* give it a last try, but now more aggressive */
-	if (num == 0 && CreateRandomTown(10000, 0) == NULL) {
+	if (num == 0 && CreateRandomTown(10000, TSM_RANDOM, 0) == NULL) {
 		if (GetNumTowns() == 0) {
 			/* XXX - can we handle that more gracefully? */
 			if (_game_mode != GM_EDITOR) error("Could not generate any town");
@@ -1718,7 +1746,7 @@
 	uint growth_multiplier = _patches.town_growth_rate != 0 ? _patches.town_growth_rate - 1 : 1;
 
 	m >>= growth_multiplier;
-	if (_patches.larger_towns != 0 && (t->index % _patches.larger_towns) == 0) m /= 2;
+	if (t->larger_town) m /= 2;
 
 	t->growth_rate = m / (t->num_houses / 50 + 1);
 	if (m <= t->grow_counter)
@@ -1977,6 +2005,9 @@
 
 	    SLE_VAR(Town, exclusivity,           SLE_UINT8),
 	    SLE_VAR(Town, exclusive_counter,     SLE_UINT8),
+
+	SLE_CONDVAR(Town, larger_town,           SLE_BOOL,                  56, SL_MAX_VERSION),
+
 	/* reserve extra space in savegame here. (currently 30 bytes) */
 	SLE_CONDNULL(30, 2, SL_MAX_VERSION),
 
--- a/src/variables.h	Wed Apr 18 07:22:53 2007 +0000
+++ b/src/variables.h	Wed Apr 18 14:23:30 2007 +0000
@@ -226,8 +226,9 @@
 	uint8 scrollwheel_scrolling;
 	uint8 scrollwheel_multiplier;
 
-	uint8 town_growth_rate; ///< Town growth rate
-	uint8 larger_towns;     ///< 1 in the specified number of towns will grow twice as fast
+	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
 };
 
 VARDEF Patches _patches;