38 #include "newgrf.h" |
38 #include "newgrf.h" |
39 #include "newgrf_callbacks.h" |
39 #include "newgrf_callbacks.h" |
40 #include "newgrf_house.h" |
40 #include "newgrf_house.h" |
41 #include "newgrf_commons.h" |
41 #include "newgrf_commons.h" |
42 #include "newgrf_townname.h" |
42 #include "newgrf_townname.h" |
43 |
43 #include "misc/autoptr.hpp" |
44 /** |
|
45 * Called if a new block is added to the town-pool |
|
46 */ |
|
47 static void TownPoolNewBlock(uint start_item) |
|
48 { |
|
49 Town *t; |
|
50 |
|
51 /* We don't use FOR_ALL here, because FOR_ALL skips invalid items. |
|
52 * TODO - This is just a temporary stage, this will be removed. */ |
|
53 for (t = GetTown(start_item); t != NULL; t = (t->index + 1U < GetTownPoolSize()) ? GetTown(t->index + 1U) : NULL) t->index = start_item++; |
|
54 } |
|
55 |
44 |
56 /* Initialize the town-pool */ |
45 /* Initialize the town-pool */ |
57 DEFINE_OLD_POOL(Town, Town, TownPoolNewBlock, NULL) |
46 DEFINE_OLD_POOL_GENERIC(Town, Town) |
58 |
47 |
59 /** |
48 Town::Town(TileIndex tile) |
60 * Removes a specific town as well as all industries |
49 { |
61 * under its "juridiction" |
50 this->xy = tile; |
62 * @param t Town to remove |
51 } |
63 */ |
52 |
64 void DestroyTown(Town *t) |
53 Town::~Town() |
65 { |
54 { |
66 Industry *i; |
55 Industry *i; |
67 TileIndex tile; |
|
68 |
56 |
69 /* Delete town authority window |
57 /* Delete town authority window |
70 * and remove from list of sorted towns */ |
58 * and remove from list of sorted towns */ |
71 DeleteWindowById(WC_TOWN_VIEW, t->index); |
59 DeleteWindowById(WC_TOWN_VIEW, this->index); |
72 _town_sort_dirty = true; |
60 _town_sort_dirty = true; |
73 _total_towns--; |
61 _total_towns--; |
74 |
62 |
75 /* Delete all industries belonging to the town */ |
63 /* Delete all industries belonging to the town */ |
76 FOR_ALL_INDUSTRIES(i) if (i->town == t) DeleteIndustry(i); |
64 FOR_ALL_INDUSTRIES(i) if (i->town == this) delete i; |
77 |
65 |
78 /* Go through all tiles and delete those belonging to the town */ |
66 /* Go through all tiles and delete those belonging to the town */ |
79 for (tile = 0; tile < MapSize(); ++tile) { |
67 for (TileIndex tile = 0; tile < MapSize(); ++tile) { |
80 switch (GetTileType(tile)) { |
68 switch (GetTileType(tile)) { |
81 case MP_HOUSE: |
69 case MP_HOUSE: |
82 if (GetTownByTile(tile) == t) DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
70 if (GetTownByTile(tile) == this) DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
83 break; |
71 break; |
84 |
72 |
85 case MP_STREET: |
73 case MP_ROAD: |
86 case MP_TUNNELBRIDGE: |
74 case MP_TUNNELBRIDGE: |
87 if (IsTileOwner(tile, OWNER_TOWN) && |
75 if (IsTileOwner(tile, OWNER_TOWN) && |
88 ClosestTownFromTile(tile, (uint)-1) == t) |
76 ClosestTownFromTile(tile, (uint)-1) == this) |
89 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
77 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
90 break; |
78 break; |
91 |
79 |
92 default: |
80 default: |
93 break; |
81 break; |
94 } |
82 } |
95 } |
83 } |
96 |
84 |
97 DeleteName(t->townnametype); |
85 DeleteSubsidyWithTown(this->index); |
98 DeleteSubsidyWithTown(t->index); |
|
99 |
86 |
100 MarkWholeScreenDirty(); |
87 MarkWholeScreenDirty(); |
|
88 |
|
89 this->QuickFree(); |
|
90 this->xy = 0; |
|
91 } |
|
92 |
|
93 void Town::QuickFree() |
|
94 { |
|
95 DeleteName(this->townnametype); |
101 } |
96 } |
102 |
97 |
103 // Local |
98 // Local |
104 static int _grow_town_result; |
99 static int _grow_town_result; |
105 |
100 |
152 } |
147 } |
153 |
148 |
154 /* Retrieve pointer to the draw town tile struct */ |
149 /* Retrieve pointer to the draw town tile struct */ |
155 dcts = &_town_draw_tile_data[house_id << 4 | OriginalTileRandomiser(ti->x, ti->y) << 2 | GetHouseBuildingStage(ti->tile)]; |
150 dcts = &_town_draw_tile_data[house_id << 4 | OriginalTileRandomiser(ti->x, ti->y) << 2 | GetHouseBuildingStage(ti->tile)]; |
156 |
151 |
157 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh); |
152 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED); |
158 |
153 |
159 image = dcts->ground.sprite; |
154 image = dcts->ground.sprite; |
160 pal = dcts->ground.pal; |
155 pal = dcts->ground.pal; |
161 DrawGroundSprite(image, pal); |
156 DrawGroundSprite(image, pal); |
162 |
157 |
163 /* Add a house on top of the ground? */ |
158 /* Add a house on top of the ground? */ |
164 image = dcts->building.sprite; |
159 image = dcts->building.sprite; |
165 if (image != 0) { |
160 if (image != 0) { |
166 if (HASBIT(_transparent_opt, TO_HOUSES)) { |
161 AddSortableSpriteToDraw(image, dcts->building.pal, |
167 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
|
168 pal = PALETTE_TO_TRANSPARENT; |
|
169 } else { |
|
170 pal = dcts->building.pal; |
|
171 } |
|
172 |
|
173 AddSortableSpriteToDraw(image, pal, |
|
174 ti->x + dcts->subtile_x, |
162 ti->x + dcts->subtile_x, |
175 ti->y + dcts->subtile_y, |
163 ti->y + dcts->subtile_y, |
176 dcts->width + 1, |
164 dcts->width + 1, |
177 dcts->height + 1, |
165 dcts->height + 1, |
178 dcts->dz, |
166 dcts->dz, |
179 ti->z |
167 ti->z, |
|
168 HASBIT(_transparent_opt, TO_HOUSES) |
180 ); |
169 ); |
181 |
170 |
182 if (HASBIT(_transparent_opt, TO_HOUSES)) return; |
171 if (HASBIT(_transparent_opt, TO_HOUSES)) return; |
183 } |
172 } |
184 |
173 |
1155 /* Select a random bit from the blockmask, walk a step |
1144 /* Select a random bit from the blockmask, walk a step |
1156 * and continue the search from there. */ |
1145 * and continue the search from there. */ |
1157 do block = Random() & 3; while (!HASBIT(mask, block)); |
1146 do block = Random() & 3; while (!HASBIT(mask, block)); |
1158 tile += ToTileIndexDiff(_roadblock_tileadd[block]); |
1147 tile += ToTileIndexDiff(_roadblock_tileadd[block]); |
1159 |
1148 |
1160 if (IsTileType(tile, MP_STREET)) { |
1149 if (IsTileType(tile, MP_ROAD)) { |
1161 /* Don't allow building over roads of other cities */ |
1150 /* Don't allow building over roads of other cities */ |
1162 if (IsTileOwner(tile, OWNER_TOWN) && GetTownByTile(tile) != t) { |
1151 if (IsTileOwner(tile, OWNER_TOWN) && GetTownByTile(tile) != t) { |
1163 _grow_town_result = -1; |
1152 _grow_town_result = -1; |
1164 } else if (_game_mode == GM_EDITOR) { |
1153 } else if (_game_mode == GM_EDITOR) { |
1165 /* If we are in the SE, and this road-piece has no town owner yet, it just found an |
1154 /* If we are in the SE, and this road-piece has no town owner yet, it just found an |
1450 t->num_houses -= x; |
1435 t->num_houses -= x; |
1451 UpdateTownRadius(t); |
1436 UpdateTownRadius(t); |
1452 UpdateTownMaxPass(t); |
1437 UpdateTownMaxPass(t); |
1453 } |
1438 } |
1454 |
1439 |
1455 static Town *AllocateTown() |
|
1456 { |
|
1457 Town *t; |
|
1458 |
|
1459 /* We don't use FOR_ALL here, because FOR_ALL skips invalid items. |
|
1460 * TODO - This is just a temporary stage, this will be removed. */ |
|
1461 for (t = GetTown(0); t != NULL; t = (t->index + 1U < GetTownPoolSize()) ? GetTown(t->index + 1U) : NULL) { |
|
1462 if (!IsValidTown(t)) { |
|
1463 TownID index = t->index; |
|
1464 |
|
1465 memset(t, 0, sizeof(Town)); |
|
1466 t->index = index; |
|
1467 |
|
1468 return t; |
|
1469 } |
|
1470 } |
|
1471 |
|
1472 /* Check if we can add a block to the pool */ |
|
1473 if (AddBlockToPool(&_Town_pool)) |
|
1474 return AllocateTown(); |
|
1475 |
|
1476 return NULL; |
|
1477 } |
|
1478 |
|
1479 /** Create a new town. |
1440 /** Create a new town. |
1480 * This obviously only works in the scenario editor. Function not removed |
1441 * This obviously only works in the scenario editor. Function not removed |
1481 * as it might be possible in the future to fund your own town :) |
1442 * as it might be possible in the future to fund your own town :) |
1482 * @param tile coordinates where town is built |
1443 * @param tile coordinates where town is built |
1483 * @param flags type of operation |
1444 * @param flags type of operation |
1484 * @param p1 size of the town (0 = small, 1 = medium, 2 = large) |
1445 * @param p1 size of the town (0 = small, 1 = medium, 2 = large) |
1485 * @param p2 size mode (@see TownSizeMode) |
1446 * @param p2 size mode (@see TownSizeMode) |
1486 */ |
1447 */ |
1487 CommandCost CmdBuildTown(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1448 CommandCost CmdBuildTown(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1488 { |
1449 { |
1489 Town *t; |
|
1490 uint32 townnameparts; |
1450 uint32 townnameparts; |
1491 |
1451 |
1492 /* Only in the scenario editor */ |
1452 /* Only in the scenario editor */ |
1493 if (_game_mode != GM_EDITOR) return CMD_ERROR; |
1453 if (_game_mode != GM_EDITOR) return CMD_ERROR; |
1494 if (p2 > TSM_CITY) return CMD_ERROR; |
1454 if (p2 > TSM_CITY) return CMD_ERROR; |
1511 /* Get a unique name for the town. */ |
1471 /* Get a unique name for the town. */ |
1512 if (!CreateTownName(&townnameparts)) |
1472 if (!CreateTownName(&townnameparts)) |
1513 return_cmd_error(STR_023A_TOO_MANY_TOWNS); |
1473 return_cmd_error(STR_023A_TOO_MANY_TOWNS); |
1514 |
1474 |
1515 /* Allocate town struct */ |
1475 /* Allocate town struct */ |
1516 t = AllocateTown(); |
1476 Town *t = new Town(tile); |
1517 if (t == NULL) return_cmd_error(STR_023A_TOO_MANY_TOWNS); |
1477 if (t == NULL) return_cmd_error(STR_023A_TOO_MANY_TOWNS); |
|
1478 AutoPtrT<Town> t_auto_delete = t; |
1518 |
1479 |
1519 /* Create the town */ |
1480 /* Create the town */ |
1520 if (flags & DC_EXEC) { |
1481 if (flags & DC_EXEC) { |
1521 _generating_world = true; |
1482 _generating_world = true; |
1522 DoCreateTown(t, tile, townnameparts, (TownSizeMode)p2, p1); |
1483 DoCreateTown(t, tile, townnameparts, (TownSizeMode)p2, p1); |
1523 _generating_world = false; |
1484 _generating_world = false; |
|
1485 t_auto_delete.Detach(); |
1524 } |
1486 } |
1525 return CommandCost(); |
1487 return CommandCost(); |
1526 } |
1488 } |
1527 |
1489 |
1528 Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size) |
1490 Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size) |
2237 |
2199 |
2238 |
2200 |
2239 Town *ClosestTownFromTile(TileIndex tile, uint threshold) |
2201 Town *ClosestTownFromTile(TileIndex tile, uint threshold) |
2240 { |
2202 { |
2241 if (IsTileType(tile, MP_HOUSE) || ( |
2203 if (IsTileType(tile, MP_HOUSE) || ( |
2242 IsTileType(tile, MP_STREET) && |
2204 IsTileType(tile, MP_ROAD) && |
2243 GetRoadOwner(tile, ROADTYPE_ROAD) == OWNER_TOWN |
2205 GetRoadOwner(tile, ROADTYPE_ROAD) == OWNER_TOWN |
2244 )) { |
2206 )) { |
2245 return GetTownByTile(tile); |
2207 return GetTownByTile(tile); |
2246 } else { |
2208 } else { |
2247 return CalcClosestTownFromTile(tile, threshold); |
2209 return CalcClosestTownFromTile(tile, threshold); |
2328 void InitializeTowns() |
2290 void InitializeTowns() |
2329 { |
2291 { |
2330 Subsidy *s; |
2292 Subsidy *s; |
2331 |
2293 |
2332 /* Clean the town pool and create 1 block in it */ |
2294 /* Clean the town pool and create 1 block in it */ |
2333 CleanPool(&_Town_pool); |
2295 _Town_pool.CleanPool(); |
2334 AddBlockToPool(&_Town_pool); |
2296 _Town_pool.AddBlockToPool(); |
2335 |
2297 |
2336 memset(_subsidies, 0, sizeof(_subsidies)); |
2298 memset(_subsidies, 0, sizeof(_subsidies)); |
2337 for (s=_subsidies; s != endof(_subsidies); s++) |
2299 for (s=_subsidies; s != endof(_subsidies); s++) |
2338 s->cargo_type = CT_INVALID; |
2300 s->cargo_type = CT_INVALID; |
2339 |
2301 |
2354 AnimateTile_Town, /* animate_tile_proc */ |
2316 AnimateTile_Town, /* animate_tile_proc */ |
2355 TileLoop_Town, /* tile_loop_clear */ |
2317 TileLoop_Town, /* tile_loop_clear */ |
2356 ChangeTileOwner_Town, /* change_tile_owner_clear */ |
2318 ChangeTileOwner_Town, /* change_tile_owner_clear */ |
2357 NULL, /* get_produced_cargo_proc */ |
2319 NULL, /* get_produced_cargo_proc */ |
2358 NULL, /* vehicle_enter_tile_proc */ |
2320 NULL, /* vehicle_enter_tile_proc */ |
2359 GetSlopeTileh_Town, /* get_slope_tileh_proc */ |
2321 GetFoundation_Town, /* get_foundation_proc */ |
2360 }; |
2322 }; |
2361 |
2323 |
2362 |
2324 |
2363 /** Save and load of towns. */ |
2325 /** Save and load of towns. */ |
2364 static const SaveLoad _town_desc[] = { |
2326 static const SaveLoad _town_desc[] = { |