Hooks
static bool BeforeCvPlayer_canConstruct(const CvPlayer* self, BuildingTypes eBuilding, bool bContinue, bool bTestVisible, bool bIgnoreCost, CvString* toolTipSink, bool& result);static void AfterCvPlayer_canConstruct(const CvPlayer* self, BuildingTypes eBuilding, bool bContinue, bool bTestVisible, bool bIgnoreCost, CvString* toolTipSink, bool& result);static bool ReplaceCvPlayer_canConstruct(bool (*original)(const CvPlayer*, BuildingTypes, bool, bool, bool, CvString*), const CvPlayer* self, BuildingTypes eBuilding, bool bContinue, bool bTestVisible, bool bIgnoreCost, CvString* toolTipSink);CivRegisterBefore<CivHooks::CvPlayer_canConstruct>(host, &BeforeCvPlayer_canConstruct);CivRegisterAfter<CivHooks::CvPlayer_canConstruct>(host, &AfterCvPlayer_canConstruct);CivRegisterReplace<CivHooks::CvPlayer_canConstruct>(host, &ReplaceCvPlayer_canConstruct);
Code
7957bool CvPlayer::canConstruct(BuildingTypes eBuilding, bool bContinue, bool bTestVisible, bool bIgnoreCost, CvString* toolTipSink) const7958{7959 CvBuildingEntry* pkBuildingInfo = GC.getBuildingInfo(eBuilding);7960 if(pkBuildingInfo == NULL)7961 return false;79627963 // Don't allow a city to consider an espionage building if they are playing a non-espionage game7964 if(GC.getGame().isOption(GAMEOPTION_NO_ESPIONAGE) && pkBuildingInfo->IsEspionage())7965 {7966 return false;7967 }79687969 CvBuildingEntry& pBuildingInfo = *pkBuildingInfo;79707971 int iI;7972 CvTeam& currentTeam = GET_TEAM(getTeam());79737974 const BuildingClassTypes eBuildingClass = ((BuildingClassTypes)(pBuildingInfo.GetBuildingClassType()));7975 const CvBuildingClassInfo& kBuildingClass = pkBuildingInfo->GetBuildingClassInfo();79767977 // Checks to make sure civilization doesn't have an override that prevents construction of this building7978 if(getCivilizationInfo().getCivilizationBuildings(eBuildingClass) != eBuilding)7979 {7980 return false;7981 }79827983 if(!bIgnoreCost)7984 {7985 if(pBuildingInfo.GetProductionCost() == -1)7986 {7987 return false;7988 }7989 }79907991 PolicyBranchTypes eBranch = (PolicyBranchTypes)pBuildingInfo.GetPolicyBranchType();7992 if (eBranch != NO_POLICY_BRANCH_TYPE)7993 {7994 if (!GetPlayerPolicies()->IsPolicyBranchUnlocked(eBranch))7995 {7996 return false;7997 }7998 }79998000 if(!(currentTeam.GetTeamTechs()->HasTech((TechTypes)(pBuildingInfo.GetPrereqAndTech()))))8001 {8002 return false;8003 }80048005 for(iI = 0; iI < GC.getNUM_BUILDING_AND_TECH_PREREQS(); iI++)8006 {8007 if(pBuildingInfo.GetPrereqAndTechs(iI) != NO_TECH)8008 {8009 if(!(currentTeam.GetTeamTechs()->HasTech((TechTypes)(pBuildingInfo.GetPrereqAndTechs(iI)))))8010 {8011 return false;8012 }8013 }8014 }80158016 if(currentTeam.isObsoleteBuilding(eBuilding))8017 {8018 return false;8019 }80208021 // Building upgrade to another type8022 BuildingClassTypes eReplacementBuildingClass = (BuildingClassTypes) pBuildingInfo.GetReplacementBuildingClass();80238024 if(eReplacementBuildingClass != NO_BUILDINGCLASS)8025 {8026 BuildingTypes eUpgradeBuilding = ((BuildingTypes)(getCivilizationInfo().getCivilizationBuildings(eReplacementBuildingClass)));80278028 if(canConstruct(eUpgradeBuilding))8029 {8030 return false;8031 }8032 }80338034 if(pBuildingInfo.GetVictoryPrereq() != NO_VICTORY)8035 {8036 if(!(GC.getGame().isVictoryValid((VictoryTypes)(pBuildingInfo.GetVictoryPrereq()))))8037 {8038 return false;8039 }80408041 if(isMinorCiv())8042 {8043 return false;8044 }80458046 if(currentTeam.getVictoryCountdown((VictoryTypes)pBuildingInfo.GetVictoryPrereq()) >= 0)8047 {8048 return false;8049 }8050 }80518052 if(pBuildingInfo.GetMaxStartEra() != NO_ERA)8053 {8054 if(GC.getGame().getStartEra() > pBuildingInfo.GetMaxStartEra())8055 {8056 return false;8057 }8058 }80598060 if(GC.getGame().isBuildingClassMaxedOut(eBuildingClass))8061 {8062 return false;8063 }80648065 if(currentTeam.isBuildingClassMaxedOut(eBuildingClass))8066 {8067 return false;8068 }80698070 if(isBuildingClassMaxedOut(eBuildingClass))8071 {8072 return false;8073 }80748075 ///////////////////////////////////////////////////////////////////////////////////8076 // Everything above this is what is checked to see if Building shows up in the list of construction items8077 ///////////////////////////////////////////////////////////////////////////////////80788079 if(!bTestVisible)8080 {8081 // Num buildings in the empire... uhhh, how is this different from the very last check in this function? (JON: It doesn't appear to be used, but I can't say for sure :)8082 CvCivilizationInfo& civilizationInfo = getCivilizationInfo();8083 int numBuildingClassInfos = GC.getNumBuildingClassInfos();80848085 for(iI = 0; iI < numBuildingClassInfos; iI++)8086 {8087 CvBuildingClassInfo* pkBuildingClassInfo = GC.getBuildingClassInfo((BuildingClassTypes)iI);8088 if(!pkBuildingClassInfo)8089 {8090 continue;8091 }80928093 BuildingTypes ePrereqBuilding = (BuildingTypes)civilizationInfo.getCivilizationBuildings(iI);80948095 if(NO_BUILDING != ePrereqBuilding && currentTeam.isObsoleteBuilding(ePrereqBuilding))8096 {8097 CvBuildingEntry* pkPrereqBuilding = GC.getBuildingInfo(ePrereqBuilding);8098 if(pkPrereqBuilding)8099 {8100 int iNumHave = getBuildingClassCount((BuildingClassTypes)iI);81018102 int iNumNeeded = getBuildingClassPrereqBuilding(eBuilding, (BuildingClassTypes)iI, 0);81038104 if(iNumHave < iNumNeeded)8105 {8106 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_BUILDING_COUNT_NEEDED", pkPrereqBuilding->GetTextKey(), "", iNumNeeded - iNumHave);81078108 if(toolTipSink == NULL)8109 return false;8110 }8111 }8112 }8113 }81148115 // Resource Requirements8116 for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)8117 {8118 const ResourceTypes eResource = static_cast<ResourceTypes>(iResourceLoop);8119 CvResourceInfo* pkResource = GC.getResourceInfo(eResource);8120 if(pkResource)8121 {8122 int iNumResource = pBuildingInfo.GetResourceQuantityRequirement(eResource);8123 if(iNumResource > 0)8124 {8125 if(bContinue)8126 iNumResource = 0;81278128 if(getNumResourceAvailable(eResource) < iNumResource)8129 {8130 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_BUILDING_LACKS_RESOURCES", pkResource->GetIconString(), pkResource->GetTextKey(), iNumResource);8131 if(toolTipSink == NULL)8132 return false;8133 }8134 }8135 }8136 }81378138 if(GC.getGame().isBuildingClassMaxedOut(eBuildingClass, (currentTeam.getBuildingClassMaking(eBuildingClass) + ((bContinue) ? -1 : 0))))8139 {8140 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_GAME_COUNT_MAX", "", "", kBuildingClass.getMaxGlobalInstances());8141 if(toolTipSink == NULL)8142 return false;8143 }81448145 if(currentTeam.isBuildingClassMaxedOut(eBuildingClass, (currentTeam.getBuildingClassMaking(eBuildingClass) + ((bContinue) ? -1 : 0))))8146 {8147 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_TEAM_COUNT_MAX", "", "", kBuildingClass.getMaxTeamInstances());8148 if(toolTipSink == NULL)8149 return false;8150 }81518152 if(isBuildingClassMaxedOut(eBuildingClass, (getBuildingClassMaking(eBuildingClass) + ((bContinue) ? -1 : 0))))8153 {8154 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_PLAYER_COUNT_MAX", "", "", kBuildingClass.getMaxPlayerInstances());8155 if(toolTipSink == NULL)8156 return false;8157 }81588159 if(getNumCities() < pBuildingInfo.GetNumCitiesPrereq())8160 {8161 return false;8162 }81638164 if(getHighestUnitLevel() < pBuildingInfo.GetUnitLevelPrereq())8165 {8166 return false;8167 }81688169 // How does this differ from the check above?8170 BuildingTypes ePrereqBuilding;8171 int iNumNeeded;8172 for(iI = 0; iI < numBuildingClassInfos; iI++)8173 {8174 iNumNeeded = getBuildingClassPrereqBuilding(eBuilding, ((BuildingClassTypes)iI), bContinue);8175 //int iNumHave = getBuildingClassCount((BuildingClassTypes)iI);8176 ePrereqBuilding = (BuildingTypes) civilizationInfo.getCivilizationBuildings(iI);8177 if(NO_BUILDING != ePrereqBuilding)8178 {8179 CvBuildingEntry* pkPrereqBuilding = GC.getBuildingInfo(ePrereqBuilding);8180 if(pkPrereqBuilding)8181 {8182 int iNumHave = 0;8183 const CvCity* pLoopCity = NULL;8184 int iLoop;8185 for(pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))8186 {8187 if(pLoopCity && !pLoopCity->IsPuppet() && pLoopCity->GetCityBuildings()->GetNumBuilding(ePrereqBuilding) > 0)8188 {8189 iNumHave++;8190 }8191 }81928193 if(iNumHave < iNumNeeded)8194 {8195 ePrereqBuilding = (BuildingTypes) civilizationInfo.getCivilizationBuildings(iI);81968197 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_BUILDING_COUNT_NEEDED", pkPrereqBuilding->GetTextKey(), "", iNumNeeded - iNumHave);81988199 if(toolTipSink == NULL)8200 return false;82018202 // If we have less than 5 to go, list what cities need them8203 int iNonPuppetCities = getNumCities() - GetNumPuppetCities();8204 if(iNumNeeded == iNonPuppetCities && iNumNeeded - iNumHave < 5)8205 {8206 (*toolTipSink) += "[NEWLINE]";82078208 for(pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))8209 {8210 if(pLoopCity && !pLoopCity->IsPuppet() && pLoopCity->GetCityBuildings()->GetNumBuilding(ePrereqBuilding) == 0)8211 {8212 (*toolTipSink) += pLoopCity->getName();8213 (*toolTipSink) += " ";8214 }8215 }8216 }8217 }8218 }8219 }8220 }8221 }82228223 ICvEngineScriptSystem1* pkScriptSystem = gDLL->GetScriptSystem();8224 if(pkScriptSystem)8225 {8226 CvLuaArgsHandle args;8227 args->Push(GetID());8228 args->Push(eBuilding);82298230 // Attempt to execute the game events.8231 // Will return false if there are no registered listeners.8232 bool bResult = false;8233 if(LuaSupport::CallTestAll(pkScriptSystem, "PlayerCanConstruct", args.get(), bResult))8234 {8235 // Check the result.8236 if(bResult == false)8237 {8238 return false;8239 }8240 }8241 }82428243 return true;8244}