(svn r18281) -Feature: founding towns in-game (based on work by Belugas, TheJosh, GeekToo, Terkhen and others)

This commit is contained in:
smatz 2009-11-24 21:18:11 +00:00
parent 8d6e323ef8
commit f0c64208cf
12 changed files with 107 additions and 24 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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"),

View File

@ -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)
};

View File

@ -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),

View File

@ -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 --- */

View File

@ -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;
}

View File

@ -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);
}
};

View File

@ -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