mirror of https://github.com/OpenTTD/OpenTTD.git
Codechange: Allocate houses dynamically instead of from a fixed array.
This uses vectors for HouseSpecs and global/town building counts.
This commit is contained in:
parent
8746be8bf2
commit
3e83dcedfd
|
@ -26,6 +26,7 @@
|
||||||
#include "void_map.h"
|
#include "void_map.h"
|
||||||
#include "town.h"
|
#include "town.h"
|
||||||
#include "newgrf.h"
|
#include "newgrf.h"
|
||||||
|
#include "newgrf_house.h"
|
||||||
#include "core/random_func.hpp"
|
#include "core/random_func.hpp"
|
||||||
#include "core/backup_type.hpp"
|
#include "core/backup_type.hpp"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
|
@ -311,6 +312,7 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti
|
||||||
|
|
||||||
/* Load the right landscape stuff, and the NewGRFs! */
|
/* Load the right landscape stuff, and the NewGRFs! */
|
||||||
GfxLoadSprites();
|
GfxLoadSprites();
|
||||||
|
InitializeBuildingCounts();
|
||||||
LoadStringWidthTable();
|
LoadStringWidthTable();
|
||||||
|
|
||||||
/* Re-init the windowing system */
|
/* Re-init the windowing system */
|
||||||
|
|
15
src/house.h
15
src/house.h
|
@ -31,12 +31,6 @@ static const HouseID INVALID_HOUSE_ID = 0xFFFF;
|
||||||
|
|
||||||
static const uint HOUSE_NUM_ACCEPTS = 16; ///< Max number of cargoes accepted by a tile
|
static const uint HOUSE_NUM_ACCEPTS = 16; ///< Max number of cargoes accepted by a tile
|
||||||
|
|
||||||
/**
|
|
||||||
* There can only be as many classes as there are new houses, plus one for
|
|
||||||
* NO_CLASS, as the original houses don't have classes.
|
|
||||||
*/
|
|
||||||
static const uint HOUSE_CLASS_MAX = NUM_HOUSES - NEW_HOUSE_OFFSET + 1;
|
|
||||||
|
|
||||||
enum BuildingFlags {
|
enum BuildingFlags {
|
||||||
TILE_NO_FLAG = 0,
|
TILE_NO_FLAG = 0,
|
||||||
TILE_SIZE_1x1 = 1U << 0,
|
TILE_SIZE_1x1 = 1U << 0,
|
||||||
|
@ -123,14 +117,11 @@ struct HouseSpec {
|
||||||
uint8_t minimum_life; ///< The minimum number of years this house will survive before the town rebuilds it
|
uint8_t minimum_life; ///< The minimum number of years this house will survive before the town rebuilds it
|
||||||
CargoTypes watched_cargoes; ///< Cargo types watched for acceptance.
|
CargoTypes watched_cargoes; ///< Cargo types watched for acceptance.
|
||||||
|
|
||||||
|
HouseID Index() const;
|
||||||
Money GetRemovalCost() const;
|
Money GetRemovalCost() const;
|
||||||
|
|
||||||
static inline HouseSpec *Get(size_t house_id)
|
static std::vector<HouseSpec> &Specs();
|
||||||
{
|
static HouseSpec *Get(size_t house_id);
|
||||||
assert(house_id < NUM_HOUSES);
|
|
||||||
extern HouseSpec _house_specs[];
|
|
||||||
return &_house_specs[house_id];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -148,7 +148,6 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
|
||||||
InitializeTrees();
|
InitializeTrees();
|
||||||
InitializeIndustries();
|
InitializeIndustries();
|
||||||
InitializeObjects();
|
InitializeObjects();
|
||||||
InitializeBuildingCounts();
|
|
||||||
|
|
||||||
InitializeNPF();
|
InitializeNPF();
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,11 @@ void HouseOverrideManager::SetEntitySpec(const HouseSpec *hs)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*HouseSpec::Get(house_id) = *hs;
|
auto &house_specs = HouseSpec::Specs();
|
||||||
|
|
||||||
|
/* Now that we know we can use the given id, copy the spec to its final destination. */
|
||||||
|
if (house_id >= house_specs.size()) house_specs.resize(house_id + 1);
|
||||||
|
house_specs[house_id] = *hs;
|
||||||
|
|
||||||
/* Now add the overrides. */
|
/* Now add the overrides. */
|
||||||
for (int i = 0; i < this->max_offset; i++) {
|
for (int i = 0; i < this->max_offset; i++) {
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
static BuildingCounts<uint32_t> _building_counts;
|
static BuildingCounts<uint32_t> _building_counts{};
|
||||||
static std::array<HouseClassMapping, HOUSE_CLASS_MAX> _class_mapping;
|
static std::vector<HouseClassMapping> _class_mapping{};
|
||||||
|
|
||||||
HouseOverrideManager _house_mngr(NEW_HOUSE_OFFSET, NUM_HOUSES, INVALID_HOUSE_ID);
|
HouseOverrideManager _house_mngr(NEW_HOUSE_OFFSET, NUM_HOUSES, INVALID_HOUSE_ID);
|
||||||
|
|
||||||
|
@ -40,6 +40,48 @@ static const GRFFile *GetHouseSpecGrf(HouseID house_id)
|
||||||
return (hs != nullptr) ? hs->grf_prop.grffile : nullptr;
|
return (hs != nullptr) ? hs->grf_prop.grffile : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern const HouseSpec _original_house_specs[NEW_HOUSE_OFFSET];
|
||||||
|
std::vector<HouseSpec> _house_specs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a reference to all HouseSpecs.
|
||||||
|
* @return Reference to vector of all HouseSpecs.
|
||||||
|
*/
|
||||||
|
std::vector<HouseSpec> &HouseSpec::Specs()
|
||||||
|
{
|
||||||
|
return _house_specs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the spec for a house ID.
|
||||||
|
* @param house_id The ID of the house.
|
||||||
|
* @return The HouseSpec associated with the ID.
|
||||||
|
*/
|
||||||
|
HouseSpec *HouseSpec::Get(size_t house_id)
|
||||||
|
{
|
||||||
|
/* Empty house if index is out of range -- this might happen if NewGRFs are changed. */
|
||||||
|
static HouseSpec empty = {};
|
||||||
|
|
||||||
|
assert(house_id < NUM_HOUSES);
|
||||||
|
if (house_id >= _house_specs.size()) return ∅
|
||||||
|
return &_house_specs[house_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset and initialise house specs. */
|
||||||
|
void ResetHouses()
|
||||||
|
{
|
||||||
|
_house_specs.clear();
|
||||||
|
_house_specs.reserve(std::size(_original_house_specs));
|
||||||
|
|
||||||
|
ResetHouseClassIDs();
|
||||||
|
|
||||||
|
/* Copy default houses. */
|
||||||
|
_house_specs.insert(std::end(_house_specs), std::begin(_original_house_specs), std::end(_original_house_specs));
|
||||||
|
|
||||||
|
/* Reset any overrides that have been set. */
|
||||||
|
_house_mngr.ResetOverride();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a resolver for a house.
|
* Construct a resolver for a house.
|
||||||
* @param house_id House to query.
|
* @param house_id House to query.
|
||||||
|
@ -74,32 +116,47 @@ uint32_t HouseResolverObject::GetDebugID() const
|
||||||
|
|
||||||
void ResetHouseClassIDs()
|
void ResetHouseClassIDs()
|
||||||
{
|
{
|
||||||
_class_mapping = {};
|
_class_mapping.clear();
|
||||||
|
|
||||||
|
/* Add initial entry for HOUSE_NO_CLASS. */
|
||||||
|
_class_mapping.emplace_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
HouseClassID AllocateHouseClassID(uint8_t grf_class_id, uint32_t grfid)
|
HouseClassID AllocateHouseClassID(uint8_t grf_class_id, uint32_t grfid)
|
||||||
{
|
{
|
||||||
/* Start from 1 because 0 means that no class has been assigned. */
|
/* Start from 1 because 0 means that no class has been assigned. */
|
||||||
for (int i = 1; i != lengthof(_class_mapping); i++) {
|
auto it = std::find_if(std::next(std::begin(_class_mapping)), std::end(_class_mapping), [grf_class_id, grfid](const HouseClassMapping &map) { return map.class_id == grf_class_id && map.grfid == grfid; });
|
||||||
HouseClassMapping *map = &_class_mapping[i];
|
|
||||||
|
|
||||||
if (map->class_id == grf_class_id && map->grfid == grfid) return (HouseClassID)i;
|
/* HouseClass not found, allocate a new one. */
|
||||||
|
if (it == std::end(_class_mapping)) it = _class_mapping.insert(it, {.grfid = grfid, .class_id = grf_class_id});
|
||||||
|
|
||||||
if (map->class_id == 0 && map->grfid == 0) {
|
return static_cast<HouseClassID>(std::distance(std::begin(_class_mapping), it));
|
||||||
map->class_id = grf_class_id;
|
|
||||||
map->grfid = grfid;
|
|
||||||
return (HouseClassID)i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return HOUSE_NO_CLASS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise building counts for a town.
|
||||||
|
* @param t Town cache to initialise.
|
||||||
|
*/
|
||||||
|
void InitializeBuildingCounts(Town *t)
|
||||||
|
{
|
||||||
|
t->cache.building_counts.id_count.clear();
|
||||||
|
t->cache.building_counts.class_count.clear();
|
||||||
|
t->cache.building_counts.id_count.resize(HouseSpec::Specs().size());
|
||||||
|
t->cache.building_counts.class_count.resize(_class_mapping.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise global building counts and all town building counts.
|
||||||
|
*/
|
||||||
void InitializeBuildingCounts()
|
void InitializeBuildingCounts()
|
||||||
{
|
{
|
||||||
memset(&_building_counts, 0, sizeof(_building_counts));
|
_building_counts.id_count.clear();
|
||||||
|
_building_counts.class_count.clear();
|
||||||
|
_building_counts.id_count.resize(HouseSpec::Specs().size());
|
||||||
|
_building_counts.class_count.resize(_class_mapping.size());
|
||||||
|
|
||||||
for (Town *t : Town::Iterate()) {
|
for (Town *t : Town::Iterate()) {
|
||||||
memset(&t->cache.building_counts, 0, sizeof(t->cache.building_counts));
|
InitializeBuildingCounts(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,7 @@ void ResetHouseClassIDs();
|
||||||
HouseClassID AllocateHouseClassID(uint8_t grf_class_id, uint32_t grfid);
|
HouseClassID AllocateHouseClassID(uint8_t grf_class_id, uint32_t grfid);
|
||||||
|
|
||||||
void InitializeBuildingCounts();
|
void InitializeBuildingCounts();
|
||||||
|
void InitializeBuildingCounts(Town *t);
|
||||||
void IncreaseBuildingCount(Town *t, HouseID house_id);
|
void IncreaseBuildingCount(Town *t, HouseID house_id);
|
||||||
void DecreaseBuildingCount(Town *t, HouseID house_id);
|
void DecreaseBuildingCount(Town *t, HouseID house_id);
|
||||||
|
|
||||||
|
|
|
@ -1817,7 +1817,7 @@ static_assert(lengthof(_town_draw_tile_data) == (NEW_HOUSE_OFFSET) * 4 * 4);
|
||||||
bf, ba, true, GRFFileProps(INVALID_HOUSE_ID), 0, {COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN}, \
|
bf, ba, true, GRFFileProps(INVALID_HOUSE_ID), 0, {COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN}, \
|
||||||
16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, {0, 2, 0, 0}, 0, 0, 0}
|
16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, {0, 2, 0, 0}, 0, 0, 0}
|
||||||
/** House specifications from original data */
|
/** House specifications from original data */
|
||||||
static const HouseSpec _original_house_specs[] = {
|
extern const HouseSpec _original_house_specs[] = {
|
||||||
/**
|
/**
|
||||||
* remove_rating_decrease
|
* remove_rating_decrease
|
||||||
* | mail_generation
|
* | mail_generation
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct BuildingCounts {
|
struct BuildingCounts {
|
||||||
T id_count[NUM_HOUSES];
|
std::vector<T> id_count;
|
||||||
T class_count[HOUSE_CLASS_MAX];
|
std::vector<T> class_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint CUSTOM_TOWN_NUMBER_DIFFICULTY = 4; ///< value for custom town number in difficulty settings
|
static const uint CUSTOM_TOWN_NUMBER_DIFFICULTY = 4; ///< value for custom town number in difficulty settings
|
||||||
|
|
|
@ -1941,6 +1941,7 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32_t townnameparts, TownSi
|
||||||
UpdateTownRadius(t);
|
UpdateTownRadius(t);
|
||||||
t->flags = 0;
|
t->flags = 0;
|
||||||
t->cache.population = 0;
|
t->cache.population = 0;
|
||||||
|
InitializeBuildingCounts(t);
|
||||||
/* Spread growth across ticks so even if there are many
|
/* Spread growth across ticks so even if there are many
|
||||||
* similar towns they're unlikely to grow all in one tick */
|
* similar towns they're unlikely to grow all in one tick */
|
||||||
t->grow_counter = t->index % Ticks::TOWN_GROWTH_TICKS;
|
t->grow_counter = t->index % Ticks::TOWN_GROWTH_TICKS;
|
||||||
|
@ -3969,17 +3970,3 @@ extern const TileTypeProcs _tile_type_town_procs = {
|
||||||
GetFoundation_Town, // get_foundation_proc
|
GetFoundation_Town, // get_foundation_proc
|
||||||
TerraformTile_Town, // terraform_tile_proc
|
TerraformTile_Town, // terraform_tile_proc
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
HouseSpec _house_specs[NUM_HOUSES];
|
|
||||||
|
|
||||||
void ResetHouses()
|
|
||||||
{
|
|
||||||
ResetHouseClassIDs();
|
|
||||||
|
|
||||||
auto insert = std::copy(std::begin(_original_house_specs), std::end(_original_house_specs), std::begin(_house_specs));
|
|
||||||
std::fill(insert, std::end(_house_specs), HouseSpec{});
|
|
||||||
|
|
||||||
/* Reset any overrides that have been set. */
|
|
||||||
_house_mngr.ResetOverride();
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue