1584 } |
1583 } |
1585 |
1584 |
1586 return true; |
1585 return true; |
1587 } |
1586 } |
1588 |
1587 |
1589 static bool CheckBuildHouseMode(TileIndex tile, Slope tileh, int mode) |
|
1590 { |
|
1591 int b; |
|
1592 Slope slope; |
|
1593 |
|
1594 static const Slope _masks[8] = { |
|
1595 SLOPE_NE, SLOPE_SW, SLOPE_NW, SLOPE_SE, |
|
1596 SLOPE_SW, SLOPE_NE, SLOPE_SE, SLOPE_NW, |
|
1597 }; |
|
1598 |
|
1599 slope = GetTileSlope(tile, NULL); |
|
1600 if (IsSteepSlope(slope)) return false; |
|
1601 |
|
1602 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return false; |
|
1603 |
|
1604 b = 0; |
|
1605 if ((slope != SLOPE_FLAT && ~slope & _masks[mode])) b = ~b; |
|
1606 if ((tileh != SLOPE_FLAT && ~tileh & _masks[mode + 4])) b = ~b; |
|
1607 if (b) |
|
1608 return false; |
|
1609 |
|
1610 return CmdSucceeded(DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR)); |
|
1611 } |
|
1612 |
1588 |
1613 /** Returns the bit corresponding to the town zone of the specified tile |
1589 /** Returns the bit corresponding to the town zone of the specified tile |
1614 * @param t Town on which radius is to be found |
1590 * @param t Town on which radius is to be found |
1615 * @param tile TileIndex where radius needs to be found |
1591 * @param tile TileIndex where radius needs to be found |
1616 * @return the bit position of the given zone, as defined in HouseZones |
1592 * @return the bit position of the given zone, as defined in HouseZones |
1629 } |
1605 } |
1630 |
1606 |
1631 return smallest; |
1607 return smallest; |
1632 } |
1608 } |
1633 |
1609 |
1634 static bool CheckFree2x2Area(TileIndex tile) |
1610 /** |
1635 { |
1611 * Clears tile and builds a house or house part. |
1636 int i; |
1612 * @param t tile index |
1637 |
1613 * @param tid Town index |
1638 static const TileIndexDiffC _tile_add[] = { |
1614 * @param counter of construction step |
1639 {0 , 0 }, |
1615 * @param stage of construction (used for drawing) |
1640 {0 - 0, 1 - 0}, |
1616 * @param type of house. Index into house specs array |
1641 {1 - 0, 0 - 1}, |
1617 * @param random_bits required for newgrf houses |
1642 {1 - 1, 1 - 0} |
1618 * @pre house can be built here |
1643 }; |
1619 */ |
1644 |
1620 |
1645 for (i = 0; i != 4; i++) { |
1621 static inline void ClearMakeHouseTile(TileIndex tile, TownID tid, byte counter, byte stage, HouseID type, byte random_bits) |
1646 tile += ToTileIndexDiff(_tile_add[i]); |
1622 { |
1647 |
1623 CommandCost cc = DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR); |
1648 if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return false; |
1624 assert(CmdSucceeded(cc)); |
1649 |
1625 |
1650 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return false; |
1626 MakeHouseTile(tile, tid, counter, stage, type, random_bits); |
1651 |
1627 } |
1652 if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER | DC_FORCETEST, CMD_LANDSCAPE_CLEAR))) |
1628 |
1653 return false; |
1629 /** |
1654 } |
1630 * Write house information into the map. For houses > 1 tile, all tiles are marked. |
|
1631 * @param t tile index |
|
1632 * @param tid Town index |
|
1633 * @param counter of construction step |
|
1634 * @param stage of construction (used for drawing) |
|
1635 * @param type of house. Index into house specs array |
|
1636 * @param random_bits required for newgrf houses |
|
1637 * @pre house can be built here |
|
1638 */ |
|
1639 static void MakeTownHouse(TileIndex t, TownID tid, byte counter, byte stage, HouseID type, byte random_bits) |
|
1640 { |
|
1641 BuildingFlags size = GetHouseSpecs(type)->building_flags; |
|
1642 |
|
1643 ClearMakeHouseTile(t, tid, counter, stage, type, random_bits); |
|
1644 if (size & BUILDING_2_TILES_Y) ClearMakeHouseTile(t + TileDiffXY(0, 1), tid, counter, stage, ++type, random_bits); |
|
1645 if (size & BUILDING_2_TILES_X) ClearMakeHouseTile(t + TileDiffXY(1, 0), tid, counter, stage, ++type, random_bits); |
|
1646 if (size & BUILDING_HAS_4_TILES) ClearMakeHouseTile(t + TileDiffXY(1, 1), tid, counter, stage, ++type, random_bits); |
|
1647 } |
|
1648 |
|
1649 |
|
1650 /** |
|
1651 * Checks if a house can be built here. Important is slope, bridge above |
|
1652 * and ability to clear the land. |
|
1653 * @param tile tile to check |
|
1654 * @param noslope are slopes (foundations) allowed? |
|
1655 * @return true iff house can be built here |
|
1656 */ |
|
1657 static inline bool CanBuildHouseHere(TileIndex tile, bool noslope) |
|
1658 { |
|
1659 /* cannot build on these slopes... */ |
|
1660 Slope slope = GetTileSlope(tile, NULL); |
|
1661 if ((noslope && slope != SLOPE_FLAT) || IsSteepSlope(slope)) return false; |
|
1662 |
|
1663 /* building under a bridge? */ |
|
1664 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return false; |
|
1665 |
|
1666 /* can we clear the land? */ |
|
1667 return CmdSucceeded(DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR)); |
|
1668 } |
|
1669 |
|
1670 |
|
1671 /** |
|
1672 * Checks if a house can be built at this tile, must have the same max z as parameter. |
|
1673 * @param tile tile to check |
|
1674 * @param z max z of this tile so more parts of a house are at the same height (with foundation) |
|
1675 * @param noslope are slopes (foundations) allowed? |
|
1676 * @return true iff house can be built here |
|
1677 * @see CanBuildHouseHere() |
|
1678 */ |
|
1679 static inline bool CheckBuildHouseSameZ(TileIndex tile, uint z, bool noslope) |
|
1680 { |
|
1681 if (!CanBuildHouseHere(tile, noslope)) return false; |
|
1682 |
|
1683 /* if building on slopes is allowed, there will be flattening foundation (to tile max z) */ |
|
1684 if (GetTileMaxZ(tile) != z) return false; |
1655 |
1685 |
1656 return true; |
1686 return true; |
1657 } |
1687 } |
1658 |
1688 |
1659 static void DoBuildTownHouse(Town *t, TileIndex tile) |
1689 |
|
1690 /** |
|
1691 * Checks if a house of size 2x2 can be built at this tile |
|
1692 * @param tile tile, N corner |
|
1693 * @param z maximum tile z so all tile have the same max z |
|
1694 * @param noslope are slopes (foundations) allowed? |
|
1695 * @return true iff house can be built |
|
1696 * @see CheckBuildHouseSameZ() |
|
1697 */ |
|
1698 static bool CheckFree2x2Area(TileIndex tile, uint z, bool noslope) |
|
1699 { |
|
1700 /* we need to check this tile too because we can be at different tile now */ |
|
1701 if (!CheckBuildHouseSameZ(tile, z, noslope)) return false; |
|
1702 |
|
1703 for (DiagDirection d = DIAGDIR_SE; d < DIAGDIR_END; d++) { |
|
1704 tile += TileOffsByDiagDir(d); |
|
1705 if (!CheckBuildHouseSameZ(tile, z, noslope)) return false; |
|
1706 } |
|
1707 |
|
1708 return true; |
|
1709 } |
|
1710 |
|
1711 |
|
1712 /** |
|
1713 * Tries to build a house at this tile |
|
1714 * @param t town the house will belong to |
|
1715 * @param tile where the house will be built |
|
1716 * @return false iff no house can be built at this tile |
|
1717 */ |
|
1718 static bool BuildTownHouse(Town *t, TileIndex tile) |
1660 { |
1719 { |
1661 int i; |
1720 int i; |
1662 uint bitmask; |
1721 uint bitmask; |
1663 HouseID house; |
1722 HouseID house; |
1664 Slope slope; |
1723 Slope slope; |
1665 uint z; |
1724 uint z; |
1666 uint oneof = 0; |
1725 uint oneof = 0; |
1667 HouseSpec *hs; |
1726 HouseSpec *hs; |
|
1727 |
|
1728 /* no house allowed at all, bail out */ |
|
1729 if (!CanBuildHouseHere(tile, false)) return false; |
1668 |
1730 |
1669 /* Above snow? */ |
1731 /* Above snow? */ |
1670 slope = GetTileSlope(tile, &z); |
1732 slope = GetTileSlope(tile, &z); |
1671 |
1733 |
1672 /* Get the town zone type of the current tile, as well as the climate. |
1734 /* Get the town zone type of the current tile, as well as the climate. |
1740 } |
1804 } |
1741 |
1805 |
1742 if (HASBITS(t->flags12 , oneof)) continue; |
1806 if (HASBITS(t->flags12 , oneof)) continue; |
1743 |
1807 |
1744 /* Make sure there is no slope? */ |
1808 /* Make sure there is no slope? */ |
1745 if (hs->building_flags & TILE_NOT_SLOPED && slope != SLOPE_FLAT) continue; |
1809 bool noslope = (hs->building_flags & TILE_NOT_SLOPED) != 0; |
|
1810 if (noslope && slope != SLOPE_FLAT) continue; |
1746 |
1811 |
1747 if (hs->building_flags & TILE_SIZE_2x2) { |
1812 if (hs->building_flags & TILE_SIZE_2x2) { |
1748 if (CheckFree2x2Area(tile) || |
1813 if (CheckFree2x2Area(tile, maxz, noslope) || |
1749 CheckFree2x2Area(tile += TileDiffXY(-1, 0)) || |
1814 CheckFree2x2Area(tile += TileDiffXY(-1, 0), maxz, noslope) || |
1750 CheckFree2x2Area(tile += TileDiffXY( 0, -1)) || |
1815 CheckFree2x2Area(tile += TileDiffXY( 0, -1), maxz, noslope) || |
1751 CheckFree2x2Area(tile += TileDiffXY( 1, 0))) { |
1816 CheckFree2x2Area(tile += TileDiffXY( 1, 0), maxz, noslope)) { |
1752 break; |
1817 break; |
1753 } |
1818 } |
|
1819 /* return to original tile */ |
1754 tile += TileDiffXY(0, 1); |
1820 tile += TileDiffXY(0, 1); |
1755 } else if (hs->building_flags & TILE_SIZE_2x1) { |
1821 } else if (hs->building_flags & TILE_SIZE_2x1) { |
1756 if (CheckBuildHouseMode(tile + TileDiffXY(1, 0), slope, 0)) break; |
1822 /* 'tile' is already checked above - CanBuildHouseHere() and slope test */ |
1757 |
1823 if (CheckBuildHouseSameZ(tile + TileDiffXY(1, 0), maxz, noslope)) break; |
1758 if (CheckBuildHouseMode(tile + TileDiffXY(-1, 0), slope, 1)) { |
1824 |
|
1825 if (CheckBuildHouseSameZ(tile + TileDiffXY(-1, 0), maxz, noslope)) { |
1759 tile += TileDiffXY(-1, 0); |
1826 tile += TileDiffXY(-1, 0); |
1760 break; |
1827 break; |
1761 } |
1828 } |
1762 } else if (hs->building_flags & TILE_SIZE_1x2) { |
1829 } else if (hs->building_flags & TILE_SIZE_1x2) { |
1763 if (CheckBuildHouseMode(tile + TileDiffXY(0, 1), slope, 2)) break; |
1830 if (CheckBuildHouseSameZ(tile + TileDiffXY(0, 1), maxz, noslope)) break; |
1764 |
1831 |
1765 if (CheckBuildHouseMode(tile + TileDiffXY(0, -1), slope, 3)) { |
1832 if (CheckBuildHouseSameZ(tile + TileDiffXY(0, -1), maxz, noslope)) { |
1766 tile += TileDiffXY(0, -1); |
1833 tile += TileDiffXY(0, -1); |
1767 break; |
1834 break; |
1768 } |
1835 } |
1769 } else { |
1836 } else { |
1770 break; |
1837 break; |