00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef TOWN_H
00013 #define TOWN_H
00014
00015 #include "core/pool_type.hpp"
00016 #include "viewport_type.h"
00017 #include "command_type.h"
00018 #include "town_map.h"
00019 #include "subsidy_type.h"
00020 #include "openttd.h"
00021 #include "table/strings.h"
00022 #include "company_func.h"
00023 #include "landscape.h"
00024 #include "landscape_type.h"
00025
00026 template <typename T>
00027 struct BuildingCounts {
00028 T id_count[HOUSE_MAX];
00029 T class_count[HOUSE_CLASS_MAX];
00030 };
00031
00032 static const uint CUSTOM_TOWN_NUMBER_DIFFICULTY = 4;
00033 static const uint CUSTOM_TOWN_MAX_NUMBER = 5000;
00034
00035 static const uint INVALID_TOWN = 0xFFFF;
00036
00037 typedef Pool<Town, TownID, 64, 64000> TownPool;
00038 extern TownPool _town_pool;
00039
00044 static const uint8 _difficulty_town_needed_for_growth[] = {
00045 2,
00046 2,
00047 3,
00048 4,
00049 5,
00050 6,
00051 10,
00052 };
00053
00055 enum TownNeededForGrowth {
00056 GROWTH_STANDARD,
00057 GROWTH_NEED_STATION,
00058 GROWTH_NEED_MORE_PASS,
00059 GROWTH_NEED_MORE_MAIL,
00060 GROWTH_NEED_MORE_FOOD,
00061 GROWTH_NEED_MORE_WATER,
00062 GROWTH_NEED_MORE_GOODS,
00063 GROWTH_NEED_PASS,
00064 GROWTH_NEED_MAIL,
00065 GROWTH_NEED_FOOD,
00066 GROWTH_NEED_WATER,
00067 GROWTH_NEED_GOODS,
00068 GROWTH_SATISFIED,
00069 };
00070
00072 struct Town : TownPool::PoolItem<&_town_pool> {
00073 TileIndex xy;
00074
00075
00076 uint32 num_houses;
00077 uint32 population;
00078
00079
00080 uint32 townnamegrfid;
00081 uint16 townnametype;
00082 uint32 townnameparts;
00083 char *name;
00084
00085
00086 ViewportSign sign;
00087
00088
00089
00090
00091
00092 byte flags;
00093
00094
00095 uint16 noise_reached;
00096
00097
00098 CompanyMask statues;
00099
00100
00101 CompanyMask have_ratings;
00102 uint8 unwanted[MAX_COMPANIES];
00103 CompanyByte exclusivity;
00104 uint16 exclusive_counter;
00105 int16 ratings[MAX_COMPANIES];
00106 StringID town_label;
00107
00108
00109 uint32 gen_act_pass;
00110 uint32 gen_act_mail;
00111 uint32 gen_max_pass;
00112 uint32 gen_max_mail;
00113 uint32 new_gen_max_pass;
00114 uint32 new_gen_max_mail;
00115 uint16 new_gen_act_pass;
00116 uint16 new_gen_act_mail;
00117
00118
00119 uint32 max_pass;
00120 uint32 max_mail;
00121 uint32 max_food;
00122 uint32 max_water;
00123 uint32 max_goods;
00124 uint32 new_max_pass;
00125 uint32 new_max_mail;
00126 uint32 new_max_food;
00127 uint32 new_max_water;
00128 uint32 new_max_goods;
00129
00130
00131 byte pct_pass_transported;
00132 byte pct_mail_transported;
00133 byte pct_food_transported;
00134 byte pct_water_transported;
00135 byte pct_goods_transported;
00136
00137
00138 uint16 act_pass;
00139 uint16 act_mail;
00140 uint16 act_food;
00141 uint16 act_water;
00142 uint16 act_goods;
00143 uint16 new_act_pass;
00144 uint16 new_act_mail;
00145 uint16 new_act_food;
00146 uint16 new_act_water;
00147 uint16 new_act_goods;
00148
00149
00150 uint16 time_until_rebuild;
00151
00152
00153 uint16 grow_counter;
00154 int16 growth_rate;
00155
00156
00157
00158 uint32 ratio;
00159
00160
00161 byte fund_buildings_months;
00162
00163
00164 byte road_build_months;
00165
00166
00167 bool larger_town;
00168 TownLayoutByte layout;
00169
00170 PartOfSubsidyByte part_of_subsidy;
00171
00172
00173 uint32 squared_town_zone_radius[HZB_END];
00174
00175 BuildingCounts<uint16> building_counts;
00176
00180 Town(TileIndex tile = INVALID_TILE) : xy(tile) { }
00181
00183 ~Town();
00184
00185 void InitializeLayout(TownLayout layout);
00186
00187 void UpdateLabel();
00188
00192 FORCEINLINE StringID Label() const{
00193 if (!(_game_mode == GM_EDITOR) && (_local_company < MAX_COMPANIES)) {
00200 if (_settings_client.gui.population_in_label) {
00201 if (!_settings_client.gui.population_in_label_coloured) {
00202 return STR_VIEWPORT_TOWN_POP;
00203 } else {
00204 return STR_VIEWPORT_TOWN_POP_VERY_POOR_RATING + this->town_label;
00205 }
00206 } else {
00207 return STR_VIEWPORT_TOWN;
00208 }
00209 } else {
00210 return STR_VIEWPORT_TOWN;
00211 }
00212 }
00213
00217 FORCEINLINE StringID SmallLabel() const{
00218 if (!(_game_mode == GM_EDITOR) && (_local_company < MAX_COMPANIES)) {
00226 if (_settings_client.gui.population_in_label_coloured && _settings_client.gui.population_in_label) {
00227 return STR_VIEWPORT_TOWN_TINY_VERY_POOR_RATING + this->town_label;
00228 } else {
00229 return STR_VIEWPORT_TOWN_TINY_WHITE;
00230 }
00231 } else {
00232 return STR_VIEWPORT_TOWN_TINY_WHITE;
00233 }
00234 }
00235
00242 inline uint16 MaxTownNoise() const
00243 {
00244 if (this->population == 0) return 0;
00245
00246
00247 return (this->population / _settings_game.economy.town_noise_population[_settings_game.difficulty.town_council_tolerance]) + 3;
00248 }
00249
00250 void UpdateVirtCoord();
00251
00252 static FORCEINLINE Town *GetByTile(TileIndex tile)
00253 {
00254 return Town::Get(GetTownIndex(tile));
00255 }
00256
00257 static Town *GetRandom();
00258 static void PostDestructor(size_t index);
00259
00260
00261
00262 inline uint16 GrowthRatePercent() const {
00263 int16 default_growth_rate = 320;
00264 uint growth_multiplier = _settings_game.economy.town_growth_rate != 0 ? _settings_game.economy.town_growth_rate - 1 : 1;
00265 default_growth_rate >>= growth_multiplier;
00266 default_growth_rate /= (num_houses / 50 + 1);
00267 if (larger_town) default_growth_rate /= 2;
00268
00269
00270 if (((!larger_town && _settings_game.economy.town_growth_cargo) || (larger_town && _settings_game.economy.larger_town_growth_cargo))&&
00271 ((!larger_town && population > _settings_game.economy.town_pop_need_goods) ||
00272 (larger_town && population > _settings_game.economy.larger_town_pop_need_goods))) {
00273 if ((_settings_game.game_creation.landscape == LT_TEMPERATE ||
00274 _settings_game.game_creation.landscape == LT_TOYLAND ||
00275 (_settings_game.game_creation.landscape == LT_ARCTIC && TilePixelHeight(this->xy) < GetSnowLine()) ||
00276 (_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(this->xy) == TROPICZONE_DESERT)) &&
00277 (act_pass == 0 || act_mail == 0 || act_goods == 0)) {
00278 return 1;
00279 } else if (_settings_game.game_creation.landscape == LT_ARCTIC &&
00280 TilePixelHeight(this->xy) >= GetSnowLine() &&
00281 (act_pass == 0 || act_mail == 0 || act_goods == 0 || act_food == 0)) {
00282 return 1;
00283 } else if (_settings_game.game_creation.landscape == LT_TROPIC &&
00284 GetTropicZone(this->xy) == TROPICZONE_DESERT &&
00285 (act_pass == 0 || act_mail == 0 || act_goods == 0 || act_food == 0|| act_water == 0)) {
00286 return 1;
00287 } else {
00288 return 320 * this->transported_goods_percent / 100;
00289 }
00290 } else {
00291 return (uint16)((1 / (double)growth_rate) * default_growth_rate * 320);
00292 }
00293 }
00294
00295 byte transported_goods_percent;
00296 byte needed_for_growth;
00297 };
00298
00299 uint32 GetWorldPopulation();
00300
00301 void UpdateAllTownVirtCoords();
00302 void ShowTownViewWindow(TownID town);
00303 void ExpandTown(Town *t);
00304
00309 enum TownRatingCheckType {
00310 ROAD_REMOVE = 0,
00311 TUNNELBRIDGE_REMOVE = 1,
00312 TOWN_RATING_CHECK_TYPE_COUNT,
00313 };
00314
00322 enum TownFlags {
00323 TOWN_IS_FUNDED = 0,
00324 TOWN_HAS_CHURCH = 1,
00325 TOWN_HAS_STADIUM = 2
00326 };
00327
00328 CommandCost CheckforTownRating(DoCommandFlag flags, Town *t, TownRatingCheckType type);
00329
00330
00331 TileIndexDiff GetHouseNorthPart(HouseID &house);
00332
00333 Town *CalcClosestTownFromTile(TileIndex tile, uint threshold = UINT_MAX);
00334
00335 #define FOR_ALL_TOWNS_FROM(var, start) FOR_ALL_ITEMS_FROM(Town, town_index, var, start)
00336 #define FOR_ALL_TOWNS(var) FOR_ALL_TOWNS_FROM(var, 0)
00337
00338 void ResetHouses();
00339
00340 void ClearTownHouse(Town *t, TileIndex tile);
00341 void UpdateTownGenCargo(Town *t);
00342 void UpdateTownDemands(Town *t);
00343 void UpdateTownRadius(Town *t);
00344 CommandCost CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlag flags);
00345 Town *ClosestTownFromTile(TileIndex tile, uint threshold);
00346 void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags);
00347 HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile);
00348 void SetTownRatingTestMode(bool mode);
00349 uint GetMaskOfTownActions(int *nump, CompanyID cid, const Town *t);
00350 bool GenerateTowns(TownLayout layout);
00351
00353 enum TownActions {
00354 TACT_NONE = 0x00,
00355
00356 TACT_ADVERTISE_SMALL = 0x01,
00357 TACT_ADVERTISE_MEDIUM = 0x02,
00358 TACT_ADVERTISE_LARGE = 0x04,
00359 TACT_ROAD_REBUILD = 0x08,
00360 TACT_BUILD_STATUE = 0x10,
00361 TACT_FOUND_BUILDINGS = 0x20,
00362 TACT_BUY_RIGHTS = 0x40,
00363 TACT_BRIBE = 0x80,
00364
00365 TACT_COUNT = 8,
00366
00367 TACT_ADVERTISE = TACT_ADVERTISE_SMALL | TACT_ADVERTISE_MEDIUM | TACT_ADVERTISE_LARGE,
00368 TACT_CONSTRUCTION = TACT_ROAD_REBUILD | TACT_BUILD_STATUE | TACT_FOUND_BUILDINGS,
00369 TACT_FUNDS = TACT_BUY_RIGHTS | TACT_BRIBE,
00370 TACT_ALL = TACT_ADVERTISE | TACT_CONSTRUCTION | TACT_FUNDS,
00371 };
00372 DECLARE_ENUM_AS_BIT_SET(TownActions)
00373
00374 extern const byte _town_action_costs[TACT_COUNT];
00375 extern TownID _new_town_id;
00376
00382 template <class T>
00383 void MakeDefaultName(T *obj)
00384 {
00385
00386 assert(obj->name == NULL || obj->town_cn == UINT16_MAX);
00387
00388 obj->town = ClosestTownFromTile(obj->xy, UINT_MAX);
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 uint32 used = 0;
00402 uint32 next = 0;
00403 uint32 idx = 0;
00404 uint32 cid = 0;
00405
00406 do {
00407 T *lobj = T::GetIfValid(cid);
00408
00409
00410 if (lobj != NULL && obj != lobj) {
00411
00412 if (lobj->town == obj->town && lobj->IsOfType(obj)) {
00413
00414 uint i = (uint)lobj->town_cn - next;
00415
00416 if (i < 32) {
00417 SetBit(used, i);
00418 if (i == 0) {
00419
00420
00421 do {
00422 used >>= 1;
00423 next++;
00424 } while (HasBit(used, 0));
00425
00426
00427
00428 idx = cid;
00429 }
00430 }
00431 }
00432 }
00433
00434 cid++;
00435 if (cid == T::GetPoolSize()) cid = 0;
00436 } while (cid != idx);
00437
00438 obj->town_cn = (uint16)next;
00439 }
00440
00441 #endif