diff --git a/src/citymania/cm_event.hpp b/src/citymania/cm_event.hpp index 9fd7c122ac..bf2c95bd8b 100644 --- a/src/citymania/cm_event.hpp +++ b/src/citymania/cm_event.hpp @@ -20,10 +20,33 @@ namespace event { struct NewMonth { }; -struct TownGrowthTick { +struct TownGrowthSucceeded { Town *town; - bool growth_result; - uint16 prev_houses; + TileIndex tile; + uint32 prev_houses; +}; + +struct TownGrowthFailed { + Town *town; + TileIndex tile; +}; + +struct HouseRebuilt { + Town *town; + TileIndex tile; + bool was_successful; +}; + +struct HouseBuilt { + Town *town; + TileIndex tile; + const HouseSpec *house_spec; +}; + +struct HouseCompleted { + Town *town; + TileIndex tile; + const HouseSpec *house_spec; }; struct CompanyEvent { diff --git a/src/citymania/cm_game.cpp b/src/citymania/cm_game.cpp index 9e6ced6d4d..187449f9d3 100644 --- a/src/citymania/cm_game.cpp +++ b/src/citymania/cm_game.cpp @@ -7,7 +7,7 @@ namespace citymania { Game::Game() { - this->events.listen([] (const event::NewMonth &) { + this->events.listen([this] (const event::NewMonth &) { for (Town *t : Town::Iterate()) { t->cm.hs_last_month = t->cm.hs_total - t->cm.hs_total_prev; t->cm.hs_total_prev = t->cm.hs_total; @@ -15,17 +15,47 @@ Game::Game() { t->cm.cs_total_prev = t->cm.cs_total; t->cm.hr_last_month = t->cm.hr_total - t->cm.hr_total_prev; t->cm.hr_total_prev = t->cm.hr_total; + + t->cm.houses_reconstructed_last_month = t->cm.houses_reconstructed_this_month; + t->cm.houses_reconstructed_this_month = 0; + t->cm.houses_demolished_last_month = t->cm.houses_demolished_this_month; + t->cm.houses_demolished_this_month = 0; + } + + this->towns_growth_tiles_last_month = this->towns_growth_tiles; + this->towns_growth_tiles.clear(); + }); + + this->events.listen([this] (const event::TownGrowthSucceeded &event) { + if (event.town->cache.num_houses <= event.prev_houses) { + event.town->cm.hs_total++; + this->towns_growth_tiles[event.tile] = TownGrowthTileState::HS; } }); - this->events.listen([this] (const event::TownGrowthTick &event) { - if (event.growth_result) { - if (event.town->cache.num_houses <= event.prev_houses) { - event.town->cm.hs_total++; - } + + this->events.listen([this] (const event::TownGrowthFailed &event) { + event.town->cm.cs_total++; + this->towns_growth_tiles[event.tile] = TownGrowthTileState::CS; + }); + + this->events.listen([this] (const event::HouseRebuilt &event) { + if (event.was_successful) { + event.town->cm.houses_reconstructed_this_month++; + this->towns_growth_tiles[event.tile] = TownGrowthTileState::RH_REBUILT; } else { - event.town->cm.cs_total++; + event.town->cm.houses_demolished_this_month++; + this->towns_growth_tiles[event.tile] = TownGrowthTileState::RH_REMOVED; } }); + + this->events.listen([this] (const event::HouseBuilt &event) { + event.town->cm.houses_constructing++; + this->towns_growth_tiles[event.tile] = TownGrowthTileState::NEW_HOUSE; + }); + + this->events.listen([this] (const event::HouseCompleted &event) { + event.town->cm.houses_constructing--; + }); } } // namespace citymania \ No newline at end of file diff --git a/src/citymania/cm_game.hpp b/src/citymania/cm_game.hpp index 2caa4a1646..a1195bd569 100644 --- a/src/citymania/cm_game.hpp +++ b/src/citymania/cm_game.hpp @@ -7,11 +7,49 @@ namespace citymania { +/* BEGIN CMClient growth tiles */ +enum class TownGrowthTileState : uint8 { + NONE = 0, + RH_REMOVED, + NEW_HOUSE, + RH_REBUILT, // rebuilt and removed houses are also + CS, + HS, + HR +}; + class Game { public: event::Dispatcher events; + typedef std::map TownsGrowthTilesIndex; + TownsGrowthTilesIndex towns_growth_tiles_last_month; + TownsGrowthTilesIndex towns_growth_tiles; + Game(); + + TownGrowthTileState get_town_growth_tile(TileIndex tile) { + auto a = this->towns_growth_tiles.find(tile); + auto b = this->towns_growth_tiles_last_month.find(tile); + auto as = (a == this->towns_growth_tiles.end() ? TownGrowthTileState::NONE : (*a).second); + auto bs = (b == this->towns_growth_tiles.end() ? TownGrowthTileState::NONE : (*b).second); + return max(as, bs); + } + + void rebuild_town_caches() { + for (Town *town : Town::Iterate()) { + town->cm.houses_constructing = 0; + town->cache.potential_pop = 0; + } + for (TileIndex t = 0; t < MapSize(); t++) { + if (!IsTileType(t, MP_HOUSE)) continue; + Town *town = Town::GetByTile(t); + if (!IsHouseCompleted(t)) + town->cm.houses_constructing++; + HouseID house_id = GetHouseType(t); + town->cache.potential_pop += HouseSpec::Get(house_id)->population; + } + } }; } // namespace citymania diff --git a/src/citymania/cm_saveload.cpp b/src/citymania/cm_saveload.cpp index 6cec829eea..832b2cdcd6 100644 --- a/src/citymania/cm_saveload.cpp +++ b/src/citymania/cm_saveload.cpp @@ -7,6 +7,8 @@ #include "cm_bitstream.hpp" #include "cm_saveload.hpp" +#include "cm_game.hpp" +#include "cm_main.hpp" namespace citymania { @@ -25,31 +27,22 @@ static const SaveLoad _storage_desc[] = { static void EncodeTownsExtraInfo(BitOStream &bs) { - uint n_affected_towns = 0; for (const Town *t : Town::Iterate()) { - if (t->growing_by_chance || t->houses_reconstruction || - t->houses_demolished) - n_affected_towns++; - } - bs.WriteBytes(n_affected_towns, 2); - for (const Town *t : Town::Iterate()) { - if (t->growing_by_chance || t->houses_reconstruction || - t->houses_demolished) { - bs.WriteBytes(t->index, 2); - bs.WriteBytes(t->growing_by_chance, 1); - bs.WriteBytes(t->houses_reconstruction, 2); - bs.WriteBytes(t->houses_demolished, 2); - } + bs.WriteBytes(t->cm.growing_by_chance, 1); + bs.WriteBytes(t->cm.houses_reconstructed_this_month, 2); + bs.WriteBytes(t->cm.houses_reconstructed_last_month, 2); + bs.WriteBytes(t->cm.houses_demolished_this_month, 2); + bs.WriteBytes(t->cm.houses_demolished_last_month, 2); } } -static void EncodeTownsGrowthTiles(BitOStream &bs, TownsGrowthTilesIndex &tiles) +static void EncodeTownsGrowthTiles(BitOStream &bs, Game::TownsGrowthTilesIndex &tiles) { bs.WriteBytes(tiles.size(), 4); - for (TownsGrowthTilesIndex::iterator p = tiles.begin(); + for (Game::TownsGrowthTilesIndex::iterator p = tiles.begin(); p != tiles.end(); p++) { bs.WriteBytes(p->first, 4); - bs.WriteBytes(p->second, 1); + bs.WriteBytes((uint8)p->second, 1); } } @@ -64,39 +57,33 @@ static void EncodeTownsLayoutErrors(BitOStream &bs) for (const Town *t : Town::Iterate()) { if (t->cm.hr_total || t->cm.hs_total || t->cm.cs_total) { bs.WriteBytes(t->index, 2); - bs.WriteBytes(t->cm.hs_total, 2); + bs.WriteBytes(t->cm.hs_total, 4); bs.WriteBytes(t->cm.hs_total_prev, 2); bs.WriteBytes(t->cm.hs_last_month, 2); - bs.WriteBytes(t->cm.cs_total, 2); + bs.WriteBytes(t->cm.cs_total, 4); bs.WriteBytes(t->cm.cs_total_prev, 2); bs.WriteBytes(t->cm.cs_last_month, 2); - bs.WriteBytes(t->cm.hr_total, 2); + bs.WriteBytes(t->cm.hr_total, 4); bs.WriteBytes(t->cm.hr_total_prev, 2); bs.WriteBytes(t->cm.hr_last_month, 2); } } - EncodeTownsGrowthTiles(bs, _towns_growth_tiles); - EncodeTownsGrowthTiles(bs, _towns_growth_tiles_last_month); + EncodeTownsGrowthTiles(bs, _game->towns_growth_tiles); + EncodeTownsGrowthTiles(bs, _game->towns_growth_tiles_last_month); } static void DecodeTownsExtraInfo(BitIStream &bs) { - Town *t; - uint n_affected_towns = bs.ReadBytes(2); - for (uint i = 0; i < n_affected_towns; i++) { - uint town_id = bs.ReadBytes(2); - t = Town::Get(town_id); - if (!t) { - DEBUG(sl, 0, "Invalid TownID in CM extra towns info (%u)", town_id); - continue; - } - t->growing_by_chance = bs.ReadBytes(1); - t->houses_reconstruction = bs.ReadBytes(2); - t->houses_demolished = bs.ReadBytes(2); + for (Town *t : Town::Iterate()) { + t->cm.growing_by_chance = bs.ReadBytes(1); + t->cm.houses_reconstructed_this_month = bs.ReadBytes(2); + t->cm.houses_reconstructed_last_month = bs.ReadBytes(2); + t->cm.houses_demolished_this_month = bs.ReadBytes(2); + t->cm.houses_demolished_last_month = bs.ReadBytes(2); } } -static void DecodeTownsGrowthTiles(BitIStream &bs, TownsGrowthTilesIndex &tiles) +static void DecodeTownsGrowthTiles(BitIStream &bs, Game::TownsGrowthTilesIndex &tiles) { uint n = bs.ReadBytes(4); for (uint i = 0; i < n; i++) { @@ -127,8 +114,8 @@ static void DecodeTownsLayoutErrors(BitIStream &bs) t->cm.hr_total_prev = bs.ReadBytes(2); t->cm.hr_last_month = bs.ReadBytes(2); } - DecodeTownsGrowthTiles(bs, _towns_growth_tiles); - DecodeTownsGrowthTiles(bs, _towns_growth_tiles_last_month); + DecodeTownsGrowthTiles(bs, _game->towns_growth_tiles); + DecodeTownsGrowthTiles(bs, _game->towns_growth_tiles_last_month); } void CBController_saveload_encode(BitOStream &bs) { @@ -310,7 +297,6 @@ static void DecodeTownsCargoV1(BitIStream &bs) } static void DecodeData(u8vector &data) { - ResetTownsGrowthTiles(); if (data.size() == 0) { DEBUG(sl, 2, "No CityMania save data"); return; diff --git a/src/citymania/extensions/cmext_town.hpp b/src/citymania/extensions/cmext_town.hpp index cd07b37a08..9001b7d600 100644 --- a/src/citymania/extensions/cmext_town.hpp +++ b/src/citymania/extensions/cmext_town.hpp @@ -7,15 +7,21 @@ namespace ext { class Town { public: - uint32 hs_total = 0; ///< number of skipped house buildings (HS) in total - uint32 hs_total_prev = 0; ///< number of skipped house buildings (HS) in total at the end of last month - uint32 hs_last_month = 0; ///< number of skipped house buildings (HS) during last month - uint32 cs_total = 0; ///< number of skipped growth cycles (CS) in total - uint32 cs_total_prev = 0; ///< number of skipped growth cycles (CS) in total at the end of last month - uint32 cs_last_month = 0; ///< number of skipped growth cycles (CS) during last month - uint32 hr_total = 0; ///< number of houses removed by the server (HR) in total - uint32 hr_total_prev = 0; ///< number of houses removed by the server (HR) in total at the end of last month - uint32 hr_last_month = 0; ///< number of houses removed by the server (HR) during last month + bool growing_by_chance = false; ///< whether town is growing due to 1/12 chance + uint32 hs_total = 0; ///< number of skipped house buildings (HS) in total + uint16 hs_total_prev = 0; ///< number of skipped house buildings (HS) in total at the end of last month + uint16 hs_last_month = 0; ///< number of skipped house buildings (HS) during last month + uint32 cs_total = 0; ///< number of skipped growth cycles (CS) in total + uint16 cs_total_prev = 0; ///< number of skipped growth cycles (CS) in total at the end of last month + uint16 cs_last_month = 0; ///< number of skipped growth cycles (CS) during last month + uint32 hr_total = 0; ///< number of houses removed by the server (HR) in total + uint16 hr_total_prev = 0; ///< number of houses removed by the server (HR) in total at the end of last month + uint16 hr_last_month = 0; ///< number of houses removed by the server (HR) during last month + uint16 houses_constructing = 0; ///< number of houses currently being built + uint16 houses_reconstructed_this_month = 0; ///< number of houses rebuilt this month + uint16 houses_reconstructed_last_month = 0; ///< number of houses rebuild last month + uint16 houses_demolished_this_month = 0; ///< number of houses demolished this month + uint16 houses_demolished_last_month = 0; ///< number of houses demolished last month }; } // namespace citymania diff --git a/src/citymania/highlight.cpp b/src/citymania/highlight.cpp index 5f033044e8..21787bf54a 100644 --- a/src/citymania/highlight.cpp +++ b/src/citymania/highlight.cpp @@ -18,6 +18,8 @@ #include "station_ui.hpp" +#include "cm_main.hpp" + /** Enumeration of multi-part foundations */ enum FoundationPart { @@ -289,28 +291,27 @@ TileHighlight GetTileHighlight(const TileInfo *ti) { th.add_border(citymania::GetAnyStationCatchmentBorder(ti->tile), SPR_PALETTE_ZONING_LIGHT_BLUE); } else if (_zoning.outer == CHECKTOWNGROWTHTILES) { - auto tgt = max(_towns_growth_tiles[ti->tile], _towns_growth_tiles_last_month[ti->tile]); // if (tgt == TGTS_NEW_HOUSE) th.sprite = SPR_IMG_HOUSE_NEW; - switch (tgt) { - case TGTS_CB_HOUSE_REMOVED_NOGROW: - case TGTS_RH_REMOVED: + switch (_game->get_town_growth_tile(ti->tile)) { + // case TGTS_CB_HOUSE_REMOVED_NOGROW: + case TownGrowthTileState::RH_REMOVED: th.selection = SPR_PALETTE_ZONING_LIGHT_BLUE; break; - case TGTS_RH_REBUILT: + case TownGrowthTileState::RH_REBUILT: th.selection = SPR_PALETTE_ZONING_WHITE; th.structure_pal = PALETTE_TINT_WHITE; break; - case TGTS_NEW_HOUSE: + case TownGrowthTileState::NEW_HOUSE: th.selection = SPR_PALETTE_ZONING_GREEN; th.structure_pal = PALETTE_TINT_GREEN; break; - case TGTS_CYCLE_SKIPPED: + case TownGrowthTileState::CS: th.selection = SPR_PALETTE_ZONING_ORANGE; break; - case TGTS_HOUSE_SKIPPED: + case TownGrowthTileState::HS: th.selection = SPR_PALETTE_ZONING_YELLOW; break; - case TGTS_CB_HOUSE_REMOVED: + case TownGrowthTileState::HR: th.selection = SPR_PALETTE_ZONING_RED; break; default: th.selection = PAL_NONE; diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 56629892eb..3535255b4c 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -17,6 +17,7 @@ #include "saveload.h" #include "newgrf_sl.h" +#include "../citymania/cm_main.hpp" #include "../safeguards.h" /** @@ -31,7 +32,6 @@ void RebuildTownCaches() for (Town *town : Town::Iterate()) { town->cache.population = 0; town->cache.num_houses = 0; - town->cache.potential_pop = 0; } for (TileIndex t = 0; t < MapSize(); t++) { @@ -41,8 +41,6 @@ void RebuildTownCaches() Town *town = Town::GetByTile(t); IncreaseBuildingCount(town, house_id); if (IsHouseCompleted(t)) town->cache.population += HouseSpec::Get(house_id)->population; - else town->houses_construction++; - town->cache.potential_pop += HouseSpec::Get(house_id)->population; /* Increase the number of houses for every house, but only once. */ if (GetHouseNorthPart(house_id) == 0) town->cache.num_houses++; @@ -54,6 +52,7 @@ void RebuildTownCaches() UpdateTownCargoes(town); } UpdateTownCargoBitmap(); + citymania::_game->rebuild_town_caches(); } /** diff --git a/src/town.h b/src/town.h index 3150f90b30..55603989d2 100644 --- a/src/town.h +++ b/src/town.h @@ -111,10 +111,6 @@ struct Town : TownPool::PoolItem<&_town_pool> { StringID town_label; ///< Label dependent on _local_company rating. CBTownInfo cb; - bool growing_by_chance; ///< town growing due to 1/12 chance? - uint houses_construction; ///< number of houses currently being built - uint houses_reconstruction; ///< number of houses currently being rebuilt - uint houses_demolished; ///< number of houses demolished this month CompanyMask fund_regularly; ///< funds buildings regularly when previous fund ends CompanyMask do_powerfund; ///< funds buildings when grow counter is maximal (results in fastest funding possible) uint32 last_funding = 0; ///< when town was funded the last time @@ -300,24 +296,6 @@ int CB_GetTownReq(uint population, uint req, uint from, bool from_non_important, uint CB_GetMaxTownStorage(Town *town, uint cargo); bool TownExecuteAction(const Town *town, uint action); -enum TownGrowthTileState { - TGTS_NONE = 0, - TGTS_RH_REMOVED, - TGTS_NEW_HOUSE, - TGTS_RH_REBUILT, // rebuilt and removed houses are also - TGTS_CB_HOUSE_REMOVED_NOGROW, // new, so larger priority - TGTS_CYCLE_SKIPPED, - TGTS_HOUSE_SKIPPED, - TGTS_CB_HOUSE_REMOVED -}; - -typedef std::map TownsGrowthTilesIndex; -extern TownsGrowthTilesIndex _towns_growth_tiles_last_month; -extern TownsGrowthTilesIndex _towns_growth_tiles; - -void UpdateTownGrowthTile(TileIndex tile, TownGrowthTileState state); -void ResetTownsGrowthTiles(); - /** Town actions of a company. */ enum TownActions { TACT_NONE = 0x00, ///< Empty action set. diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index b734d2b1f0..54b4a399fd 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -66,8 +66,6 @@ uint days_in_month[] = {31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};//CB void CB_UpdateTownStorage(Town *t); //CB const Money NOVAPOLIS_COMPANY_MONEY_THRESHOLD = INT64_MAX >> 4; -TownsGrowthTilesIndex _towns_growth_tiles_last_month; -TownsGrowthTilesIndex _towns_growth_tiles; TownID _new_town_id; CargoTypes _town_cargoes_accepted; ///< Bitmap of all cargoes accepted by houses. @@ -533,12 +531,13 @@ static void MakeSingleHouseBigger(TileIndex tile) /* Now that construction is complete, we can add the population of the * building to the town. */ HouseID house_id = GetHouseType(tile); + auto hs = HouseSpec::Get(house_id); Town *town = Town::GetByTile(tile); - const HouseSpec *hs = HouseSpec::Get(house_id); - ChangePopulation(town, hs->population); + ChangePopulation(Town::GetByTile(tile), hs->population); ResetHouseAge(tile); + if (hs->building_flags & BUILDING_HAS_1_TILE) - town->houses_construction--; + citymania::Emit(citymania::event::HouseCompleted{town, tile, hs}); } MarkTileDirtyByTile(tile); } @@ -673,14 +672,9 @@ static void TileLoop_Town(TileIndex tile) ClearTownHouse(t, tile); /* Rebuild with another house? */ - if (GB(r, 24, 8) >= 12 && BuildTownHouse(t, tile)) { - t->houses_reconstruction++; - UpdateTownGrowthTile(tile, TGTS_RH_REBUILT); - } else { - /* House wasn't replaced, so remove it */ - t->houses_demolished++; - UpdateTownGrowthTile(tile, TGTS_RH_REMOVED); - } + bool rebuild_res = false; + if (GB(r, 24, 8) >= 12) rebuild_res = BuildTownHouse(t, tile); + citymania::Emit(citymania::event::HouseRebuilt{t, tile, rebuild_res}); } cur_company.Restore(); @@ -708,11 +702,11 @@ static CommandCost ClearTile_Town(TileIndex tile, DoCommandFlag flags) ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM, flags); if (flags & DC_EXEC) { - if (_current_company == COMPANY_FIRST && - Company::Get(_current_company)->money > NOVAPOLIS_COMPANY_MONEY_THRESHOLD) { - if (t->cb.growth_state == TownGrowthState::GROWING) t->cm.hr_total++; - UpdateTownGrowthTile(tile, t->cb.growth_state == TownGrowthState::GROWING ? TGTS_CB_HOUSE_REMOVED: TGTS_CB_HOUSE_REMOVED_NOGROW); - } + // if (_current_company == COMPANY_FIRST && + // Company::Get(_current_company)->money > NOVAPOLIS_COMPANY_MONEY_THRESHOLD) { + // if (t->cb.growth_state == TownGrowthState::GROWING) t->cm.hr_total++; + // UpdateTownGrowthTile(tile, t->cb.growth_state == TownGrowthState::GROWING ? TGTS_CB_HOUSE_REMOVED: TGTS_CB_HOUSE_REMOVED_NOGROW); + // } ClearTownHouse(t, tile); } @@ -1026,10 +1020,7 @@ static void TownTickHandler(Town *t) int i = (int)t->grow_counter - 1; uint16 houses_prev = t->cache.num_houses; if (i < 0) { - uint16 prev_houses = t->cache.num_houses; - bool growth_res = GrowTown(t); - citymania::Emit((citymania::event::TownGrowthTick){t, growth_res, prev_houses}); - if (growth_res) { + if (GrowTown(t)) { i = t->growth_rate; } else { /* If growth failed wait a bit before retrying */ @@ -1690,12 +1681,11 @@ static bool CanFollowRoad(TileIndex tile, DiagDirection dir) * @param tile to inquiry * @return true if town expansion was possible */ -static bool GrowTownAtRoad(Town *t, TileIndex start_tile, TileIndex &tile) +static bool GrowTownAtRoad(Town *t, TileIndex tile) { /* Special case. * @see GrowTownInTile Check the else if */ - tile = start_tile; DiagDirection target_dir = DIAGDIR_END; // The direction in which we want to extend the town assert(tile < MapSize()); @@ -1718,17 +1708,24 @@ static bool GrowTownAtRoad(Town *t, TileIndex start_tile, TileIndex &tile) break; } + uint16 prev_houses = t->cache.num_houses; do { RoadBits cur_rb = GetTownRoadBits(tile); // The RoadBits of the current tile /* Try to grow the town from this point */ GrowTownInTile(&tile, cur_rb, target_dir, t); - if (_grow_town_result == GROWTH_SUCCEED) return true; + if (_grow_town_result == GROWTH_SUCCEED) { + citymania::Emit(citymania::event::TownGrowthSucceeded{t, tile, prev_houses}); + return true; + } /* Exclude the source position from the bitmask * and return if no more road blocks available */ if (IsValidDiagDirection(target_dir)) cur_rb &= ~DiagDirToRoadBits(ReverseDiagDir(target_dir)); - if (cur_rb == ROAD_NONE) return false; + if (cur_rb == ROAD_NONE) { + citymania::Emit(citymania::event::TownGrowthFailed{t, tile}); + return false; + } if (IsTileType(tile, MP_TUNNELBRIDGE)) { /* Only build in the direction away from the tunnel or bridge. */ @@ -1737,7 +1734,10 @@ static bool GrowTownAtRoad(Town *t, TileIndex start_tile, TileIndex &tile) /* Select a random bit from the blockmask, walk a step * and continue the search from there. */ do { - if (cur_rb == ROAD_NONE) return false; + if (cur_rb == ROAD_NONE) { + citymania::Emit(citymania::event::TownGrowthFailed{t, tile}); + return false; + } RoadBits target_bits; do { target_dir = RandomDiagDir(); @@ -1751,6 +1751,7 @@ static bool GrowTownAtRoad(Town *t, TileIndex start_tile, TileIndex &tile) if (IsTileType(tile, MP_ROAD) && !IsRoadDepot(tile) && HasTileRoadType(tile, RTT_ROAD)) { /* Don't allow building over roads of other cities */ if (IsRoadOwner(tile, RTT_ROAD, OWNER_TOWN) && Town::GetByTile(tile) != t) { + citymania::Emit(citymania::event::TownGrowthFailed{t, tile}); return false; } else if (IsRoadOwner(tile, RTT_ROAD, OWNER_NONE) && _game_mode == GM_EDITOR) { /* If we are in the SE, and this road-piece has no town owner yet, it just found an @@ -1763,6 +1764,7 @@ static bool GrowTownAtRoad(Town *t, TileIndex start_tile, TileIndex &tile) /* Max number of times is checked. */ } while (--_grow_town_result >= 0); + citymania::Emit(citymania::event::TownGrowthFailed{t, tile}); return false; } @@ -1814,14 +1816,8 @@ static bool GrowTown(Town *t) const TileIndexDiffC *ptr; for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) { if (GetTownRoadBits(tile) != ROAD_NONE) { - uint16 houses_prev = t->cache.num_houses; - TileIndex end_tile; - bool success = GrowTownAtRoad(t, tile, end_tile); + bool success = GrowTownAtRoad(t, tile); cur_company.Restore(); - if (!success) - UpdateTownGrowthTile(end_tile, TGTS_CYCLE_SKIPPED); - else if (t->cache.num_houses <= houses_prev) - UpdateTownGrowthTile(end_tile, TGTS_HOUSE_SKIPPED); return success; } tile = TILE_ADD(tile, ToTileIndexDiff(*ptr)); @@ -1837,8 +1833,8 @@ static bool GrowTown(Town *t) if (DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR).Succeeded()) { RoadType rt = GetTownRoadType(t); DoCommand(tile, GenRandomRoadBits() | (rt << 4), t->index, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD); - UpdateTownGrowthTile(tile, TGTS_HOUSE_SKIPPED); cur_company.Restore(); + citymania::Emit(citymania::event::TownGrowthSucceeded{t, tile, t->cache.num_houses}); return true; } } @@ -1846,8 +1842,8 @@ static bool GrowTown(Town *t) } } - UpdateTownGrowthTile(tile, TGTS_CYCLE_SKIPPED); cur_company.Restore(); + citymania::Emit(citymania::event::TownGrowthFailed{t, tile}); return false; } @@ -2014,16 +2010,6 @@ void CB_UpdateTownStorage(Town *t) } //CB -void UpdateTownGrowthTile(TileIndex tile, TownGrowthTileState state) { - _towns_growth_tiles[tile] = max(_towns_growth_tiles[tile], state); -} - -void ResetTownsGrowthTiles() { - _towns_growth_tiles_last_month.clear(); - _towns_growth_tiles.clear(); -} - - extern TileIndex _closest_cache_ref; /** @@ -2075,9 +2061,6 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize t->cb.delivered_last_month[i] = 0; t->cb.required_last_month[i] = 0; } - t->houses_construction = 0; - t->houses_reconstruction = 0; - t->houses_demolished = 0; t->fund_regularly = 0; t->do_powerfund = 0; t->advertise_regularly = 0; @@ -2883,7 +2866,6 @@ static bool BuildTownHouse(Town *t, TileIndex tile) /* build the house */ t->cache.num_houses++; t->cache.potential_pop += hs->population; - t->houses_construction++; /* Special houses that there can be only one of. */ t->flags |= oneof; @@ -2891,6 +2873,7 @@ static bool BuildTownHouse(Town *t, TileIndex tile) byte construction_counter = 0; byte construction_stage = 0; + bool completed = false; if (_generating_world || _game_mode == GM_EDITOR) { uint32 r = Random(); @@ -2899,7 +2882,7 @@ static bool BuildTownHouse(Town *t, TileIndex tile) if (construction_stage == TOWN_HOUSE_COMPLETED) { ChangePopulation(t, hs->population); - t->houses_construction--; + completed = true; } else { construction_counter = GB(r, 2, 2); } @@ -2908,11 +2891,13 @@ static bool BuildTownHouse(Town *t, TileIndex tile) citymania::UpdateZoningTownHouses(t, t->cache.num_houses - 1); MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits); - UpdateTownGrowthTile(tile, TGTS_NEW_HOUSE); UpdateTownRadius(t); UpdateTownGrowthRate(t); UpdateTownCargoes(t, tile); + citymania::Emit(citymania::event::HouseBuilt{t, tile, hs}); + if (completed) citymania::Emit(citymania::event::HouseCompleted{t, tile, hs}); + return true; } @@ -2976,8 +2961,6 @@ void ClearTownHouse(Town *t, TileIndex tile) /* Remove population from the town if the house is finished. */ if (IsHouseCompleted(tile)) { ChangePopulation(t, -hs->population); - } else { - t->houses_construction--; } t->cache.num_houses--; @@ -3773,9 +3756,9 @@ static void UpdateTownGrowth(Town *t) UpdateTownGrowthRate(t); ClrBit(t->flags, TOWN_IS_GROWING); - t->growing_by_chance = false; SetWindowDirty(WC_TOWN_VIEW, t->index); SetWindowDirty(WC_CB_TOWN, t->index); + t->cm.growing_by_chance = false; if (_settings_game.economy.town_growth_rate == 0 && t->fund_buildings_months == 0) return; @@ -3805,7 +3788,7 @@ static void UpdateTownGrowth(Town *t) if (t->fund_buildings_months == 0 && CountActiveStations(t) == 0) { if(!Chance16(1, 12)) return; - t->growing_by_chance = true; + t->cm.growing_by_chance = true; } SetBit(t->flags, TOWN_IS_GROWING); @@ -4024,9 +4007,6 @@ CommandCost CheckforTownRating(DoCommandFlag flags, Town *t, TownRatingCheckType void TownsMonthlyLoop() { - _towns_growth_tiles_last_month = _towns_growth_tiles; - _towns_growth_tiles.clear(); - for (Town *t : Town::Iterate()) { if (t->road_build_months != 0) t->road_build_months--; @@ -4043,9 +4023,6 @@ void TownsMonthlyLoop() UpdateTownCargoes(t); DoRegularFunding(t); - - t->houses_demolished = 0; - t->houses_reconstruction = 0; } UpdateTownCargoBitmap(); diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 0c0cf185be..6d6985572a 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -1408,9 +1408,9 @@ static void DrawExtraTownInfo (const Rect &r, uint &y, Town *town, uint line, bo DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += line, STR_TOWN_VIEW_GROWTH); if (show_house_states_info) { - SetDParam(0, town->houses_construction); - SetDParam(1, town->houses_reconstruction); - SetDParam(2, town->houses_demolished); + SetDParam(0, town->cm.houses_constructing); + SetDParam(1, town->cm.houses_reconstructed_last_month); + SetDParam(2, town->cm.houses_demolished_last_month); DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += line, STR_TOWN_VIEW_HOUSE_STATE); } diff --git a/src/zoning_cmd.cpp b/src/zoning_cmd.cpp index d6bf05c868..0f1d880505 100644 --- a/src/zoning_cmd.cpp +++ b/src/zoning_cmd.cpp @@ -10,6 +10,8 @@ #include #include "citymania/highlight.hpp" +#include "citymania/cm_game.hpp" +#include "citymania/cm_main.hpp" Zoning _zoning = {CHECKNOTHING, CHECKNOTHING}; @@ -311,14 +313,14 @@ SpriteID TileZoneCheckTownAdvertisementZones(TileIndex tile) { //Checks for tile in growth tiles info SpriteID TileZoneCheckTownsGrowthTiles(TileIndex tile) { - switch (max(_towns_growth_tiles[tile], _towns_growth_tiles_last_month[tile])) { - case TGTS_CB_HOUSE_REMOVED_NOGROW: return SPR_PALETTE_ZONING_LIGHT_BLUE; - case TGTS_RH_REMOVED: return SPR_PALETTE_ZONING_LIGHT_BLUE; - case TGTS_RH_REBUILT: return SPR_PALETTE_ZONING_WHITE; - case TGTS_NEW_HOUSE: return SPR_PALETTE_ZONING_GREEN; - case TGTS_CYCLE_SKIPPED: return SPR_PALETTE_ZONING_ORANGE; - case TGTS_HOUSE_SKIPPED: return SPR_PALETTE_ZONING_YELLOW; - case TGTS_CB_HOUSE_REMOVED: return SPR_PALETTE_ZONING_RED; + switch (citymania::_game->get_town_growth_tile(tile)) { + // case TGTS_CB_HOUSE_REMOVED_NOGROW: return SPR_PALETTE_ZONING_LIGHT_BLUE; + case citymania::TownGrowthTileState::RH_REMOVED: return SPR_PALETTE_ZONING_LIGHT_BLUE; + case citymania::TownGrowthTileState::RH_REBUILT: return SPR_PALETTE_ZONING_WHITE; + case citymania::TownGrowthTileState::NEW_HOUSE: return SPR_PALETTE_ZONING_GREEN; + case citymania::TownGrowthTileState::CS: return SPR_PALETTE_ZONING_ORANGE; + case citymania::TownGrowthTileState::HS: return SPR_PALETTE_ZONING_YELLOW; + case citymania::TownGrowthTileState::HR: return SPR_PALETTE_ZONING_RED; default: return INVALID_SPRITE_ID; } }