Hooks
static bool BeforeCvNotifications_IsNotificationExpired(CvNotifications* self, int iIndex, bool& result);static void AfterCvNotifications_IsNotificationExpired(CvNotifications* self, int iIndex, bool& result);static bool ReplaceCvNotifications_IsNotificationExpired(bool (*original)(CvNotifications*, int), CvNotifications* self, int iIndex);CivRegisterBefore<CivHooks::CvNotifications_IsNotificationExpired>(host, &BeforeCvNotifications_IsNotificationExpired);CivRegisterAfter<CivHooks::CvNotifications_IsNotificationExpired>(host, &AfterCvNotifications_IsNotificationExpired);CivRegisterReplace<CivHooks::CvNotifications_IsNotificationExpired>(host, &ReplaceCvNotifications_IsNotificationExpired);
Code
1616bool CvNotifications::IsNotificationExpired(int iIndex)1617{1618 switch(m_aNotifications[iIndex].m_eNotificationType)1619 {1620 case NOTIFICATION_BUY_TILE:1621 {1622 if(GET_PLAYER(m_ePlayer).GetTreasury()->GetGold() < GET_PLAYER(m_ePlayer).GetBuyPlotCost())1623 {1624 return true;1625 }1626 }1627 break;16281629 case NOTIFICATION_BARBARIAN:1630 {1631 CvPlot* pPlot = GC.getMap().plot(m_aNotifications[iIndex].m_iX, m_aNotifications[iIndex].m_iY);1632 if(!pPlot->HasBarbarianCamp())1633 {1634 return true;1635 }1636 }1637 break;16381639 case NOTIFICATION_CITY_RANGE_ATTACK:1640 {1641 int iCityID = m_aNotifications[iIndex].m_iGameDataIndex;1642 CvCity* pCity = GET_PLAYER(m_ePlayer).getCity(iCityID);16431644 if(pCity == NULL)1645 return true;16461647 else if(!pCity->CanRangeStrikeNow())1648 return true;1649 }1650 break;16511652 case NOTIFICATION_GOODY:1653 {1654 CvPlot* pPlot = GC.getMap().plot(m_aNotifications[iIndex].m_iX, m_aNotifications[iIndex].m_iY);1655 if(!pPlot->isGoody(GET_PLAYER(m_ePlayer).getTeam()))1656 {1657 return true;1658 }1659 }1660 break;16611662 case NOTIFICATION_TECH:1663 {1664 CvPlayerAI& kPlayer = GET_PLAYER(m_ePlayer);1665 CvPlayerTechs* pkPlayerTechs = kPlayer.GetPlayerTechs();1666 if(pkPlayerTechs->GetCurrentResearch() != NO_TECH)1667 {1668 return true;1669 }16701671 int iNotificationIndex = m_iNotificationsBeginIndex;1672 while(iNotificationIndex != m_iNotificationsEndIndex)1673 {1674 if(NOTIFICATION_FREE_TECH == m_aNotifications[iNotificationIndex].m_eNotificationType)1675 {1676 if(!m_aNotifications[iNotificationIndex].m_bDismissed)1677 {1678 return true;1679 }1680 }16811682 iNotificationIndex++;1683 if(iNotificationIndex >= (int)m_aNotifications.size())1684 {1685 iNotificationIndex = 0;1686 }1687 }16881689 //Expire this notification if there are no more techs that can be researched at this time.1690 return pkPlayerTechs->GetNumTechsCanBeResearched() == 0;1691 }1692 break;1693 case NOTIFICATION_FREE_TECH:1694 {1695 CvPlayerAI& kPlayer = GET_PLAYER(m_ePlayer);1696 if(kPlayer.GetNumFreeTechs() == 0)1697 {1698 return true;1699 }1700 else1701 {1702 //Expire this notification if there are no more techs that can be researched at this time.1703 return kPlayer.GetPlayerTechs()->GetNumTechsCanBeResearched() == 0;1704 }1705 }1706 break;17071708 case NOTIFICATION_FREE_POLICY:1709 {1710 if(GC.getGame().isOption(GAMEOPTION_POLICY_SAVING))1711 {1712 if(GET_PLAYER(m_ePlayer).GetNumFreePolicies() == 0 && GET_PLAYER(m_ePlayer).GetNumFreeTenets() == 0)1713 return true;1714 }1715 else1716 {1717 if((GET_PLAYER(m_ePlayer).getJONSCulture() < GET_PLAYER(m_ePlayer).getNextPolicyCost() && GET_PLAYER(m_ePlayer).GetNumFreePolicies() == 0 && GET_PLAYER(m_ePlayer).GetNumFreeTenets() == 0))1718 return true;1719 }1720 }1721 break;17221723 case NOTIFICATION_FREE_GREAT_PERSON:1724 {1725 if(GET_PLAYER(m_ePlayer).GetNumFreeGreatPeople() == 0)1726 {1727 return true;1728 }1729 }1730 break;17311732 case NOTIFICATION_MAYA_LONG_COUNT:1733 {1734 if(GET_PLAYER(m_ePlayer).GetNumMayaBoosts() == 0)1735 {1736 return true;1737 }1738 }1739 break;17401741 case NOTIFICATION_FAITH_GREAT_PERSON:1742 {1743 if(GET_PLAYER(m_ePlayer).GetNumFaithGreatPeople() == 0)1744 {1745 return true;1746 }1747 }1748 break;17491750 case NOTIFICATION_POLICY:1751 {1752 if(GET_PLAYER(m_ePlayer).getJONSCulture() < GET_PLAYER(m_ePlayer).getNextPolicyCost() && GET_PLAYER(m_ePlayer).GetNumFreePolicies() == 0 && GET_PLAYER(m_ePlayer).GetNumFreeTenets() == 0)1753 {1754 return true;1755 }1756 }1757 break;1758 case NOTIFICATION_PRODUCTION:1759 {1760 //CvCity* pCity = GET_PLAYER(m_ePlayer).getCity(m_aNotifications[iIndex].m_iGameDataIndex);1761 CvCity* pCity = GC.getMap().plot(m_aNotifications[iIndex].m_iX, m_aNotifications[iIndex].m_iY)->getPlotCity();//GET_PLAYER(m_ePlayer).getCity(notification.m_iGameDataIndex);17621763 // if the city no longer exists1764 if(!pCity)1765 {1766 return true;1767 }17681769 // if the city is a puppet1770 if(pCity->IsPuppet())1771 {1772 return true;1773 }17741775 // City has chosen something1776 if(pCity->getOrderQueueLength() > 0)1777 {1778 return true;1779 }1780 }1781 break;1782#if defined(MOD_UI_CITY_EXPANSION)1783 case NOTIFICATION_CITY_TILE:1784 {1785 if (MOD_UI_CITY_EXPANSION) {1786 CvCity* pCity = GC.getMap().plot(m_aNotifications[iIndex].m_iX, m_aNotifications[iIndex].m_iY)->getPlotCity();17871788 // if the city no longer exists, is a puppet, or doesn't belong to the active player1789 if (!pCity || pCity->IsPuppet() || (pCity->getOwner() != GC.getGame().getActivePlayer())) {1790 // we no longer need the notification1791 return true;1792 }17931794 // if the city has choosen a tile (probably by cycling the cities after the first notification)1795 if (pCity->GetJONSCultureStored() < pCity->GetJONSCultureThreshold()) {1796 // we no longer need the notification1797 return true;1798 }1799 }1800 }1801 break;1802#endif1803 case NOTIFICATION_DIPLO_VOTE:1804 {1805 TeamTypes eTeam = GET_PLAYER(m_ePlayer).getTeam();18061807 // Vote from this team registered1808 if(GC.getGame().GetVoteCast(eTeam) != NO_TEAM)1809 {1810 return true;1811 }18121813 // Votes from ALL teams registered. This is necessary in addition to the above if block, because if this player is the last to vote1814 // then everything gets reset immediately, and it'll be NO_TEAM by the time this function is tested again1815 if(GC.getGame().GetNumVictoryVotesExpected() == 0)1816 {1817 return true;1818 }1819 }1820 break;1821 case NOTIFICATION_UNIT_PROMOTION:1822 {1823 UnitHandle pUnit = GET_PLAYER(m_ePlayer).getUnit(m_aNotifications[iIndex].m_iExtraGameData);1824 if(!pUnit || !pUnit->isPromotionReady())1825 {1826 return true;1827 }1828 }1829 break;1830 case NOTIFICATION_PLAYER_DEAL:1831 {1832 CvGame& game = GC.getGame();1833 CvGameDeals* pDeals = game.GetGameDeals();18341835#if defined(MOD_AI_MP_DIPLOMACY)1836 bool bCond = (MOD_AI_MP_DIPLOMACY) ?1837 (pDeals->GetProposedDeal(m_ePlayer, (PlayerTypes)(m_aNotifications[iIndex].m_iX), true) == NULL) :1838 (!pDeals->ProposedDealExists(m_ePlayer, (PlayerTypes)(m_aNotifications[iIndex].m_iX)));1839 if(bCond)1840#else1841 if(!pDeals->ProposedDealExists(m_ePlayer, (PlayerTypes)(m_aNotifications[iIndex].m_iX)))1842#endif1843 {1844 return true;1845 }1846 }1847 break;1848 case NOTIFICATION_PLAYER_DEAL_RECEIVED:1849 {1850 CvGame& game = GC.getGame();1851 CvGameDeals* pDeals = game.GetGameDeals();18521853#if defined(MOD_AI_MP_DIPLOMACY)1854 if (MOD_AI_MP_DIPLOMACY) {1855 PlayerTypes eFrom = static_cast<PlayerTypes>(m_aNotifications[iIndex].m_iX);1856 if (m_aNotifications[iIndex].m_iY != -1 /* no deal request */)1857 {1858 // TODO: check why AI to human deal notifications don't expire here1859 return false;1860 }1861 else if (game.GetGameDeals()->GetProposedDeal(eFrom, m_ePlayer, true) == NULL)1862 {1863 return true;1864 }1865 } else {1866#endif1867 if(!pDeals->ProposedDealExists((PlayerTypes)(m_aNotifications[iIndex].m_iX), m_ePlayer))1868 {1869 return true;1870 }1871#if defined(MOD_AI_MP_DIPLOMACY)1872 }1873#endif1874 }1875 break;1876 case NOTIFICATION_DEMAND_RESOURCE:1877 {1878 // if this is a "you ran out of this resource" demand resource.1879 // I did this so not to break the save format1880 if(m_aNotifications[iIndex].m_iX == -1 && m_aNotifications[iIndex].m_iY == -1)1881 {1882 if(GET_PLAYER(m_ePlayer).getNumResourceAvailable((ResourceTypes)m_aNotifications[iIndex].m_iGameDataIndex, true) >= 0)1883 {1884 return true;1885 }1886 }1887 }18881889 case NOTIFICATION_FOUND_PANTHEON:1890 {1891 CvGame& kGame(GC.getGame());1892 CvGameReligions* pkReligions(kGame.GetGameReligions());1893 return pkReligions->CanCreatePantheon(m_ePlayer, true) != CvGameReligions::FOUNDING_OK;1894 }1895 break;18961897 case NOTIFICATION_ADD_REFORMATION_BELIEF:1898 {1899 CvGame& kGame(GC.getGame());1900 CvGameReligions* pkReligions(kGame.GetGameReligions());1901 return pkReligions->HasAddedReformationBelief(m_ePlayer);1902 }19031904 case NOTIFICATION_FOUND_RELIGION:1905 {1906 CvGame& kGame(GC.getGame());1907 CvGameReligions* pkReligions(kGame.GetGameReligions());1908 if (pkReligions->GetNumReligionsStillToFound() <= 0)1909 return true; // None left, dismiss the notification19101911 return pkReligions->HasCreatedReligion(m_ePlayer);1912 }1913 break;19141915 case NOTIFICATION_ENHANCE_RELIGION:1916 {1917 CvGame& kGame(GC.getGame());1918 CvGameReligions* pkReligions(kGame.GetGameReligions());1919#if defined(MOD_EVENTS_ACQUIRE_BELIEFS)1920 ReligionTypes eReligion = pkReligions->GetReligionCreatedByPlayer(m_ePlayer);1921 if (pkReligions->GetAvailableEnhancerBeliefs(m_ePlayer, eReligion).size() == 0)1922 return true; // None left, dismiss the notification.1923 if (pkReligions->GetAvailableFollowerBeliefs(m_ePlayer, eReligion).size() == 0)1924 return true; // None left, dismiss the notification. 1925#else1926 if (pkReligions->GetAvailableEnhancerBeliefs().size() == 0)1927 return true; // None left, dismiss the notification.1928 if (pkReligions->GetAvailableFollowerBeliefs().size() == 0)1929 return true; // None left, dismiss the notification. 19301931 ReligionTypes eReligion = pkReligions->GetReligionCreatedByPlayer(m_ePlayer);1932#endif1933 const CvReligion* pReligion = pkReligions->GetReligion(eReligion, m_ePlayer);1934 return (NULL != pReligion && pReligion->m_bEnhanced);1935 }1936 break;19371938 case NOTIFICATION_SPY_STOLE_TECH:1939 {1940 CvPlayerEspionage* pEspionage = GET_PLAYER(m_ePlayer).GetEspionage();1941 if (pEspionage->m_aiNumTechsToStealList[m_aNotifications[iIndex].m_iGameDataIndex] <= 0)1942 {1943 return true;1944 }1945 else1946 {1947 return false;1948 }1949 }1950 break;19511952 case NOTIFICATION_LEAGUE_CALL_FOR_PROPOSALS:1953 {1954 LeagueTypes eLeague = (LeagueTypes) m_aNotifications[iIndex].m_iGameDataIndex;1955 CvLeague* pLeague = GC.getGame().GetGameLeagues()->GetLeague(eLeague);1956 if (!pLeague->CanPropose(m_ePlayer))1957 {1958 return true;1959 }1960 else1961 {1962 return false;1963 }1964 }1965 break;19661967 case NOTIFICATION_CHOOSE_ARCHAEOLOGY:1968 {1969 if (GET_PLAYER(m_ePlayer).GetNumArchaeologyChoices() == 0)1970 {1971 return true;1972 }1973 }1974 break;19751976 case NOTIFICATION_CHOOSE_IDEOLOGY:1977 {1978 if (GET_PLAYER(m_ePlayer).GetPlayerPolicies()->GetLateGamePolicyTree() != NO_POLICY_BRANCH_TYPE)1979 {1980 return true;1981 }1982 }1983 break;19841985 case NOTIFICATION_LEAGUE_CALL_FOR_VOTES:1986 {1987 LeagueTypes eLeague = (LeagueTypes) m_aNotifications[iIndex].m_iGameDataIndex;1988 CvLeague* pLeague = GC.getGame().GetGameLeagues()->GetLeague(eLeague);1989 if (!pLeague->CanVote(m_ePlayer))1990 {1991 return true;1992 }1993 else1994 {1995 return false;1996 }1997 }1998 break;19992000 case NOTIFICATION_PLAYER_CONNECTING:2001 {2002 if(!gDLL->IsPlayerHotJoining(m_aNotifications[iIndex].m_iGameDataIndex)){2003 //Player has finished hot joining. Remove this notification, we'll add a NOTIFICATION_PLAYER_RECONNECTED in NetProxy::OnHotJoinComplete().2004 return true;2005 }2006 }2007 break;20082009 default: // don't expire2010 {2011 return false;2012 }2013 break;2014 }20152016 return false;2017}