Add: Setting to allow placing houses manually in-game (#13266)

This commit is contained in:
Tyler Trahan 2025-02-09 13:34:31 -05:00 committed by GitHub
parent 01b639bb23
commit b2f5a4901b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 57 additions and 12 deletions

View File

@ -1987,6 +1987,13 @@ 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_HOUSE_PLACER :Placing individual town houses: {STRING2}
STR_CONFIG_SETTING_HOUSE_PLACER_HELPTEXT :Enabling this setting allows players to place town houses manually
###length 3
STR_CONFIG_SETTING_HOUSE_PLACER_FORBIDDEN :Forbidden
STR_CONFIG_SETTING_HOUSE_PLACER_ALLOWED :Allowed
STR_CONFIG_SETTING_HOUSE_PLACER_FULLY_CONSTRUCTED :Allowed, fully constructed
STR_CONFIG_SETTING_TOWN_CARGOGENMODE :Town cargo generation: {STRING2}
STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :How much cargo is produced by houses in towns, relative to the overall population of the town.{}Quadratic growth: A town twice the size generates four times as many passengers.{}Linear growth: A town twice the size generates twice the amount of passengers
###length 2

View File

@ -2219,6 +2219,7 @@ static SettingsContainer &GetSettingsTree()
towns->Add(new SettingEntry("economy.allow_town_roads"));
towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
towns->Add(new SettingEntry("economy.found_town"));
towns->Add(new SettingEntry("economy.place_houses"));
towns->Add(new SettingEntry("economy.town_layout"));
towns->Add(new SettingEntry("economy.larger_towns"));
towns->Add(new SettingEntry("economy.initial_city_size"));

View File

@ -91,6 +91,13 @@ enum RightClickClose : uint8_t {
RCC_YES_EXCEPT_STICKY,
};
/** Possible values for "place_houses" setting. */
enum PlaceHouses : uint8_t {
PH_FORBIDDEN = 0,
PH_ALLOWED,
PH_ALLOWED_CONSTRUCTED,
};
/** Settings related to the difficulty of the game */
struct DifficultySettings {
uint8_t competitor_start_time; ///< Unused value, used to load old savegames.
@ -529,6 +536,7 @@ struct EconomySettings {
TownCargoGenMode town_cargogen_mode; ///< algorithm for generating cargo from houses, @see TownCargoGenMode
bool allow_town_roads; ///< towns are allowed to build roads (always allowed when generating world / in SE)
TownFounding found_town; ///< town founding.
PlaceHouses place_houses; ///< players are allowed to place town houses.
bool station_noise_level; ///< build new airports when the town noise level is still within accepted limits
uint16_t town_noise_population[4]; ///< population to base decision on noise evaluation (@see town_council_tolerance)
bool allow_town_level_crossings; ///< towns are allowed to build level crossings

View File

@ -12,6 +12,8 @@ static void TownFoundingChanged(int32_t new_value);
static void ChangeTimekeepingUnits(int32_t new_value);
static void ChangeMinutesPerYear(int32_t new_value);
static constexpr std::initializer_list<const char*> _place_houses{"forbidden", "allowed", "fully constructed"};
static const SettingVariant _economy_settings_table[] = {
[post-amble]
};
@ -80,6 +82,19 @@ strval = STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN
post_cb = TownFoundingChanged
cat = SC_BASIC
[SDT_VAR]
var = economy.place_houses
type = SLE_UINT8
flags = SettingFlag::GuiDropdown
def = PH_FORBIDDEN
min = PH_FORBIDDEN
max = PH_ALLOWED_CONSTRUCTED
full = _place_houses
str = STR_CONFIG_SETTING_HOUSE_PLACER
strhelp = STR_CONFIG_SETTING_HOUSE_PLACER_HELPTEXT
strval = STR_CONFIG_SETTING_HOUSE_PLACER_FORBIDDEN
cat = SC_ADVANCED
[SDT_BOOL]
var = economy.allow_town_level_crossings
from = SLV_143

View File

@ -481,13 +481,21 @@ static CallBackFunction MenuClickMap(int index)
/* --- Town button menu --- */
enum TownMenuEntries {
TME_SHOW_DIRECTORY = 0,
TME_SHOW_FOUND_TOWN,
TME_SHOW_PLACE_HOUSES,
};
static CallBackFunction ToolbarTownClick(Window *w)
{
if (_settings_game.economy.found_town == TF_FORBIDDEN) {
PopupMainToolbarMenu(w, WID_TN_TOWNS, {STR_TOWN_MENU_TOWN_DIRECTORY});
} else {
PopupMainToolbarMenu(w, WID_TN_TOWNS, {STR_TOWN_MENU_TOWN_DIRECTORY, STR_TOWN_MENU_FOUND_TOWN});
}
DropDownList list;
list.push_back(MakeDropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY, TME_SHOW_DIRECTORY));
if (_settings_game.economy.found_town != TF_FORBIDDEN) list.push_back(MakeDropDownListStringItem(STR_TOWN_MENU_FOUND_TOWN, TME_SHOW_FOUND_TOWN));
if (_settings_game.economy.place_houses != PH_FORBIDDEN) list.push_back(MakeDropDownListStringItem(STR_SCENEDIT_TOWN_MENU_PACE_HOUSE, TME_SHOW_PLACE_HOUSES));
PopupMainToolbarMenu(w, WID_TN_TOWNS, std::move(list), 0);
return CBF_NONE;
}
@ -500,10 +508,13 @@ static CallBackFunction ToolbarTownClick(Window *w)
static CallBackFunction MenuClickTown(int index)
{
switch (index) {
case 0: ShowTownDirectory(); break;
case 1: // setting could be changed when the dropdown was open
case TME_SHOW_DIRECTORY: ShowTownDirectory(); break;
case TME_SHOW_FOUND_TOWN: // Setting could be changed when the dropdown was open
if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow();
break;
case TME_SHOW_PLACE_HOUSES: // Setting could be changed when the dropdown was open
if (_settings_game.economy.place_houses != PH_FORBIDDEN) ShowBuildHousePicker(nullptr);
break;
}
return CBF_NONE;
}

View File

@ -2731,8 +2731,9 @@ static bool CheckTownBuild2x2House(TileIndex *tile, Town *t, int maxz, bool nosl
* @param hs The @a HouseSpec of the house.
* @param house The @a HouseID of the house.
* @param random_bits The random data to be associated with the house.
* @param house_completed Should the house be placed already complete, instead of under construction?
*/
static void BuildTownHouse(Town *t, TileIndex tile, const HouseSpec *hs, HouseID house, uint8_t random_bits)
static void BuildTownHouse(Town *t, TileIndex tile, const HouseSpec *hs, HouseID house, uint8_t random_bits, bool house_completed)
{
/* build the house */
t->cache.num_houses++;
@ -2740,7 +2741,7 @@ static void BuildTownHouse(Town *t, TileIndex tile, const HouseSpec *hs, HouseID
uint8_t construction_counter = 0;
uint8_t construction_stage = 0;
if (_generating_world || _game_mode == GM_EDITOR) {
if (_generating_world || _game_mode == GM_EDITOR || house_completed) {
uint32_t construction_random = Random();
construction_stage = TOWN_HOUSE_COMPLETED;
@ -2879,7 +2880,7 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile)
/* Special houses that there can be only one of. */
t->flags |= oneof;
BuildTownHouse(t, tile, hs, house, random_bits);
BuildTownHouse(t, tile, hs, house, random_bits, false);
return true;
}
@ -2889,7 +2890,8 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile)
CommandCost CmdPlaceHouse(DoCommandFlag flags, TileIndex tile, HouseID house)
{
if (_game_mode != GM_EDITOR) return CMD_ERROR;
if (_game_mode != GM_EDITOR && _settings_game.economy.place_houses == PH_FORBIDDEN) return CMD_ERROR;
if (Town::GetNumItems() == 0) return CommandCost(STR_ERROR_MUST_FOUND_TOWN_FIRST);
if (static_cast<size_t>(house) >= HouseSpec::Specs().size()) return CMD_ERROR;
@ -2929,7 +2931,8 @@ CommandCost CmdPlaceHouse(DoCommandFlag flags, TileIndex tile, HouseID house)
}
if (flags & DC_EXEC) {
BuildTownHouse(t, tile, hs, house, Random());
bool house_completed = _settings_game.economy.place_houses == PH_ALLOWED_CONSTRUCTED;
BuildTownHouse(t, tile, hs, house, Random(), house_completed);
}
return CommandCost();