232 MarkTileDirtyByTile(tile); |
249 MarkTileDirtyByTile(tile); |
233 } |
250 } |
234 |
251 |
235 static void UpdateTownRadius(Town *t); |
252 static void UpdateTownRadius(Town *t); |
236 |
253 |
|
254 /** |
|
255 * Determines if a town is close to a tile |
|
256 * @param tile TileIndex of the tile to query |
|
257 * @param dist maximum distance to be accepted |
|
258 * @returns true if the tile correspond to the distance criteria |
|
259 */ |
237 static bool IsCloseToTown(TileIndex tile, uint dist) |
260 static bool IsCloseToTown(TileIndex tile, uint dist) |
238 { |
261 { |
239 const Town* t; |
262 const Town* t; |
240 |
263 |
241 FOR_ALL_TOWNS(t) { |
264 FOR_ALL_TOWNS(t) { |
242 if (DistanceManhattan(tile, t->xy) < dist) return true; |
265 if (DistanceManhattan(tile, t->xy) < dist) return true; |
243 } |
266 } |
244 return false; |
267 return false; |
245 } |
268 } |
246 |
269 |
|
270 /** |
|
271 * Marks the town sign as needing a repaint |
|
272 * @param t Town requesting repaint |
|
273 */ |
247 static void MarkTownSignDirty(Town *t) |
274 static void MarkTownSignDirty(Town *t) |
248 { |
275 { |
249 MarkAllViewportsDirty( |
276 MarkAllViewportsDirty( |
250 t->sign.left - 6, |
277 t->sign.left - 6, |
251 t->sign.top - 3, |
278 t->sign.top - 3, |
252 t->sign.left + t->sign.width_1 * 4 + 12, |
279 t->sign.left + t->sign.width_1 * 4 + 12, |
253 t->sign.top + 45 |
280 t->sign.top + 45 |
254 ); |
281 ); |
255 } |
282 } |
256 |
283 |
|
284 /** |
|
285 * Resize the sign(label) of the town after changes in |
|
286 * population (creation or growth or else) |
|
287 * @param t Town to update |
|
288 */ |
257 void UpdateTownVirtCoord(Town *t) |
289 void UpdateTownVirtCoord(Town *t) |
258 { |
290 { |
259 Point pt; |
291 Point pt; |
260 |
292 |
261 MarkTownSignDirty(t); |
293 MarkTownSignDirty(t); |
265 UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24, |
297 UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24, |
266 _patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL); |
298 _patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL); |
267 MarkTownSignDirty(t); |
299 MarkTownSignDirty(t); |
268 } |
300 } |
269 |
301 |
|
302 /** |
|
303 * Change the towns population |
|
304 * @param t Town which polulation has changed |
|
305 * @param mod polulation change (can be positive or negative) |
|
306 */ |
270 static void ChangePopulation(Town *t, int mod) |
307 static void ChangePopulation(Town *t, int mod) |
271 { |
308 { |
272 t->population += mod; |
309 t->population += mod; |
273 InvalidateWindow(WC_TOWN_VIEW, t->index); |
310 InvalidateWindow(WC_TOWN_VIEW, t->index); |
274 UpdateTownVirtCoord(t); |
311 UpdateTownVirtCoord(t); |
275 |
312 |
276 if (_town_sort_order & 2) _town_sort_dirty = true; |
313 if (_town_sort_order & 2) _town_sort_dirty = true; |
277 } |
314 } |
278 |
315 |
|
316 /** |
|
317 * Determines the world population |
|
318 * Basically, count population of all towns, one by one |
|
319 * @return uint32 the calculated population of the world |
|
320 */ |
279 uint32 GetWorldPopulation() |
321 uint32 GetWorldPopulation() |
280 { |
322 { |
281 uint32 pop; |
323 uint32 pop; |
282 const Town* t; |
324 const Town* t; |
283 |
325 |
284 pop = 0; |
326 pop = 0; |
285 FOR_ALL_TOWNS(t) pop += t->population; |
327 FOR_ALL_TOWNS(t) pop += t->population; |
286 return pop; |
328 return pop; |
287 } |
329 } |
288 |
330 |
|
331 /** |
|
332 * Helper function for house completion stages progression |
|
333 * @param tile TileIndex of the house (or parts of it) to "grow" |
|
334 */ |
289 static void MakeSingleHouseBigger(TileIndex tile) |
335 static void MakeSingleHouseBigger(TileIndex tile) |
290 { |
336 { |
291 assert(IsTileType(tile, MP_HOUSE)); |
337 assert(IsTileType(tile, MP_HOUSE)); |
292 |
338 |
|
339 /* means it is completed, get out. */ |
293 if (LiftHasDestination(tile)) return; |
340 if (LiftHasDestination(tile)) return; |
294 |
341 |
|
342 /* progress in construction stages */ |
295 IncHouseConstructionTick(tile); |
343 IncHouseConstructionTick(tile); |
296 if (GetHouseConstructionTick(tile) != 0) return; |
344 if (GetHouseConstructionTick(tile) != 0) return; |
297 |
345 |
|
346 /* Check and/or */ |
298 if (HASBIT(GetHouseSpecs(GetHouseType(tile))->callback_mask, CBM_CONSTRUCTION_STATE_CHANGE)) { |
347 if (HASBIT(GetHouseSpecs(GetHouseType(tile))->callback_mask, CBM_CONSTRUCTION_STATE_CHANGE)) { |
299 uint16 callback_res = GetHouseCallback(CBID_CONSTRUCTION_STATE_CHANGE, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
348 uint16 callback_res = GetHouseCallback(CBID_CONSTRUCTION_STATE_CHANGE, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
300 if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res); |
349 if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res); |
301 } |
350 } |
302 |
351 |
303 if (IsHouseCompleted(tile)) { |
352 if (IsHouseCompleted(tile)) { |
304 /* Now that construction is complete, we can add the population of the |
353 /* Now that construction is complete, we can add the population of the |
306 ChangePopulation(GetTownByTile(tile), GetHouseSpecs(GetHouseType(tile))->population); |
355 ChangePopulation(GetTownByTile(tile), GetHouseSpecs(GetHouseType(tile))->population); |
307 } |
356 } |
308 MarkTileDirtyByTile(tile); |
357 MarkTileDirtyByTile(tile); |
309 } |
358 } |
310 |
359 |
|
360 /** Make the house advances in its construction stages until completion |
|
361 * @param tile TileIndex of house |
|
362 */ |
311 static void MakeTownHouseBigger(TileIndex tile) |
363 static void MakeTownHouseBigger(TileIndex tile) |
312 { |
364 { |
313 uint flags = GetHouseSpecs(GetHouseType(tile))->building_flags; |
365 uint flags = GetHouseSpecs(GetHouseType(tile))->building_flags; |
314 if (flags & BUILDING_HAS_1_TILE) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0)); |
366 if (flags & BUILDING_HAS_1_TILE) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0)); |
315 if (flags & BUILDING_2_TILES_Y) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1)); |
367 if (flags & BUILDING_2_TILES_Y) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1)); |
316 if (flags & BUILDING_2_TILES_X) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0)); |
368 if (flags & BUILDING_2_TILES_X) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0)); |
317 if (flags & BUILDING_HAS_4_TILES) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1)); |
369 if (flags & BUILDING_HAS_4_TILES) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1)); |
318 } |
370 } |
319 |
371 |
|
372 /** |
|
373 * Periodic tic handler for houses and town |
|
374 * @param tile been asked to do its stuff |
|
375 */ |
320 static void TileLoop_Town(TileIndex tile) |
376 static void TileLoop_Town(TileIndex tile) |
321 { |
377 { |
322 Town *t; |
378 Town *t; |
323 uint32 r; |
379 uint32 r; |
324 HouseID house_id = GetHouseType(tile); |
380 HouseID house_id = GetHouseType(tile); |
333 MakeTownHouseBigger(tile); |
389 MakeTownHouseBigger(tile); |
334 return; |
390 return; |
335 } |
391 } |
336 |
392 |
337 /* If the lift has a destination, it is already an animated tile. */ |
393 /* If the lift has a destination, it is already an animated tile. */ |
338 if ((hs->building_flags & BUILDING_IS_ANIMATED) && house_id < NEW_HOUSE_OFFSET && !LiftHasDestination(tile) && CHANCE16(1, 2)) AddAnimatedTile(tile); |
394 if ((hs->building_flags & BUILDING_IS_ANIMATED) && |
|
395 house_id < NEW_HOUSE_OFFSET && |
|
396 !LiftHasDestination(tile) && |
|
397 CHANCE16(1, 2)) |
|
398 AddAnimatedTile(tile); |
339 |
399 |
340 t = GetTownByTile(tile); |
400 t = GetTownByTile(tile); |
341 |
401 |
342 r = Random(); |
402 r = Random(); |
343 |
403 |
344 if (GB(r, 0, 8) < (t->GetActivity() * _eco->GetActivity() * 8)) { |
404 if (HASBIT(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) { |
345 int amt = hs->population / 8 + 1; |
405 /** @todo Implement economic activity here as well */ |
346 t->new_max_pass += amt; |
406 for (uint i = 0; i < 256; i++) { |
347 int moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt); |
407 uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, r, house_id, t, tile); |
348 t->new_act_pass += moved; |
408 |
349 } |
409 if (callback == CALLBACK_FAILED) break; |
350 |
410 if (callback == 0x20FF) break; |
351 if (GB(r, 8, 8) < (t->GetActivity() * _eco->GetActivity() * 8)) { |
411 |
352 int amt = hs->mail_generation / 8 + 1; |
412 CargoID cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grffile); |
353 t->new_max_pass += amt; |
413 if (cargo == CT_INVALID) continue; |
354 int moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt); |
414 |
355 t->new_act_pass += moved; |
415 uint amt = GB(callback, 0, 8); |
|
416 uint moved = MoveGoodsToStation(tile, 1, 1, cargo, amt); |
|
417 |
|
418 const CargoSpec *cs = GetCargo(cargo); |
|
419 switch (cs->town_effect) { |
|
420 case TE_PASSENGERS: |
|
421 t->new_max_pass += amt; |
|
422 t->new_act_pass += moved; |
|
423 break; |
|
424 |
|
425 case TE_MAIL: |
|
426 t->new_max_mail += amt; |
|
427 t->new_act_mail += moved; |
|
428 break; |
|
429 |
|
430 default: |
|
431 break; |
|
432 } |
|
433 } |
|
434 } else { |
|
435 if (GB(r, 0, 8) < (t->GetActivity() * _eco->GetActivity() * 8)) { |
|
436 int amt = hs->population / 8 + 1; |
|
437 t->new_max_pass += amt; |
|
438 int moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt); |
|
439 t->new_act_pass += moved; |
|
440 } |
|
441 |
|
442 if (GB(r, 8, 8) < (t->GetActivity() * _eco->GetActivity() * 8)) { |
|
443 int amt = hs->mail_generation / 8 + 1; |
|
444 t->new_max_pass += amt; |
|
445 int moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt); |
|
446 t->new_act_pass += moved; |
|
447 } |
356 } |
448 } |
357 |
449 |
358 _current_player = OWNER_TOWN; |
450 _current_player = OWNER_TOWN; |
359 |
451 |
360 if (hs->building_flags & BUILDING_HAS_1_TILE && HASBIT(t->flags12, TOWN_IS_FUNDED) && CanDeleteHouse(tile) && --t->time_until_rebuild == 0) { |
452 if (hs->building_flags & BUILDING_HAS_1_TILE && |
|
453 HASBIT(t->flags12, TOWN_IS_FUNDED) && |
|
454 CanDeleteHouse(tile) && |
|
455 max(_cur_year - GetHouseConstructionYear(tile), 0) >= hs->minimum_life && |
|
456 --t->time_until_rebuild == 0) { |
361 t->time_until_rebuild = GB(r, 16, 8) + 192; |
457 t->time_until_rebuild = GB(r, 16, 8) + 192; |
362 |
458 |
363 ClearTownHouse(t, tile); |
459 ClearTownHouse(t, tile); |
364 |
460 |
365 /* Rebuild with another house? */ |
461 /* Rebuild with another house? */ |
406 } |
506 } |
407 |
507 |
408 static void GetAcceptedCargo_Town(TileIndex tile, AcceptedCargo ac) |
508 static void GetAcceptedCargo_Town(TileIndex tile, AcceptedCargo ac) |
409 { |
509 { |
410 HouseSpec *hs = GetHouseSpecs(GetHouseType(tile)); |
510 HouseSpec *hs = GetHouseSpecs(GetHouseType(tile)); |
411 |
511 CargoID accepts[3]; |
412 for (uint8 i = 0; i < 3; i++) ac[hs->accepts_cargo[i]] = hs->cargo_acceptance[i]; |
512 |
|
513 /* Set the initial accepted cargo types */ |
|
514 for (uint8 i = 0; i < lengthof(accepts); i++) { |
|
515 accepts[i] = hs->accepts_cargo[i]; |
|
516 } |
|
517 |
|
518 /* Check for custom accepted cargo types */ |
|
519 if (HASBIT(hs->callback_mask, CBM_HOUSE_ACCEPT_CARGO)) { |
|
520 uint16 callback = GetHouseCallback(CBID_HOUSE_ACCEPT_CARGO, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
|
521 if (callback != CALLBACK_FAILED) { |
|
522 /* Replace accepted cargo types with translated values from callback */ |
|
523 accepts[0] = GetCargoTranslation(GB(callback, 0, 5), hs->grffile); |
|
524 accepts[1] = GetCargoTranslation(GB(callback, 5, 5), hs->grffile); |
|
525 accepts[2] = GetCargoTranslation(GB(callback, 10, 5), hs->grffile); |
|
526 } |
|
527 } |
|
528 |
|
529 /* Check for custom cargo acceptance */ |
|
530 if (HASBIT(hs->callback_mask, CBM_CARGO_ACCEPTANCE)) { |
|
531 uint16 callback = GetHouseCallback(CBID_HOUSE_CARGO_ACCEPTANCE, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
|
532 if (callback != CALLBACK_FAILED) { |
|
533 if (accepts[0] != CT_INVALID) ac[accepts[0]] = GB(callback, 0, 4); |
|
534 if (accepts[1] != CT_INVALID) ac[accepts[1]] = GB(callback, 4, 4); |
|
535 if (_opt.landscape != LT_TEMPERATE && HASBIT(callback, 12)) { |
|
536 /* The 'S' bit indicates food instead of goods */ |
|
537 ac[CT_FOOD] = GB(callback, 8, 4); |
|
538 } else { |
|
539 if (accepts[2] != CT_INVALID) ac[accepts[2]] = GB(callback, 8, 4); |
|
540 } |
|
541 return; |
|
542 } |
|
543 } |
|
544 |
|
545 /* No custom acceptance, so fill in with the default values */ |
|
546 for (uint8 i = 0; i < lengthof(accepts); i++) { |
|
547 if (accepts[i] != CT_INVALID) ac[accepts[i]] = hs->cargo_acceptance[i]; |
|
548 } |
413 } |
549 } |
414 |
550 |
415 static void GetTileDesc_Town(TileIndex tile, TileDesc *td) |
551 static void GetTileDesc_Town(TileIndex tile, TileDesc *td) |
416 { |
552 { |
417 td->str = GetHouseSpecs(GetHouseType(tile))->building_name; |
553 td->str = GetHouseSpecs(GetHouseType(tile))->building_name; |
498 if (b & TRACK_BIT_LEFT) r |= ROAD_NW | ROAD_SW; |
642 if (b & TRACK_BIT_LEFT) r |= ROAD_NW | ROAD_SW; |
499 if (b & TRACK_BIT_RIGHT) r |= ROAD_NE | ROAD_SE; |
643 if (b & TRACK_BIT_RIGHT) r |= ROAD_NE | ROAD_SE; |
500 return r; |
644 return r; |
501 } |
645 } |
502 |
646 |
|
647 /** |
|
648 * Check if a neighboring tile has a road |
|
649 * |
|
650 * @param tile curent tile |
|
651 * @param dir target direction |
|
652 * @param dist_multi distance multiplyer |
|
653 * @return true if one of the neighboring tiles at the |
|
654 * given distance is a road tile else |
|
655 */ |
|
656 static bool NeighborIsRoadTile(TileIndex tile, int dir, RoadBlockTitleDistance dist_multi) |
|
657 { |
|
658 return (HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * ToTileIndexDiff(_roadblock_tileadd[dir + 1]))), dir ^ 2) || |
|
659 HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * ToTileIndexDiff(_roadblock_tileadd[dir + 3]))), dir ^ 2) || |
|
660 HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * (ToTileIndexDiff(_roadblock_tileadd[dir + 1]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2])))), dir) || |
|
661 HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * (ToTileIndexDiff(_roadblock_tileadd[dir + 3]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2])))), dir)); |
|
662 } |
|
663 |
503 static bool IsRoadAllowedHere(TileIndex tile, int dir) |
664 static bool IsRoadAllowedHere(TileIndex tile, int dir) |
504 { |
665 { |
505 Slope k; |
666 Slope k; |
506 Slope slope; |
667 Slope slope; |
507 |
668 |
509 * land at the edges. This is not ok. */ |
670 * land at the edges. This is not ok. */ |
510 TILE_ASSERT(tile); |
671 TILE_ASSERT(tile); |
511 |
672 |
512 for (;;) { |
673 for (;;) { |
513 /* Check if there already is a road at this point? */ |
674 /* Check if there already is a road at this point? */ |
514 if (GetAnyRoadTrackBits(tile) == 0) { |
675 if (GetAnyRoadTrackBits(tile, ROADTYPE_ROAD) == 0) { |
515 /* No, try to build one in the direction. |
676 /* No, try to build one in the direction. |
516 * if that fails clear the land, and if that fails exit. |
677 * if that fails clear the land, and if that fails exit. |
517 * This is to make sure that we can build a road here later. */ |
678 * This is to make sure that we can build a road here later. */ |
518 if (CmdFailed(DoCommand(tile, (dir & 1 ? ROAD_X : ROAD_Y), 0, DC_AUTO, CMD_BUILD_ROAD)) && |
679 if (CmdFailed(DoCommand(tile, (dir & 1 ? ROAD_X : ROAD_Y), 0, DC_AUTO, CMD_BUILD_ROAD)) && |
519 CmdFailed(DoCommand(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR))) |
680 CmdFailed(DoCommand(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR))) |
521 } |
682 } |
522 |
683 |
523 slope = GetTileSlope(tile, NULL); |
684 slope = GetTileSlope(tile, NULL); |
524 if (slope == SLOPE_FLAT) { |
685 if (slope == SLOPE_FLAT) { |
525 no_slope: |
686 no_slope: |
526 /* Tile has no slope |
687 /* Tile has no slope */ |
527 * Disallow the road if any neighboring tile has a road. */ |
688 switch (_patches.town_layout) { |
528 if (HASBIT(GetTownRoadMask(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[dir + 1]))), dir ^ 2) || |
689 default: NOT_REACHED(); |
529 HASBIT(GetTownRoadMask(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[dir + 3]))), dir ^ 2) || |
690 |
530 HASBIT(GetTownRoadMask(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[dir + 1]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2]))), dir) || |
691 case TL_ORIGINAL: /* Disallow the road if any neighboring tile has a road (distance: 1) */ |
531 HASBIT(GetTownRoadMask(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[dir + 3]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2]))), dir)) |
692 return !NeighborIsRoadTile(tile, dir, RB_TILE_DIST1); |
532 return false; |
693 |
533 |
694 case TL_BETTER_ROADS: /* Disallow the road if any neighboring tile has a road (distance: 1 and 2). */ |
534 /* Otherwise allow */ |
695 return !(NeighborIsRoadTile(tile, dir, RB_TILE_DIST1) || |
535 return true; |
696 NeighborIsRoadTile(tile, dir, RB_TILE_DIST2)); |
|
697 } |
536 } |
698 } |
537 |
699 |
538 /* If the tile is not a slope in the right direction, then |
700 /* If the tile is not a slope in the right direction, then |
539 * maybe terraform some. */ |
701 * maybe terraform some. */ |
540 k = (dir & 1) ? SLOPE_NE : SLOPE_NW; |
702 k = (dir & 1) ? SLOPE_NE : SLOPE_NW; |
589 if (!TerraformTownTile(tile, ~tileh & 0xF, 1)) { |
751 if (!TerraformTownTile(tile, ~tileh & 0xF, 1)) { |
590 TerraformTownTile(tile, tileh & 0xF, 0); |
752 TerraformTownTile(tile, tileh & 0xF, 0); |
591 } |
753 } |
592 } |
754 } |
593 |
755 |
|
756 /** |
|
757 * Generate the RoadBits of a grid tile |
|
758 * |
|
759 * @param t current town |
|
760 * @param tile tile in reference to the town |
|
761 * @return the RoadBit of the current tile regarding |
|
762 * the selected town layout |
|
763 */ |
|
764 static RoadBits GetTownRoadGridElement(Town* t, TileIndex tile) |
|
765 { |
|
766 /* align the grid to the downtown */ |
|
767 TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); ///< Vector from downtown to the tile |
|
768 |
|
769 /* lx, ly description: |
|
770 * @li lx and ly are true if the tile is a crossing tile. |
|
771 * @li lx xor ly are true if the tile is a straight road tile. |
|
772 * @li lx and ly are false if the tile is a house tile. |
|
773 */ |
|
774 bool lx, ly; |
|
775 |
|
776 switch (_patches.town_layout) { |
|
777 default: NOT_REACHED(); |
|
778 |
|
779 case TL_2X2_GRID: |
|
780 lx = ((grid_pos.x % 3) == 0); |
|
781 ly = ((grid_pos.y % 3) == 0); |
|
782 break; |
|
783 |
|
784 case TL_3X3_GRID: |
|
785 lx = ((grid_pos.x % 4) == 0); |
|
786 ly = ((grid_pos.y % 4) == 0); |
|
787 break; |
|
788 } |
|
789 |
|
790 /* generate the basic grid structure */ |
|
791 if (!lx && !ly) { ///< It is a house tile |
|
792 return ROAD_NONE; |
|
793 } else if (lx && !ly) { ///< It is a Y-dir road tile |
|
794 return ROAD_Y; |
|
795 } else if (!lx && ly) { ///< It is a X-dir road tile |
|
796 return ROAD_X; |
|
797 } else { ///< It is a crossing tile |
|
798 /* Presets for junctions on slopes |
|
799 * not nice :( */ |
|
800 switch (GetTileSlope(tile, NULL)) { |
|
801 case SLOPE_W: |
|
802 return ROAD_NW | ROAD_SW; |
|
803 case SLOPE_S: |
|
804 return ROAD_SE | ROAD_SW; |
|
805 case SLOPE_SW: |
|
806 return ROAD_Y | ROAD_SW; |
|
807 case SLOPE_E: |
|
808 return ROAD_NE | ROAD_SE; |
|
809 case SLOPE_SE: |
|
810 return ROAD_X | ROAD_SE; |
|
811 case SLOPE_N: |
|
812 return ROAD_NW | ROAD_NE; |
|
813 case SLOPE_NW: |
|
814 return ROAD_X | ROAD_NW; |
|
815 case SLOPE_NE: |
|
816 return ROAD_Y | ROAD_NE; |
|
817 case SLOPE_STEEP_W: |
|
818 case SLOPE_STEEP_N: |
|
819 return ROAD_X; |
|
820 case SLOPE_STEEP_S: |
|
821 case SLOPE_STEEP_E: |
|
822 return ROAD_Y; |
|
823 default: |
|
824 return ROAD_ALL; |
|
825 } |
|
826 } |
|
827 } |
|
828 |
|
829 /** |
|
830 * Check there are enougth neighbor house tiles next to the current tile |
|
831 * |
|
832 * @param tile current tile |
|
833 * @return true if there are more than 2 house tiles next |
|
834 * to the current one |
|
835 */ |
|
836 static bool NeighborsAreHouseTiles(TileIndex tile) |
|
837 { |
|
838 uint counter = 0; ///< counts the house neighbor tiles |
|
839 |
|
840 /* We can't look further than that. */ |
|
841 if (TileX(tile) < 1 || TileY(tile) < 1) { |
|
842 return false; |
|
843 } |
|
844 |
|
845 /* Check the tiles E,N,W and S of the current tile. */ |
|
846 for (uint i = 0; i < 4; i++) { |
|
847 if (IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[i])), MP_HOUSE)) { |
|
848 counter++; |
|
849 } |
|
850 |
|
851 /* If there are enougth neighbor's stop it here */ |
|
852 if (counter >= 3) { |
|
853 return true; |
|
854 } |
|
855 } |
|
856 return false; |
|
857 } |
|
858 |
|
859 /** |
|
860 * Grows the given town. |
|
861 * There are at the moment 3 possible way's for |
|
862 * the town expansion: |
|
863 * @li Generate a random tile and check if there is a road allowed |
|
864 * @li TL_ORIGINAL |
|
865 * @li TL_BETTER_ROADS |
|
866 * @li Check if the town geometry allows a road and which one |
|
867 * @li TL_2X2_GRID |
|
868 * @li TL_3X3_GRID |
|
869 * @li Forbid roads, only build houses |
|
870 * @li TL_NO_ROADS |
|
871 * |
|
872 * @param tile_ptr current tile |
|
873 * @param mask current tiles RoadBits |
|
874 * @param block road block |
|
875 * @param t1 current town |
|
876 */ |
594 static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town* t1) |
877 static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town* t1) |
595 { |
878 { |
596 RoadBits rcmd; |
879 RoadBits rcmd; |
597 TileIndex tmptile; |
880 TileIndex tmptile; |
598 DiagDirection i; |
881 DiagDirection i; |
611 |
894 |
612 /* Remove hills etc */ |
895 /* Remove hills etc */ |
613 LevelTownLand(tile); |
896 LevelTownLand(tile); |
614 |
897 |
615 /* Is a road allowed here? */ |
898 /* Is a road allowed here? */ |
616 if (!IsRoadAllowedHere(tile, block)) return; |
899 switch (_patches.town_layout) { |
617 |
900 default: NOT_REACHED(); |
618 /* Randomize new road block numbers */ |
901 |
619 a = block; |
902 case TL_NO_ROADS: /* Disallow Roads */ |
620 b = block ^ 2; |
|
621 if (CHANCE16(1, 4)) { |
|
622 do { |
|
623 a = GB(Random(), 0, 2); |
|
624 } while (a == b); |
|
625 } |
|
626 |
|
627 if (!IsRoadAllowedHere(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a])), a)) { |
|
628 /* A road is not allowed to continue the randomized road, |
|
629 * return if the road we're trying to build is curved. */ |
|
630 if (a != (b ^ 2)) return; |
|
631 |
|
632 /* Return if neither side of the new road is a house */ |
|
633 if (!IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 1])), MP_HOUSE) && |
|
634 !IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 3])), MP_HOUSE)) |
|
635 return; |
903 return; |
636 |
904 |
637 /* That means that the road is only allowed if there is a house |
905 case TL_3X3_GRID: |
638 * at any side of the new road. */ |
906 case TL_2X2_GRID: |
639 } |
907 rcmd = GetTownRoadGridElement(t1, tile); |
640 rcmd = (RoadBits)((1 << a) + (1 << b)); |
908 if (rcmd == ROAD_NONE) { |
|
909 return; |
|
910 } |
|
911 break; |
|
912 |
|
913 case TL_BETTER_ROADS: |
|
914 case TL_ORIGINAL: |
|
915 if (!IsRoadAllowedHere(tile, block)) { |
|
916 return; |
|
917 } |
|
918 |
|
919 /* Randomize new road block numbers */ |
|
920 a = block; |
|
921 b = block ^ 2; |
|
922 if (CHANCE16(1, 4)) { |
|
923 do { |
|
924 a = GB(Random(), 0, 2); |
|
925 } while (a == b); |
|
926 } |
|
927 |
|
928 if (!IsRoadAllowedHere(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a])), a)) { |
|
929 /* A road is not allowed to continue the randomized road, |
|
930 * return if the road we're trying to build is curved. */ |
|
931 if (a != (b ^ 2)) { |
|
932 return; |
|
933 } |
|
934 |
|
935 /* Return if neither side of the new road is a house */ |
|
936 if (!IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 1])), MP_HOUSE) && |
|
937 !IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 3])), MP_HOUSE)) { |
|
938 return; |
|
939 } |
|
940 |
|
941 /* That means that the road is only allowed if there is a house |
|
942 * at any side of the new road. */ |
|
943 } |
|
944 |
|
945 rcmd = (RoadBits)((1 << a) + (1 << b)); |
|
946 break; |
|
947 } |
641 |
948 |
642 } else if (block < 5 && !HASBIT(mask, block ^ 2)) { |
949 } else if (block < 5 && !HASBIT(mask, block ^ 2)) { |
643 /* Continue building on a partial road. |
950 /* Continue building on a partial road. |
644 * Always OK. */ |
951 * Always OK. */ |
645 _grow_town_result = 0; |
952 _grow_town_result = 0; |
646 rcmd = (RoadBits)(1 << (block ^ 2)); |
953 |
|
954 switch (_patches.town_layout) { |
|
955 default: NOT_REACHED(); |
|
956 |
|
957 case TL_NO_ROADS: /* Disallow Roads */ |
|
958 return; |
|
959 |
|
960 case TL_3X3_GRID: |
|
961 case TL_2X2_GRID: |
|
962 rcmd = GetTownRoadGridElement(t1, tile); |
|
963 break; |
|
964 |
|
965 case TL_BETTER_ROADS: |
|
966 case TL_ORIGINAL: |
|
967 rcmd = (RoadBits)(1 << (block ^ 2)); |
|
968 break; |
|
969 } |
647 } else { |
970 } else { |
648 int i; |
971 int i; |
|
972 bool allow_house = false; |
|
973 TileIndex tmptile2; |
649 |
974 |
650 /* Reached a tunnel/bridge? Then continue at the other side of it. */ |
975 /* Reached a tunnel/bridge? Then continue at the other side of it. */ |
651 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
976 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
652 if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) { |
977 if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) { |
653 *tile_ptr = GetOtherTunnelEnd(tile); |
978 *tile_ptr = GetOtherTunnelEnd(tile); |
666 tmptile = TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[i])); |
991 tmptile = TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[i])); |
667 |
992 |
668 /* Don't do it if it reaches to water. */ |
993 /* Don't do it if it reaches to water. */ |
669 if (IsClearWaterTile(tmptile)) return; |
994 if (IsClearWaterTile(tmptile)) return; |
670 |
995 |
671 /* Build a house at the edge. 60% chance or |
996 switch (_patches.town_layout) { |
672 * always ok if no road allowed. */ |
997 default: NOT_REACHED(); |
673 if (!IsRoadAllowedHere(tmptile, i) || CHANCE16(6, 10)) { |
998 |
674 /* But not if there already is a house there. */ |
999 case TL_NO_ROADS: |
|
1000 allow_house = true; |
|
1001 break; |
|
1002 |
|
1003 case TL_3X3_GRID: /* Use 2x2 grid afterwards! */ |
|
1004 /* Fill gap if house has enougth neighbors */ |
|
1005 tmptile2 = TILE_ADD(tmptile, ToTileIndexDiff(_roadblock_tileadd[i])); |
|
1006 if (NeighborsAreHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) { |
|
1007 _grow_town_result = -1; |
|
1008 } |
|
1009 |
|
1010 case TL_2X2_GRID: |
|
1011 rcmd = GetTownRoadGridElement(t1, tmptile); |
|
1012 allow_house = (rcmd == ROAD_NONE); |
|
1013 break; |
|
1014 |
|
1015 case TL_BETTER_ROADS: /* Use original afterwards! */ |
|
1016 /* Fill gap if house has enougth neighbors */ |
|
1017 tmptile2 = TILE_ADD(tmptile, ToTileIndexDiff(_roadblock_tileadd[i])); |
|
1018 if (NeighborsAreHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) { |
|
1019 _grow_town_result = -1; |
|
1020 } |
|
1021 |
|
1022 case TL_ORIGINAL: |
|
1023 /* Allow a house at the edge. 60% chance or |
|
1024 * always ok if no road allowed. */ |
|
1025 allow_house = (!IsRoadAllowedHere(tmptile, i) || CHANCE16(6, 10)); |
|
1026 break; |
|
1027 } |
|
1028 |
|
1029 |
|
1030 if (allow_house) { |
|
1031 /* Build a house, but not if there already is a house there. */ |
675 if (!IsTileType(tmptile, MP_HOUSE)) { |
1032 if (!IsTileType(tmptile, MP_HOUSE)) { |
676 /* Level the land if possible */ |
1033 /* Level the land if possible */ |
677 LevelTownLand(tmptile); |
1034 LevelTownLand(tmptile); |
678 |
1035 |
679 /* And build a house. |
1036 /* And build a house. |
680 * Set result to -1 if we managed to build it. */ |
1037 * Set result to -1 if we managed to build it. */ |
681 if (BuildTownHouse(t1, tmptile)) _grow_town_result = -1; |
1038 if (BuildTownHouse(t1, tmptile)) { |
|
1039 _grow_town_result = -1; |
|
1040 } |
682 } |
1041 } |
683 return; |
1042 return; |
684 } |
1043 } |
685 |
1044 |
686 _grow_town_result = 0; |
1045 _grow_town_result = 0; |
821 { 2, 2}, |
1201 { 2, 2}, |
822 { 2, -2}, |
1202 { 2, -2}, |
823 { 0, 0} |
1203 { 0, 0} |
824 }; |
1204 }; |
825 |
1205 |
|
1206 /* Let the town be a ghost town |
|
1207 * The player wanted it in such a way. Thus there he has it. ;) |
|
1208 * Never reached in editor mode. */ |
|
1209 if (_patches.town_layout == TL_NO_ROADS && _generating_world) { |
|
1210 return false; |
|
1211 } |
|
1212 |
826 /* Current player is a town */ |
1213 /* Current player is a town */ |
827 old_player = _current_player; |
1214 old_player = _current_player; |
828 _current_player = OWNER_TOWN; |
1215 _current_player = OWNER_TOWN; |
829 |
1216 |
830 /* Find a road that we can base the construction on. */ |
1217 /* Find a road that we can base the construction on. */ |
831 tile = t->xy; |
1218 tile = t->xy; |
832 for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) { |
1219 for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) { |
833 if (GetAnyRoadTrackBits(tile) != 0) { |
1220 if (GetAnyRoadTrackBits(tile, ROADTYPE_ROAD) != 0) { |
834 int r = GrowTownAtRoad(t, tile); |
1221 int r = GrowTownAtRoad(t, tile); |
835 _current_player = old_player; |
1222 _current_player = old_player; |
836 return r != 0; |
1223 return r != 0; |
837 } |
1224 } |
838 tile = TILE_ADD(tile, ToTileIndexDiff(*ptr)); |
1225 tile = TILE_ADD(tile, ToTileIndexDiff(*ptr)); |
842 * clearing some land and then building a road there. */ |
1229 * clearing some land and then building a road there. */ |
843 tile = t->xy; |
1230 tile = t->xy; |
844 for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) { |
1231 for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) { |
845 /* Only work with plain land that not already has a house */ |
1232 /* Only work with plain land that not already has a house */ |
846 if (!IsTileType(tile, MP_HOUSE) && GetTileSlope(tile, NULL) == SLOPE_FLAT) { |
1233 if (!IsTileType(tile, MP_HOUSE) && GetTileSlope(tile, NULL) == SLOPE_FLAT) { |
847 if (!CmdFailed(DoCommand(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR))) { |
1234 if (!CmdFailed(DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR))) { |
848 DoCommand(tile, GenRandomRoadBits(), t->index, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD); |
1235 DoCommand(tile, GenRandomRoadBits(), t->index, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD); |
849 _current_player = old_player; |
1236 _current_player = old_player; |
850 return true; |
1237 return true; |
851 } |
1238 } |
852 } |
1239 } |
1302 if (hs->override != 0) hs = GetHouseSpecs(hs->override); |
1689 if (hs->override != 0) hs = GetHouseSpecs(hs->override); |
1303 |
1690 |
1304 if ((hs->extra_flags & BUILDING_IS_HISTORICAL) && !_generating_world) continue; |
1691 if ((hs->extra_flags & BUILDING_IS_HISTORICAL) && !_generating_world) continue; |
1305 |
1692 |
1306 if (HASBIT(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) { |
1693 if (HASBIT(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) { |
1307 uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, house, t, tile); |
1694 uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, 0, house, t, tile); |
1308 if (callback_res != CALLBACK_FAILED && callback_res == 0) continue; |
1695 if (callback_res != CALLBACK_FAILED && callback_res == 0) continue; |
1309 } |
1696 } |
1310 } |
1697 } |
1311 |
1698 |
1312 if (_cur_year < hs->min_date || _cur_year > hs->max_date) continue; |
1699 if (_cur_year < hs->min_date || _cur_year > hs->max_date) continue; |
2012 }; |
2399 }; |
2013 |
2400 |
2014 /* Save and load the mapping between the house id on the map, and the grf file |
2401 /* Save and load the mapping between the house id on the map, and the grf file |
2015 * it came from. */ |
2402 * it came from. */ |
2016 static const SaveLoad _house_id_mapping_desc[] = { |
2403 static const SaveLoad _house_id_mapping_desc[] = { |
2017 SLE_VAR(HouseIDMapping, grfid, SLE_UINT32), |
2404 SLE_VAR(EntityIDMapping, grfid, SLE_UINT32), |
2018 SLE_VAR(HouseIDMapping, house_id, SLE_UINT8), |
2405 SLE_VAR(EntityIDMapping, entity_id, SLE_UINT8), |
2019 SLE_VAR(HouseIDMapping, substitute_id, SLE_UINT8), |
2406 SLE_VAR(EntityIDMapping, substitute_id, SLE_UINT8), |
2020 SLE_END() |
2407 SLE_END() |
2021 }; |
2408 }; |
2022 |
2409 |
2023 static void Save_HOUSEIDS() |
2410 static void Save_HOUSEIDS() |
2024 { |
2411 { |
2025 uint i; |
2412 uint j = _house_mngr.GetMaxMapping(); |
2026 |
2413 |
2027 for (i = 0; i != lengthof(_house_id_mapping); i++) { |
2414 for (uint i = 0; i < j; i++) { |
2028 SlSetArrayIndex(i); |
2415 SlSetArrayIndex(i); |
2029 SlObject(&_house_id_mapping[i], _house_id_mapping_desc); |
2416 SlObject(&_house_mngr.mapping_ID[i], _house_id_mapping_desc); |
2030 } |
2417 } |
2031 } |
2418 } |
2032 |
2419 |
2033 static void Load_HOUSEIDS() |
2420 static void Load_HOUSEIDS() |
2034 { |
2421 { |
2035 int index; |
2422 int index; |
2036 |
2423 |
2037 ResetHouseIDMapping(); |
2424 _house_mngr.ResetMapping(); |
|
2425 uint max_id = _house_mngr.GetMaxMapping(); |
2038 |
2426 |
2039 while ((index = SlIterateArray()) != -1) { |
2427 while ((index = SlIterateArray()) != -1) { |
2040 if ((uint)index >= lengthof(_house_id_mapping)) break; |
2428 if ((uint)index >= max_id) break; |
2041 SlObject(&_house_id_mapping[index], _house_id_mapping_desc); |
2429 SlObject(&_house_mngr.mapping_ID[index], _house_id_mapping_desc); |
2042 } |
2430 } |
2043 } |
2431 } |
2044 |
2432 |
2045 static void Save_TOWN() |
2433 static void Save_TOWN() |
2046 { |
2434 { |