tron@2186: /* $Id$ */ tron@2186: KUDr@6307: /** @file town.h */ KUDr@6307: truelight@0: #ifndef TOWN_H truelight@0: #define TOWN_H truelight@0: matthijs@5216: #include "oldpool.h" truelight@0: #include "player.h" KUDr@6303: #include "functions.h" KUDr@6303: #include "helpers.hpp" truelight@0: rubidium@5299: enum { KUDr@6303: HOUSE_NO_CLASS = 0, KUDr@6303: NEW_HOUSE_OFFSET = 110, KUDr@6303: HOUSE_MAX = 512, KUDr@6303: INVALID_TOWN = 0xFFFF, KUDr@6303: INVALID_HOUSE_ID = 0xFFFF, KUDr@6303: KUDr@6303: /* There can only be as many classes as there are new houses, plus one for KUDr@6303: * NO_CLASS, as the original houses don't have classes. */ KUDr@6303: HOUSE_CLASS_MAX = HOUSE_MAX - NEW_HOUSE_OFFSET + 1, KUDr@6303: }; KUDr@6303: KUDr@6303: enum BuildingFlags { KUDr@6303: TILE_NO_FLAG = 0, KUDr@6303: TILE_SIZE_1x1 = 1U << 0, KUDr@6303: TILE_NOT_SLOPED = 1U << 1, KUDr@6303: TILE_SIZE_2x1 = 1U << 2, KUDr@6303: TILE_SIZE_1x2 = 1U << 3, KUDr@6303: TILE_SIZE_2x2 = 1U << 4, KUDr@6303: BUILDING_IS_ANIMATED = 1U << 5, KUDr@6303: BUILDING_IS_CHURCH = 1U << 6, KUDr@6303: BUILDING_IS_STADIUM = 1U << 7, KUDr@6303: BUILDING_HAS_1_TILE = TILE_SIZE_1x1 | TILE_SIZE_2x1 | TILE_SIZE_1x2 | TILE_SIZE_2x2, KUDr@6303: BUILDING_2_TILES_X = TILE_SIZE_2x1 | TILE_SIZE_2x2, KUDr@6303: BUILDING_2_TILES_Y = TILE_SIZE_1x2 | TILE_SIZE_2x2, KUDr@6303: BUILDING_HAS_4_TILES = TILE_SIZE_2x2, KUDr@6303: }; KUDr@6303: KUDr@6303: DECLARE_ENUM_AS_BIT_SET(BuildingFlags) KUDr@6303: KUDr@6303: enum HouseZones { ///< Bit Value Meaning KUDr@6303: HZ_NOZNS = 0x0000, ///< 0 This is just to get rid of zeros, meaning none KUDr@6303: HZ_ZON1 = 0x0001, ///< 0..4 1,2,4,8,10 which town zones the building can be built in, Zone1 been the further suburb KUDr@6303: HZ_ZON2 = 0x0002, KUDr@6303: HZ_ZON3 = 0x0004, KUDr@6303: HZ_ZON4 = 0x0008, KUDr@6303: HZ_ZON5 = 0x0010, ///< center of town KUDr@6303: HZ_ZONALL = 0x001F, ///< 1F This is just to englobe all above types at once KUDr@6303: HZ_SUBARTC_ABOVE = 0x0800, ///< 11 800 can appear in sub-arctic climate above the snow line KUDr@6303: HZ_TEMP = 0x1000, ///< 12 1000 can appear in temperate climate KUDr@6303: HZ_SUBARTC_BELOW = 0x2000, ///< 13 2000 can appear in sub-arctic climate below the snow line KUDr@6303: HZ_SUBTROPIC = 0x4000, ///< 14 4000 can appear in subtropical climate KUDr@6303: HZ_TOYLND = 0x8000 ///< 15 8000 can appear in toyland climate KUDr@6303: }; KUDr@6303: KUDr@6303: DECLARE_ENUM_AS_BIT_SET(HouseZones) KUDr@6303: KUDr@6303: enum HouseExtraFlags { KUDr@6303: NO_EXTRA_FLAG = 0, KUDr@6303: BUILDING_IS_HISTORICAL = 1U << 0, ///< this house will only appear during town generation in random games, thus the historical KUDr@6303: BUILDING_IS_PROTECTED = 1U << 1, ///< towns and AI will not remove this house, while human players will be able tp KUDr@6303: SYNCHRONISED_CALLBACK_1B = 1U << 2, ///< synchronized callback 1B will be performed, on multi tile houses KUDr@6303: CALLBACK_1A_RANDOM_BITS = 1U << 3, ///< callback 1A needs random bits KUDr@6303: }; KUDr@6303: KUDr@6303: DECLARE_ENUM_AS_BIT_SET(HouseExtraFlags) KUDr@6303: KUDr@6303: typedef uint16 HouseID; KUDr@6303: typedef uint16 HouseClassID; KUDr@6303: KUDr@6303: struct BuildingCounts { KUDr@6303: uint8 id_count[HOUSE_MAX]; KUDr@6303: uint8 class_count[HOUSE_CLASS_MAX]; rubidium@5299: }; rubidium@5299: truelight@0: struct Town { truelight@0: TileIndex xy; truelight@0: KUDr@6307: /* Current population of people and amount of houses. */ truelight@0: uint16 num_houses; truelight@0: uint32 population; truelight@193: KUDr@6307: /* Town name */ truelight@0: uint16 townnametype; truelight@0: uint32 townnameparts; truelight@193: KUDr@6307: /* NOSAVE: Location of name sign, UpdateTownVirtCoord updates this. */ truelight@0: ViewportSign sign; truelight@193: KUDr@6307: /* Makes sure we don't build certain house types twice. KUDr@6307: * bit 0 = Building funds received KUDr@6307: * bit 1 = CHURCH KUDr@6307: * bit 2 = STADIUM */ truelight@0: byte flags12; truelight@0: KUDr@6307: /* Which players have a statue? */ truelight@0: byte statues; truelight@0: KUDr@6307: /* Player ratings as well as a mask that determines which players have a rating. */ truelight@0: byte have_ratings; KUDr@6307: uint8 unwanted[MAX_PLAYERS]; ///< how many months companies aren't wanted by towns (bribe) KUDr@6307: PlayerByte exclusivity; ///< which player has exslusivity KUDr@6307: uint8 exclusive_counter; ///< months till the exclusivity expires truelight@0: int16 ratings[MAX_PLAYERS]; truelight@193: KUDr@6307: /* Maximum amount of passengers and mail that can be transported. */ celestar@1377: uint32 max_pass; celestar@1377: uint32 max_mail; celestar@1377: uint32 new_max_pass; celestar@1377: uint32 new_max_mail; celestar@1377: uint32 act_pass; celestar@1377: uint32 act_mail; celestar@1377: uint32 new_act_pass; celestar@1377: uint32 new_act_mail; truelight@0: KUDr@6307: /* Amount of passengers that were transported. */ truelight@0: byte pct_pass_transported; truelight@0: byte pct_mail_transported; truelight@0: KUDr@6307: /* Amount of food and paper that was transported. Actually a bit mask would be enough. */ truelight@0: uint16 act_food; darkvater@4: uint16 act_water; truelight@0: uint16 new_act_food; darkvater@4: uint16 new_act_water; truelight@193: KUDr@6307: /* Time until we rebuild a house. */ KUDr@6307: uint16 time_until_rebuild; truelight@0: KUDr@6307: /* When to grow town next time. */ KUDr@6307: uint16 grow_counter; KUDr@6307: int16 growth_rate; truelight@0: KUDr@6307: /* Fund buildings program in action? */ truelight@0: byte fund_buildings_months; truelight@193: KUDr@6307: /* Fund road reconstruction in action? */ truelight@0: byte road_build_months; truelight@0: KUDr@6307: /* Index in town array */ Darkvater@3346: TownID index; truelight@0: KUDr@6308: /* If this is a larger town, and should grow more quickly. */ KUDr@6308: bool larger_town; KUDr@6308: KUDr@6307: /* NOSAVE: UpdateTownRadius updates this given the house count. */ truelight@0: uint16 radius[5]; KUDr@6303: KUDr@6307: /* NOSAVE: The number of each type of building in the town. */ KUDr@6303: BuildingCounts building_counts; truelight@0: }; truelight@0: KUDr@6303: struct HouseSpec { KUDr@6303: /* Standard properties */ KUDr@6303: Year min_date; ///< introduction year of the house KUDr@6303: Year max_date; ///< last year it can be built KUDr@6303: byte population; ///< population (Zero on other tiles in multi tile house.) KUDr@6303: byte removal_cost; ///< cost multiplier for removing it KUDr@6303: StringID building_name; ///< building name KUDr@6303: uint16 remove_rating_decrease; ///< rating decrease if removed KUDr@6303: byte mail_generation; ///< mail generation multiplier (tile based, as the acceptances below) KUDr@6303: byte cargo_acceptance[3]; ///< acceptance level for the cargo slots KUDr@6303: CargoID accepts_cargo[3]; ///< 3 input cargo slots KUDr@6303: BuildingFlags building_flags; ///< some flags that describe the house (size, stadium etc...) KUDr@6303: HouseZones building_availability; ///< where can it be built (climates, zones) KUDr@6303: bool enabled; ///< the house is still avaible (by default, true.newgrf can disable it, though) KUDr@6303: KUDr@6303: /* NewHouses properties */ KUDr@6303: HouseID substitute_id; ///< which house this one is based on KUDr@6303: struct SpriteGroup *spritegroup; ///< pointer to the different sprites of the house KUDr@6303: HouseID override; ///< which house this one replaces KUDr@6303: uint16 callback_mask; ///< House callback flags KUDr@6303: byte random_colour[4]; ///< 4 "random" colours KUDr@6303: byte probability; ///< Relative probability of appearing (16 is the standard value) KUDr@6303: HouseExtraFlags extra_flags; ///< some more flags KUDr@6303: HouseClassID class_id; ///< defines the class this house has (grf file based) @See HouseGetVariable, prop 0x44 KUDr@6303: byte animation_frames; ///< number of animation frames KUDr@6303: byte animation_speed; ///< amount of time between each of those frames KUDr@6303: byte processing_time; ///< Periodic refresh multiplier KUDr@6303: KUDr@6303: /* grf file related properties*/ KUDr@6303: uint8 local_id; ///< id defined by the grf file for this house KUDr@6303: const struct GRFFile *grffile; ///< grf file that introduced this house KUDr@6303: }; KUDr@6303: KUDr@6308: enum TownSizeMode { KUDr@6308: TSM_RANDOM, KUDr@6308: TSM_FIXED, KUDr@6308: TSM_CITY KUDr@6308: }; KUDr@6308: KUDr@6303: VARDEF HouseSpec _house_specs[HOUSE_MAX]; KUDr@6303: bjarni@6298: uint32 GetWorldPopulation(); truelight@0: truelight@835: void UpdateTownVirtCoord(Town *t); bjarni@6298: void InitializeTown(); Darkvater@3346: void ShowTownViewWindow(TownID town); truelight@0: void ExpandTown(Town *t); KUDr@6308: Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size); truelight@0: truelight@0: enum { truelight@0: ROAD_REMOVE = 0, truelight@0: UNMOVEABLE_REMOVE = 1, truelight@0: TUNNELBRIDGE_REMOVE = 1, truelight@0: INDUSTRY_REMOVE = 2 truelight@0: }; truelight@0: celestar@1005: enum { KUDr@6307: /* These refer to the maximums, so Appalling is -1000 to -400 KUDr@6307: * MAXIMUM RATINGS BOUNDARIES */ belugas@3432: RATING_MINIMUM = -1000, rubidium@4344: RATING_APPALLING = -400, rubidium@4344: RATING_VERYPOOR = -200, rubidium@4344: RATING_POOR = 0, rubidium@4344: RATING_MEDIOCRE = 200, rubidium@4344: RATING_GOOD = 400, rubidium@4344: RATING_VERYGOOD = 600, rubidium@4344: RATING_EXCELLENT = 800, KUDr@6307: RATING_OUTSTANDING = 1000, ///< OUTSTANDING celestar@1005: celestar@1005: RATING_MAXIMUM = RATING_OUTSTANDING, celestar@1005: KUDr@6307: /* RATINGS AFFECTING NUMBERS */ celestar@1005: RATING_TREE_DOWN_STEP = -35, rubidium@4344: RATING_TREE_MINIMUM = RATING_MINIMUM, rubidium@4344: RATING_TREE_UP_STEP = 7, rubidium@4344: RATING_TREE_MAXIMUM = 220, celestar@1005: celestar@1005: RATING_TUNNEL_BRIDGE_DOWN_STEP = -250, rubidium@4344: RATING_TUNNEL_BRIDGE_MINIMUM = 0, celestar@1005: celestar@1005: RATING_INDUSTRY_DOWN_STEP = -1500, rubidium@4344: RATING_INDUSTRY_MINIMUM = RATING_MINIMUM, celestar@1005: celestar@1005: RATING_ROAD_DOWN_STEP = -50, rubidium@4344: RATING_ROAD_MINIMUM = -100, rubidium@4344: RATING_HOUSE_MINIMUM = RATING_MINIMUM, celestar@1005: celestar@1005: RATING_BRIBE_UP_STEP = 200, celestar@1005: RATING_BRIBE_MAXIMUM = 800, belugas@3432: RATING_BRIBE_DOWN_TO = -50 // XXX SHOULD BE SOMETHING LOWER? belugas@3432: }; belugas@3432: KUDr@6307: /** This is the number of ticks between towns being processed for building new KUDr@6307: * houses or roads. This value originally came from the size of the town array KUDr@6307: * in TTD. */ KUDr@6307: static const byte TOWN_GROWTH_FREQUENCY = 70; belugas@3432: KUDr@6307: /** Simple value that indicates the house has reached the final stage of KUDr@6307: * construction. */ KUDr@6307: static const byte TOWN_HOUSE_COMPLETED = 3; KUDr@6307: KUDr@6307: /** This enum is used in conjonction with town->flags12. belugas@3432: * IT simply states what bit is used for. belugas@3432: * It is pretty unrealistic (IMHO) to only have one church/stadium belugas@3432: * per town, NO MATTER the population of it. belugas@3432: * And there are 5 more bits available on flags12... belugas@3432: */ belugas@3432: enum { KUDr@6307: TOWN_IS_FUNDED = 0, ///< Town has received some funds for KUDr@6307: TOWN_HAS_CHURCH = 1, ///< There can be only one church by town. KUDr@6307: TOWN_HAS_STADIUM = 2 ///< There can be only one stadium by town. celestar@1005: }; celestar@1005: tron@2958: bool CheckforTownRating(uint32 flags, Town *t, byte type); truelight@0: tron@4277: VARDEF const Town** _town_sort; truelight@919: matthijs@5216: DECLARE_OLD_POOL(Town, Town, 3, 8000) truelight@1260: KUDr@6303: static inline HouseSpec *GetHouseSpecs(HouseID house_id) KUDr@6303: { KUDr@6303: assert(house_id < HOUSE_MAX); KUDr@6303: return &_house_specs[house_id]; KUDr@6303: } KUDr@6303: truelight@1260: /** matthijs@1330: * Check if a Town really exists. KUDr@6307: * @param town to inquiry KUDr@6307: * @return true if it exists matthijs@1330: */ Darkvater@2436: static inline bool IsValidTown(const Town* town) matthijs@1330: { truelight@4346: return town->xy != 0; matthijs@1330: } matthijs@1330: KUDr@6307: /** KUDr@6307: * Check if a TownID is valid. KUDr@6308: * @param index to inquiry in the pool of town KUDr@6307: * @return true if it exists KUDr@6307: */ rubidium@5299: static inline bool IsValidTownID(TownID index) rubidium@5299: { rubidium@5299: return index < GetTownPoolSize() && IsValidTown(GetTown(index)); rubidium@5299: } rubidium@5299: truelight@4354: VARDEF uint _total_towns; truelight@4354: bjarni@6298: static inline TownID GetMaxTownIndex() truelight@4354: { truelight@4354: /* TODO - This isn't the real content of the function, but truelight@4354: * with the new pool-system this will be replaced with one that matthijs@5247: * _really_ returns the highest index. Now it just returns truelight@4354: * the next safe value we are sure about everything is below. truelight@4354: */ rubidium@5298: return GetTownPoolSize() - 1; matthijs@5247: } matthijs@5247: bjarni@6298: static inline uint GetNumTowns() matthijs@5247: { truelight@4357: return _total_towns; truelight@4354: } truelight@4354: truelight@4356: /** truelight@4356: * Return a random valid town. truelight@4356: */ bjarni@6298: static inline Town *GetRandomTown() truelight@4356: { rubidium@5299: int num = RandomRange(GetNumTowns()); rubidium@5299: TownID index = INVALID_TOWN; truelight@4356: rubidium@5299: while (num >= 0) { truelight@4356: num--; truelight@4356: truelight@4356: index++; rubidium@6233: /* Make sure we have a valid town */ rubidium@5299: while (!IsValidTownID(index)) { truelight@4356: index++; rubidium@5299: assert(index <= GetMaxTownIndex()); truelight@4356: } truelight@4356: } truelight@4356: truelight@4356: return GetTown(index); truelight@4356: } truelight@4356: truelight@4396: void DestroyTown(Town *t); truelight@4396: truelight@4396: static inline void DeleteTown(Town *t) truelight@4396: { truelight@4396: DestroyTown(t); truelight@4396: t->xy = 0; truelight@4396: } truelight@4396: rubidium@6220: Town* CalcClosestTownFromTile(TileIndex tile, uint threshold); rubidium@6220: tron@4983: #define FOR_ALL_TOWNS_FROM(t, start) for (t = GetTown(start); t != NULL; t = (t->index + 1U < GetTownPoolSize()) ? GetTown(t->index + 1U) : NULL) if (IsValidTown(t)) truelight@1260: #define FOR_ALL_TOWNS(t) FOR_ALL_TOWNS_FROM(t, 0) truelight@1260: truelight@0: VARDEF bool _town_sort_dirty; truelight@0: VARDEF byte _town_sort_order; truelight@0: truelight@0: VARDEF Town *_cleared_town; truelight@0: VARDEF int _cleared_town_rating; truelight@0: KUDr@6303: uint OriginalTileRandomiser(uint x, uint y); KUDr@6303: void ResetHouses(); KUDr@6303: KUDr@6303: void ClearTownHouse(Town *t, TileIndex tile); KUDr@6303: truelight@0: #endif /* TOWN_H */