Hooks
static bool BeforeCvPlot_changeAdjacentSight(CvPlot* self, TeamTypes eTeam, int iRange, bool bIncrement, InvisibleTypes eSeeInvisible, DirectionTypes eFacingDirection, CvUnit* pUnit);static void AfterCvPlot_changeAdjacentSight(CvPlot* self, TeamTypes eTeam, int iRange, bool bIncrement, InvisibleTypes eSeeInvisible, DirectionTypes eFacingDirection, CvUnit* pUnit);static void ReplaceCvPlot_changeAdjacentSight(void (*original)(CvPlot*, TeamTypes, int, bool, InvisibleTypes, DirectionTypes, CvUnit*), CvPlot* self, TeamTypes eTeam, int iRange, bool bIncrement, InvisibleTypes eSeeInvisible, DirectionTypes eFacingDirection, CvUnit* pUnit);CivRegisterBefore<CivHooks::CvPlot_changeAdjacentSight>(host, &BeforeCvPlot_changeAdjacentSight);CivRegisterAfter<CivHooks::CvPlot_changeAdjacentSight>(host, &AfterCvPlot_changeAdjacentSight);CivRegisterReplace<CivHooks::CvPlot_changeAdjacentSight>(host, &ReplaceCvPlot_changeAdjacentSight);
Code
1527// while this looks more complex than the previous version, it should run much faster1528#if defined(MOD_API_EXTENSIONS)1529void CvPlot::changeAdjacentSight(TeamTypes eTeam, int iRange, bool bIncrement, InvisibleTypes eSeeInvisible, DirectionTypes eFacingDirection, CvUnit* pUnit)1530#else1531void CvPlot::changeAdjacentSight(TeamTypes eTeam, int iRange, bool bIncrement, InvisibleTypes eSeeInvisible, DirectionTypes eFacingDirection, bool bBasedOnUnit)1532#endif1533{1534#if defined(MOD_API_EXTENSIONS)1535 bool bBasedOnUnit = (pUnit != NULL);1536#endif1537 //check one extra outer ring1538 int iRangeWithOneExtraRing = iRange + 1;15391540 // start in the center going NE1541 int thisRing = 0;1542 DirectionTypes eDirectionOfNextTileToCheck = DIRECTION_NORTHWEST;1543 CvPlot* pPlotToCheck = this;1544 int iDX = 0;1545 int iDY = 0;1546 int iCenterLevel = seeFromLevel(eTeam);1547 int iPlotCounter = 0;1548 int iMaxPlotNumberOnThisRing = 0;15491550 while(thisRing <= iRangeWithOneExtraRing)1551 {1552 if(pPlotToCheck)1553 {1554 //always reveal adjacent plots when using line of sight - but then clear it out1555 if(thisRing <= 1)1556 {1557 if(eFacingDirection != NO_DIRECTION)1558 {1559#if defined(MOD_API_EXTENSIONS)1560 pPlotToCheck->changeVisibilityCount(eTeam, 1, eSeeInvisible, false /*bInformExplorationTracking*/, false, pUnit);1561 pPlotToCheck->changeVisibilityCount(eTeam, -1, eSeeInvisible, false /*bInformExplorationTracking*/, false, pUnit);1562#else1563 pPlotToCheck->changeVisibilityCount(eTeam, 1, eSeeInvisible, false /*bInformExplorationTracking*/, false);1564 pPlotToCheck->changeVisibilityCount(eTeam, -1, eSeeInvisible, false /*bInformExplorationTracking*/, false);1565#endif1566 }1567 }15681569 // see if this plot is in the visibility wedge1570 if(shouldProcessDisplacementPlot(iDX, iDY, iRange, eFacingDirection))1571 {1572 if(thisRing != 0)1573 {1574 CvPlot* pFirstInwardPlot = NULL;1575 CvPlot* pSecondInwardPlot = NULL;1576 const int INVALID_RING = -1;1577 const int HALF_BLOCKED = 0x01000000;1578 int iRingOfFirstInwardPlot = INVALID_RING;1579 int iRingOfSecondInwardPlot = INVALID_RING;1580 int iFirstInwardLevel = INVALID_RING;1581 int iSecondInwardLevel = INVALID_RING;1582 bool bFirstHalfBlocked = false;1583 bool bSecondHalfBlocked = false;15841585 // try to look at the two plot inwards1586 switch(eDirectionOfNextTileToCheck)1587 {1588 case DIRECTION_NORTHEAST:1589 pFirstInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_EAST);1590 pSecondInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_SOUTHEAST);1591 break;1592 case DIRECTION_EAST:1593 pFirstInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_SOUTHWEST);1594 pSecondInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_SOUTHEAST);1595 break;1596 case DIRECTION_SOUTHEAST:1597 pFirstInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_SOUTHWEST);1598 pSecondInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_WEST);1599 break;1600 case DIRECTION_SOUTHWEST:1601 pFirstInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_WEST);1602 pSecondInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_NORTHWEST);1603 break;1604 case DIRECTION_WEST:1605 pFirstInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_NORTHWEST);1606 pSecondInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_NORTHEAST);1607 break;1608 case DIRECTION_NORTHWEST:1609 pFirstInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_EAST);1610 pSecondInwardPlot = plotDirection(pPlotToCheck->getX(),pPlotToCheck->getY(),DIRECTION_NORTHEAST);1611 break;1612 }1613 if(pFirstInwardPlot)1614 {1615 iRingOfFirstInwardPlot = plotDistance(getX(),getY(),pFirstInwardPlot->getX(),pFirstInwardPlot->getY());1616 if(iRingOfFirstInwardPlot == thisRing - 1)1617 {1618 iFirstInwardLevel = pFirstInwardPlot->getScratchPad();1619 if(iFirstInwardLevel >= HALF_BLOCKED)1620 {1621 iFirstInwardLevel -= HALF_BLOCKED;1622 bFirstHalfBlocked = true;1623 }1624 }1625 }1626 if(pSecondInwardPlot)1627 {1628 iRingOfSecondInwardPlot = plotDistance(getX(),getY(),pSecondInwardPlot->getX(),pSecondInwardPlot->getY());1629 if(iRingOfSecondInwardPlot == thisRing - 1)1630 {1631 iSecondInwardLevel = pSecondInwardPlot->getScratchPad();1632 if(iSecondInwardLevel >= HALF_BLOCKED)1633 {1634 iSecondInwardLevel -= HALF_BLOCKED;1635 bSecondHalfBlocked = true;1636 }1637 }1638 }1639 int iThisPlotLevel = pPlotToCheck->seeThroughLevel(thisRing != iRangeWithOneExtraRing);1640 if(iFirstInwardLevel != INVALID_RING && iSecondInwardLevel != INVALID_RING && iFirstInwardLevel != iSecondInwardLevel && !bFirstHalfBlocked && !bSecondHalfBlocked)1641 {1642 double fP0X = (double) getX();1643 double fP0Y = (double) getY();1644 double fP1X = (double) pPlotToCheck->getX();1645 double fP1Y = (double) pPlotToCheck->getY();1646 if(getY() & 1)1647 {1648 fP0X += 0.5;1649 }1650 if(pPlotToCheck->getY() & 1)1651 {1652 fP1X += 0.5;1653 }16541655 double a = fP1Y - fP0Y;1656 double b = fP0X - fP1X;1657 double c = fP0Y * fP1X - fP1Y * fP0X;16581659 double fFirstInwardX = (double) pFirstInwardPlot->getX();1660 double fFirstInwardY = (double) pFirstInwardPlot->getY();1661 if(pFirstInwardPlot->getY() & 1)1662 {1663 fFirstInwardX += 0.5;1664 }1665 double fFirstDist = a * fFirstInwardX + b * fFirstInwardY + c;1666 fFirstDist = abs(fFirstDist);1667 // skip the extra distance since it is the same for both equations16681669 double fSecondInwardX = (double) pSecondInwardPlot->getX();1670 double fSecondInwardY = (double) pSecondInwardPlot->getY();1671 if(pSecondInwardPlot->getY() & 1)1672 {1673 fSecondInwardX += 0.5;1674 }1675 double fSecondDist = a * fSecondInwardX + b * fSecondInwardY + c;1676 fSecondDist = abs(fSecondDist);1677 // skip the extra distance since it is the same for both equations16781679 if(fFirstDist - fSecondDist > 0.05) // we are closer to the second point1680 {1681 int iHighestLevel = (iSecondInwardLevel > iThisPlotLevel) ? iSecondInwardLevel : iThisPlotLevel;1682 pPlotToCheck->setScratchPad(iHighestLevel);1683 if(iSecondInwardLevel < iThisPlotLevel || ((iCenterLevel >= iSecondInwardLevel) && (thisRing < iRangeWithOneExtraRing)))1684 { 1685#if defined(MOD_API_EXTENSIONS)1686 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2) ? true : false, pUnit);1687#else1688 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2)?true:false);1689#endif1690 }1691 }1692 else if(fSecondDist - fFirstDist > 0.05) // we are closer to the first point1693 {1694 int iHighestLevel = (iFirstInwardLevel > iThisPlotLevel) ? iFirstInwardLevel : iThisPlotLevel;1695 pPlotToCheck->setScratchPad(iHighestLevel);1696 if(iFirstInwardLevel < iThisPlotLevel || ((iCenterLevel >= iFirstInwardLevel) && (thisRing < iRangeWithOneExtraRing)))1697 { 1698#if defined(MOD_API_EXTENSIONS)1699 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2) ? true : false, pUnit);1700#else1701 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2)?true:false);1702#endif1703 }1704 }1705 else1706 {1707 int iHighestInwardLevel = (iFirstInwardLevel > iSecondInwardLevel) ? iFirstInwardLevel : iSecondInwardLevel;1708 int iLowestInwardLevel = (iFirstInwardLevel > iSecondInwardLevel) ? iSecondInwardLevel : iFirstInwardLevel;1709 int iHighestLevel = (iHighestInwardLevel > iThisPlotLevel) ? iHighestInwardLevel : iThisPlotLevel;1710 int iHighestLowestLevel = (iLowestInwardLevel > iThisPlotLevel) ? iLowestInwardLevel : iThisPlotLevel;1711 if(iHighestInwardLevel > iThisPlotLevel)1712 {1713 pPlotToCheck->setScratchPad(iHighestLowestLevel + HALF_BLOCKED);1714 }1715 else1716 {1717 pPlotToCheck->setScratchPad(iHighestLevel);1718 }1719 if(iLowestInwardLevel < iThisPlotLevel || ((iCenterLevel >= iLowestInwardLevel) && (thisRing < iRangeWithOneExtraRing)))1720 { 1721#if defined(MOD_API_EXTENSIONS)1722 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2) ? true : false, pUnit);1723#else1724 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2)?true:false);1725#endif1726 }1727 }1728 }1729 else if(iFirstInwardLevel != INVALID_RING && !bFirstHalfBlocked)1730 {1731 int iHighestLevel = (iFirstInwardLevel > iThisPlotLevel) ? iFirstInwardLevel : iThisPlotLevel;1732 pPlotToCheck->setScratchPad(iHighestLevel);1733 if(iFirstInwardLevel < iThisPlotLevel || ((iCenterLevel >= iFirstInwardLevel) && (thisRing < iRangeWithOneExtraRing)))1734 { 1735#if defined(MOD_API_EXTENSIONS)1736 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2) ? true : false, pUnit);1737#else1738 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2)?true:false);1739#endif1740 }1741 }1742 else if(iSecondInwardLevel != INVALID_RING && !bSecondHalfBlocked)1743 {1744 int iHighestLevel = (iSecondInwardLevel > iThisPlotLevel) ? iSecondInwardLevel : iThisPlotLevel;1745 pPlotToCheck->setScratchPad(iHighestLevel);1746 if(iSecondInwardLevel < iThisPlotLevel || ((iCenterLevel >= iSecondInwardLevel) && (thisRing < iRangeWithOneExtraRing)))1747 { 1748#if defined(MOD_API_EXTENSIONS)1749 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2) ? true : false, pUnit);1750#else1751 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2)?true:false);1752#endif1753 }1754 }1755 else if(iFirstInwardLevel != INVALID_RING)1756 {1757 int iHighestLevel = (iFirstInwardLevel > iThisPlotLevel) ? iFirstInwardLevel : iThisPlotLevel;1758 pPlotToCheck->setScratchPad(iHighestLevel);1759 if(iFirstInwardLevel < iThisPlotLevel || ((iCenterLevel >= iFirstInwardLevel) && (thisRing < iRangeWithOneExtraRing)))1760 {1761#if defined(MOD_API_EXTENSIONS)1762 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2) ? true : false, pUnit);1763#else1764 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2)?true:false);1765#endif1766 }1767 }1768 else if(iSecondInwardLevel != INVALID_RING)1769 {1770 int iHighestLevel = (iSecondInwardLevel > iThisPlotLevel) ? iSecondInwardLevel : iThisPlotLevel;1771 pPlotToCheck->setScratchPad(iHighestLevel);1772 if(iSecondInwardLevel < iThisPlotLevel || ((iCenterLevel >= iSecondInwardLevel) && (thisRing < iRangeWithOneExtraRing)))1773 { 1774#if defined(MOD_API_EXTENSIONS)1775 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2) ? true : false, pUnit);1776#else1777 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2)?true:false);1778#endif1779 }1780 }1781 else // I have no idea how this can happen, but...1782 {1783 // set our value in the scratch pad1784 pPlotToCheck->setScratchPad(iThisPlotLevel);1785 }1786 }1787 else // this is the center point1788 { 1789#if defined(MOD_API_EXTENSIONS)1790 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2) ? true : false, pUnit);1791#else1792 pPlotToCheck->changeVisibilityCount(eTeam, ((bIncrement) ? 1 : -1), eSeeInvisible, true, (bBasedOnUnit && thisRing < 2)?true:false);1793#endif1794 pPlotToCheck->setScratchPad(0);1795 }1796 }17971798 }17991800 int iNextDX;1801 int iNextDY;1802 if(iPlotCounter >= iMaxPlotNumberOnThisRing) // we have processed all of the plots in this ring1803 {1804 // if that fails go out one ring in the NE direction traveling E1805 eDirectionOfNextTileToCheck = DIRECTION_NORTHEAST;1806 iNextDX = iDX + GC.getPlotDirectionX()[eDirectionOfNextTileToCheck];1807 iNextDY = iDY + GC.getPlotDirectionY()[eDirectionOfNextTileToCheck];1808 thisRing++;1809 iMaxPlotNumberOnThisRing += thisRing * 6;1810 eDirectionOfNextTileToCheck = DIRECTION_EAST;1811 // (if that is further out than the extended range, we are done)1812 }1813 else1814 {1815 iNextDX = iDX + GC.getPlotDirectionX()[eDirectionOfNextTileToCheck];1816 iNextDY = iDY + GC.getPlotDirectionY()[eDirectionOfNextTileToCheck];1817 if(hexDistance(iNextDX,iNextDY) > thisRing)1818 {1819 // try to turn right1820 eDirectionOfNextTileToCheck = GC.getTurnRightDirection(eDirectionOfNextTileToCheck);1821 iNextDX = iDX + GC.getPlotDirectionX()[eDirectionOfNextTileToCheck];1822 iNextDY = iDY + GC.getPlotDirectionY()[eDirectionOfNextTileToCheck];1823 }1824 }18251826 iPlotCounter++;18271828 iDX = iNextDX;1829 iDY = iNextDY;1830 pPlotToCheck = plotXYWithRangeCheck(getX(),getY(),iDX,iDY,iRangeWithOneExtraRing);1831 }18321833}