1
0
Fork 0

Add: "Many random towns" button in scenario editor now prompts for the number of towns, with defaults based on new game settings (#14158)

pull/14186/head
Iris-Persephone 2025-05-02 17:54:21 -04:00 committed by GitHub
parent 3eba97f67c
commit 2f020abe74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 46 additions and 13 deletions

View File

@ -231,7 +231,8 @@ void ChangeTownRating(Town *t, int add, int max, DoCommandFlags flags);
HouseZone GetTownRadiusGroup(const Town *t, TileIndex tile); HouseZone GetTownRadiusGroup(const Town *t, TileIndex tile);
void SetTownRatingTestMode(bool mode); void SetTownRatingTestMode(bool mode);
TownActions GetMaskOfTownActions(CompanyID cid, const Town *t); TownActions GetMaskOfTownActions(CompanyID cid, const Town *t);
bool GenerateTowns(TownLayout layout); uint GetDefaultTownsForMapSize();
bool GenerateTowns(TownLayout layout, std::optional<uint> number = std::nullopt);
const CargoSpec *FindFirstCargoWithTownAcceptanceEffect(TownAcceptanceEffect effect); const CargoSpec *FindFirstCargoWithTownAcceptanceEffect(TownAcceptanceEffect effect);
CargoArray GetAcceptedCargoOfHouse(const HouseSpec *hs); CargoArray GetAcceptedCargoOfHouse(const HouseSpec *hs);

View File

@ -2372,19 +2372,39 @@ static Town *CreateRandomTown(uint attempts, uint32_t townnameparts, TownSize si
return nullptr; return nullptr;
} }
static const uint8_t _num_initial_towns[4] = {5, 11, 23, 46}; // very low, low, normal, high /**
* Calculate the number of towns which should be on the map according to the current "town density" newgame setting and the map size.
* If the number of towns is set to "custom", the function will always return that value instead.
* @return The number of towns.
*/
uint GetDefaultTownsForMapSize()
{
static const uint8_t num_initial_towns[4] = {5, 11, 23, 46}; // very low, low, normal, high
if (_settings_game.difficulty.number_towns == static_cast<uint>(CUSTOM_TOWN_NUMBER_DIFFICULTY)) {
return _settings_newgame.game_creation.custom_town_number;
}
return Map::ScaleBySize(num_initial_towns[_settings_game.difficulty.number_towns]);
}
/** /**
* Generate a number of towns with a given layout. * Generate a number of towns with a given layout.
* This function is used by the Random Towns button in Scenario Editor as well as in world generation. * This function is used by the Random Towns button in Scenario Editor as well as in world generation.
* @param layout The road layout to build. * @param layout The road layout to build.
* @param number The number of towns to create. std::nullopt means to use the game settings.
* @return true if towns have been successfully created. * @return true if towns have been successfully created.
*/ */
bool GenerateTowns(TownLayout layout) bool GenerateTowns(TownLayout layout, std::optional<uint> number)
{ {
uint current_number = 0; uint current_number = 0;
uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.number_towns : 0; uint total;
uint total = (difficulty == (uint)CUSTOM_TOWN_NUMBER_DIFFICULTY) ? _settings_game.game_creation.custom_town_number : Map::ScaleBySize(_num_initial_towns[difficulty] + (Random() & 7)); if (number.has_value()) {
total = number.value();
} else if (_settings_game.difficulty.number_towns == static_cast<uint>(CUSTOM_TOWN_NUMBER_DIFFICULTY)) {
total = GetDefaultTownsForMapSize();
} else {
total = GetDefaultTownsForMapSize() + (Random() & 7);
}
total = std::min<uint>(TownPool::MAX_SIZE, total); total = std::min<uint>(TownPool::MAX_SIZE, total);
uint32_t townnameparts; uint32_t townnameparts;
TownNames town_names; TownNames town_names;

View File

@ -34,6 +34,7 @@
#include "townname_func.h" #include "townname_func.h"
#include "core/backup_type.hpp" #include "core/backup_type.hpp"
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
#include "core/string_consumer.hpp"
#include "genworld.h" #include "genworld.h"
#include "fios.h" #include "fios.h"
#include "stringfilter_type.h" #include "stringfilter_type.h"
@ -1249,16 +1250,10 @@ public:
break; break;
case WID_TF_MANY_RANDOM_TOWNS: { case WID_TF_MANY_RANDOM_TOWNS: {
Backup<bool> old_generating_world(_generating_world, true); std::string default_town_number = fmt::format("{}", GetDefaultTownsForMapSize());
UpdateNearestTownForRoadTiles(true); ShowQueryString(default_town_number, STR_MAPGEN_NUMBER_OF_TOWNS, 5, this, CS_NUMERAL, {QueryStringFlag::AcceptUnchanged});
if (!GenerateTowns(this->town_layout)) {
ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_GENERATE_TOWN), GetEncodedString(STR_ERROR_NO_SPACE_FOR_TOWN), WL_INFO);
}
UpdateNearestTownForRoadTiles(false);
old_generating_world.Restore();
break; break;
} }
case WID_TF_LOAD_FROM_FILE: case WID_TF_LOAD_FROM_FILE:
ShowSaveLoadDialog(FT_TOWN_DATA, SLO_LOAD); ShowSaveLoadDialog(FT_TOWN_DATA, SLO_LOAD);
break; break;
@ -1293,6 +1288,23 @@ public:
} }
} }
void OnQueryTextFinished(std::optional<std::string> str) override
{
/* Was 'cancel' pressed? */
if (!str.has_value()) return;
auto value = ParseInteger(*str);
if (!value.has_value()) return;
Backup<bool> old_generating_world(_generating_world, true);
UpdateNearestTownForRoadTiles(true);
if (!GenerateTowns(this->town_layout, value)) {
ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_GENERATE_TOWN), GetEncodedString(STR_ERROR_NO_SPACE_FOR_TOWN), WL_INFO);
}
UpdateNearestTownForRoadTiles(false);
old_generating_world.Restore();
}
void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
{ {
this->ExecuteFoundTownCommand(tile, false, STR_ERROR_CAN_T_FOUND_TOWN_HERE, CcFoundTown); this->ExecuteFoundTownCommand(tile, false, STR_ERROR_CAN_T_FOUND_TOWN_HERE, CcFoundTown);