diff -r f6f6db47bd98 src/script/api/ai_changelog.hpp --- a/src/script/api/ai_changelog.hpp Mon Oct 28 11:09:02 2013 +0000 +++ b/src/script/api/ai_changelog.hpp Mon Oct 28 12:29:28 2013 +0100 @@ -23,6 +23,7 @@ * \li AIStation::HasCargoRating * \li AITile::GetTerrainType * \li AITown::FoundTown + * \li AITown::TOWN_GROWTH_NONE * * Other changes: * \li AIStation::GetCargoRating does return -1 for cargo-station combinations that diff -r f6f6db47bd98 src/script/api/game_changelog.hpp --- a/src/script/api/game_changelog.hpp Mon Oct 28 11:09:02 2013 +0000 +++ b/src/script/api/game_changelog.hpp Mon Oct 28 12:29:28 2013 +0100 @@ -30,6 +30,8 @@ * \li GSTile::GetTerrainType * \li GSTown::FoundTown * \li GSTown::SetName + * \li GSTown::TOWN_GROWTH_NONE + * \li GSTown::TOWN_GROWTH_NORMAL * * Other changes: * \li GSGoal::New can now create up to 64000 concurrent goals. The old limit was 256 goals. diff -r f6f6db47bd98 src/script/api/script_town.cpp --- a/src/script/api/script_town.cpp Mon Oct 28 11:09:02 2013 +0000 +++ b/src/script/api/script_town.cpp Mon Oct 28 12:29:28 2013 +0100 @@ -154,12 +154,25 @@ } } -/* static */ bool ScriptTown::SetGrowthRate(TownID town_id, uint16 days_between_town_growth) +/* static */ bool ScriptTown::SetGrowthRate(TownID town_id, uint32 days_between_town_growth) { - days_between_town_growth = days_between_town_growth * DAY_TICKS / TOWN_GROWTH_TICKS; + EnforcePrecondition(false, IsValidTown(town_id)); - EnforcePrecondition(false, IsValidTown(town_id)); - EnforcePrecondition(false, (days_between_town_growth & TOWN_GROW_RATE_CUSTOM) == 0); + switch (days_between_town_growth) { + case TOWN_GROWTH_NORMAL: + days_between_town_growth = 0; + break; + + case TOWN_GROWTH_NONE: + days_between_town_growth = TOWN_GROW_RATE_CUSTOM_NONE; + break; + + default: + days_between_town_growth = days_between_town_growth * DAY_TICKS / TOWN_GROWTH_TICKS; + EnforcePrecondition(false, days_between_town_growth < TOWN_GROW_RATE_CUSTOM); + if (days_between_town_growth == 0) days_between_town_growth = 1; + break; + } return ScriptObject::DoCommand(::Town::Get(town_id)->xy, town_id, days_between_town_growth, CMD_TOWN_GROWTH_RATE); } @@ -170,6 +183,8 @@ const Town *t = ::Town::Get(town_id); + if (t->growth_rate == TOWN_GROW_RATE_CUSTOM_NONE) return TOWN_GROWTH_NONE; + return ((t->growth_rate & ~TOWN_GROW_RATE_CUSTOM) * TOWN_GROWTH_TICKS + DAY_TICKS) / DAY_TICKS; } diff -r f6f6db47bd98 src/script/api/script_town.hpp --- a/src/script/api/script_town.hpp Mon Oct 28 11:09:02 2013 +0000 +++ b/src/script/api/script_town.hpp Mon Oct 28 12:29:28 2013 +0100 @@ -117,6 +117,14 @@ }; /** + * Special values for SetGrowthRate. + */ + enum TownGrowth { + TOWN_GROWTH_NONE = 0xFFFF, ///< Town does not grow at all. + TOWN_GROWTH_NORMAL = 0x10000, ///< Use default town growth algorithm instead of custom growth rate. + }; + + /** * Gets the number of towns. * @return The number of towns. */ @@ -249,20 +257,20 @@ /** * Set the amount of days between town growth. * @param town_id The index of the town. - * @param days_between_town_growth The amount of days between town growth. + * @param days_between_town_growth The amount of days between town growth, or TOWN_GROWTH_NONE or TOWN_GROWTH_NORMAL. * @pre IsValidTown(town_id). * @return True if the action succeeded. * @note Even when setting a growth rate, towns only grow when the conditions for growth (SetCargoCoal) are met, * and the game settings (economy.town_growth_rate) allow town growth at all. * @api -ai */ - static bool SetGrowthRate(TownID town_id, uint16 days_between_town_growth); + static bool SetGrowthRate(TownID town_id, uint32 days_between_town_growth); /** * Get the amount of days between town growth. * @param town_id The index of the town. * @pre IsValidTown(town_id). - * @return Amount of days between town growth. + * @return Amount of days between town growth, or TOWN_GROWTH_NONE. * @note This function does not indicate when it will grow next. It only tells you the time between growths. */ static int32 GetGrowthRate(TownID town_id); diff -r f6f6db47bd98 src/town.h --- a/src/town.h Mon Oct 28 11:09:02 2013 +0000 +++ b/src/town.h Mon Oct 28 12:29:28 2013 +0100 @@ -35,7 +35,8 @@ static const uint TOWN_GROWTH_WINTER = 0xFFFFFFFE; ///< The town only needs this cargo in the winter (any amount) static const uint TOWN_GROWTH_DESERT = 0xFFFFFFFF; ///< The town needs the cargo for growth when on desert (any amount) -static const uint16 TOWN_GROW_RATE_CUSTOM = 0x8000; ///< If this mask is applied to Town::grow_counter, the grow_counter will not be calculated by the system (but assumed to be set by scripts) +static const uint16 TOWN_GROW_RATE_CUSTOM = 0x8000; ///< If this mask is applied to Town::growth_rate, the grow_counter will not be calculated by the system (but assumed to be set by scripts) +static const uint16 TOWN_GROW_RATE_CUSTOM_NONE = 0xFFFF; ///< Special value for Town::growth_rate to disable town growth. typedef Pool TownPool; extern TownPool _town_pool; diff -r f6f6db47bd98 src/town_cmd.cpp --- a/src/town_cmd.cpp Mon Oct 28 11:09:02 2013 +0000 +++ b/src/town_cmd.cpp Mon Oct 28 12:29:28 2013 +0100 @@ -2513,14 +2513,14 @@ * @param tile Unused. * @param flags Type of operation. * @param p1 Town ID to cargo game of. - * @param p2 Amount of days between growth. + * @param p2 Amount of days between growth, or TOWN_GROW_RATE_CUSTOM_NONE, or 0 to reset custom growth rate. * @param text Unused. * @return Empty cost or an error. */ CommandCost CmdTownGrowthRate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { if (_current_company != OWNER_DEITY) return CMD_ERROR; - if ((p2 & TOWN_GROW_RATE_CUSTOM) != 0) return CMD_ERROR; + if ((p2 & TOWN_GROW_RATE_CUSTOM) != 0 && p2 != TOWN_GROW_RATE_CUSTOM_NONE) return CMD_ERROR; if (GB(p2, 16, 16) != 0) return CMD_ERROR; Town *t = Town::GetIfValid(p1); @@ -2813,11 +2813,12 @@ if (flags & DC_EXEC) { /* Build next tick */ t->grow_counter = 1; - /* If we were not already growing */ - SetBit(t->flags, TOWN_IS_GROWING); /* And grow for 3 months */ t->fund_buildings_months = 3; + /* Enable growth (also checking GameScript's opinion */ + UpdateTownGrowRate(t); + SetWindowDirty(WC_TOWN_VIEW, t->index); } return CommandCost(); @@ -3035,7 +3036,7 @@ } if ((t->growth_rate & TOWN_GROW_RATE_CUSTOM) != 0) { - SetBit(t->flags, TOWN_IS_GROWING); + if (t->growth_rate != TOWN_GROW_RATE_CUSTOM_NONE) SetBit(t->flags, TOWN_IS_GROWING); SetWindowDirty(WC_TOWN_VIEW, t->index); return; }