//------------------------------------------------------------------------------ void CvDllNetMessageHandler::ResponsePushMission(PlayerTypes ePlayer, int iUnitID, MissionTypes eMission, int iData1, int iData2, int iFlags, bool bShift) { CvUnit::dispatchingNetMessage(true); CvPlayerAI& kPlayer = GET_PLAYER(ePlayer); CvUnit* pkUnit = kPlayer.getUnit(iUnitID); if(pkUnit != NULL) { pkUnit->PushMission(eMission, iData1, iData2, iFlags, bShift, true); } CvUnit::dispatchingNetMessage(false); }
//------------------------------------------------------------------------------ void CvDllNetMessageHandler::ResponseGreatPersonChoice(PlayerTypes ePlayer, UnitTypes eGreatPersonUnit) { CvPlayerAI& kPlayer = GET_PLAYER(ePlayer); CvCity* pCity = kPlayer.GetGreatPersonSpawnCity(eGreatPersonUnit); if(pCity) { #if defined(MOD_GLOBAL_TRULY_FREE_GP) pCity->GetCityCitizens()->DoSpawnGreatPerson(eGreatPersonUnit, true, false, MOD_GLOBAL_TRULY_FREE_GP); #else pCity->GetCityCitizens()->DoSpawnGreatPerson(eGreatPersonUnit, true, false); #endif } kPlayer.ChangeNumFreeGreatPeople(-1); }
//------------------------------------------------------------------------------ void CvDllNetMessageHandler::ResponseStageCoup(PlayerTypes eSpyPlayer, int iSpyIndex) { CvAssertMsg(eSpyPlayer != NO_PLAYER, "eSpyPlayer invalid"); CvAssertMsg(iSpyIndex >= 0, "iSpyIndex invalid"); CvPlayerAI& kPlayer = GET_PLAYER(eSpyPlayer); CvPlayerEspionage* pPlayerEspionage = kPlayer.GetEspionage(); CvAssertMsg(pPlayerEspionage, "pPlayerEspionage is null"); if(pPlayerEspionage) { bool bCoupSuccess = pPlayerEspionage->AttemptCoup(iSpyIndex); } }
//------------------------------------------------------------------------------ void CvAchievementUnlocker::AlexanderConquest(PlayerTypes ePlayer) { //Test For Alexander Conquest CvGame& kGame = GC.getGame(); if (ePlayer == kGame.getActivePlayer()) { CvString szLeaderName = (CvString)GET_PLAYER(ePlayer).getLeaderTypeKey(); if(szLeaderName == "LEADER_ALEXANDER") { if(kGame.getGameTurnYear() <= 350) { for(int iPlayerLoop = 0; iPlayerLoop < MAX_PLAYERS; iPlayerLoop++) { CvPlayer* pPlayer = &GET_PLAYER((PlayerTypes) iPlayerLoop); //All known players must be dead and killed by us if(GET_TEAM(pPlayer->getTeam()).isHasMet(GET_PLAYER(kGame.getActivePlayer()).getTeam())) { // ---------------------------------------------------------------- // WoTMod Addition // ---------------------------------------------------------------- if(!pPlayer->isBarbarian() && !pPlayer->isMinorCiv() && !pPlayer->IsShadowspawn()) { if(pPlayer->isAlive() && pPlayer->GetID() != GET_PLAYER(kGame.getActivePlayer()).GetID()) { return; // Nope. } } } } // Yep. gDLL->UnlockAchievement(ACHIEVEMENT_SPECIAL_CONQUEST_WORLD); } } } }
void CvNetAutoMission::Execute() { if (m_ePlayer != NO_PLAYER) { CvUnit* pUnit = GET_PLAYER(m_ePlayer).getUnit(m_iUnitID); if (pUnit != NULL) { CvSelectionGroup* pSelectionGroup = pUnit->getGroup(); if (pSelectionGroup != NULL) { pSelectionGroup->autoMission(); } } } }
CyPlayer* CyGlobalContext::getCyPlayer(int idx) { static CyPlayer cyPlayers[MAX_PLAYERS]; static bool bInit=false; if (!bInit) { int i; for(i=0;i<MAX_PLAYERS;i++) cyPlayers[i]=CyPlayer(&GET_PLAYER((PlayerTypes)i)); bInit=true; } FAssert(idx>=0); FAssert(idx<MAX_PLAYERS); return idx < MAX_PLAYERS && idx != NO_PLAYER ? &cyPlayers[idx] : NULL; }
// ----------------------------------------------------------------------------------------------- // Loop through all the players and do any deferred updates of their danger plots // static void CvPlayerManager::RefreshDangerPlots() { for (int iPlayerCivLoop = 0; iPlayerCivLoop < MAX_CIV_PLAYERS; iPlayerCivLoop++) { PlayerTypes ePlayer = (PlayerTypes) iPlayerCivLoop; CvPlayer& kPlayer = GET_PLAYER(ePlayer); // Must be alive if (!kPlayer.isAlive()) continue; if (kPlayer.m_pDangerPlots && kPlayer.m_pDangerPlots->IsDirty()) kPlayer.UpdateDangerPlots(); } }
void CvNetPushMission::Execute() { if (m_ePlayer != NO_PLAYER) { CvUnit* pUnit = GET_PLAYER(m_ePlayer).getUnit(m_iUnitID); if (pUnit != NULL) { CvSelectionGroup* pSelectionGroup = pUnit->getGroup(); if (pSelectionGroup != NULL) { pSelectionGroup->pushMission(m_eMission, m_iData1, m_iData2, m_iFlags, m_bShift, true); } } } }
void CvNetPushOrder::Execute() { if (m_ePlayer != NO_PLAYER) { CvCity* pCity = GET_PLAYER(m_ePlayer).getCity(m_iCityID); if (pCity != NULL) { pCity->pushOrder(m_eOrder, m_iData, -1, m_bAlt, !(m_bShift || m_bCtrl), m_bShift); } if (GC.getGameINLINE().getActivePlayer() == m_ePlayer) { gDLL->getInterfaceIFace()->updatePythonScreens(); } } }
// UNIT STRENGTH ACCESSORS /// Total unit power int CvArmyAI::GetTotalPower() { int iRtnValue = 0; for (size_t i = 0; i<m_FormationEntries.size(); i++) { if (!m_FormationEntries[i].IsUsed()) continue; CvUnit* pThisUnit = GET_PLAYER(GetOwner()).getUnit(m_FormationEntries[i].GetUnitID()); if (pThisUnit) iRtnValue += pThisUnit->GetPower(); } return iRtnValue; }
void CvArmyAI::RemoveStuckUnits() { CvAIOperation* pOperation = GET_PLAYER(GetOwner()).getAIOperation(GetOperationID()); for(unsigned int iI = 0; iI < m_FormationEntries.size(); iI++) { if(m_FormationEntries[iI].GetUnitID() > ARMYSLOT_NO_UNIT && m_FormationEntries[iI].GetTurnAtCheckpoint()==ARMYSLOT_UNKNOWN_TURN_AT_CHECKPOINT) { CvString strMsg; strMsg.Format("Removing unit %d from army %d because no path to checkpoint",m_FormationEntries[iI].GetUnitID(),GetID()); pOperation->LogOperationSpecialMessage(strMsg); RemoveUnit(m_FormationEntries[iI].GetUnitID()); } } }
void CvNetPopOrder::Execute() { if (m_ePlayer != NO_PLAYER) { CvCity* pCity = GET_PLAYER(m_ePlayer).getCity(m_iCityID); if (pCity != NULL) { pCity->popOrder(m_iNum); } if (GC.getGameINLINE().getActivePlayer() == m_ePlayer) { gDLL->getInterfaceIFace()->updatePythonScreens(); } } }
//------------------------------------------------------------------------------ void CvDllNetMessageHandler::ResponseUpdatePolicies(PlayerTypes ePlayer, bool bNOTPolicyBranch, int iPolicyID, bool bValue) { CvPlayerAI& kPlayer = GET_PLAYER(ePlayer); // Policy Update if(bNOTPolicyBranch) { const PolicyTypes ePolicy = static_cast<PolicyTypes>(iPolicyID); if(bValue) { kPlayer.doAdoptPolicy(ePolicy); } else { kPlayer.setHasPolicy(ePolicy, bValue); #if defined(MOD_BALANCE_CORE_HAPPINESS) kPlayer.CalculateHappiness(); #else kPlayer.DoUpdateHappiness(); #endif kPlayer.DoUpdateHappiness(); } } // Policy Branch Update else { const PolicyBranchTypes eBranch = static_cast<PolicyBranchTypes>(iPolicyID); CvPlayerPolicies* pPlayerPolicies = kPlayer.GetPlayerPolicies(); // If Branch was blocked by another branch, then unblock this one - this may be the only thing this NetMessage does if(pPlayerPolicies->IsPolicyBranchBlocked(eBranch)) { // Can't switch to a Branch that's still locked. DoUnlockPolicyBranch below will handle this for us if(pPlayerPolicies->IsPolicyBranchUnlocked(eBranch)) { //pPlayerPolicies->ChangePolicyBranchBlockedCount(eBranch, -1); pPlayerPolicies->DoSwitchToPolicyBranch(eBranch); } } // Unlock the branch if it hasn't been already if(!pPlayerPolicies->IsPolicyBranchUnlocked(eBranch)) { pPlayerPolicies->DoUnlockPolicyBranch(eBranch); } } }
void CvGameObjectTeam::foreach(GameObjectTypes eType, boost::function<void (CvGameObject*)> func) { switch(eType) { case GAMEOBJECT_GAME: func(GC.getGameINLINE().getGameObject()); break; case GAMEOBJECT_PLAYER: for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer) { CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer); if (kLoopPlayer.isAlive()) { if (kLoopPlayer.getTeam() == m_pTeam->getID()) { func((CvGameObject*)&CvGameObjectPlayer(&kLoopPlayer)); } } } break; case GAMEOBJECT_CITY: foreach(GAMEOBJECT_PLAYER, boost::bind(callForeach, _1, GAMEOBJECT_CITY, func)); break; case GAMEOBJECT_UNIT: foreach(GAMEOBJECT_PLAYER, boost::bind(callForeach, _1, GAMEOBJECT_UNIT, func)); break; case GAMEOBJECT_PLOT: for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++) { CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI); if (pLoopPlot->getTeam() == m_pTeam->getID()) { func(pLoopPlot->getGameObject()); } } break; case GAMEOBJECT_TEAM: func(this); break; } }
//------------------------------------------------------------------------------ void CvPlayerAchievements::AlliedWithCityState(PlayerTypes eNewCityStateAlly) { #if !defined(NO_ACHIEVEMENTS) if(m_kPlayer.GetID() != GC.getGame().getActivePlayer()) return; //Cache value if needed if(m_ePapalPrimacyType == UNDEFINED_TYPE) { m_ePapalPrimacyType = (BeliefTypes)GC.getInfoTypeForString("BELIEF_PAPAL_PRIMACY", true); } if(m_ePapalPrimacyType != NO_BELIEF) { const ReligionTypes eReligion = m_kPlayer.GetReligions()->GetReligionCreatedByPlayer(); if(eReligion != NO_RELIGION) { const CvReligion* pReligion = GC.getGame().GetGameReligions()->GetReligion(eReligion, m_kPlayer.GetID()); if(pReligion != NULL) { if(pReligion->m_Beliefs.HasBelief(m_ePapalPrimacyType)) { int iNumAllies = 0; //We've got the belief! How many city state Allies do we have?? for(int i = 0; i < MAX_CIV_PLAYERS; ++i) { const PlayerTypes ePlayer = static_cast<PlayerTypes>(i); CvPlayerAI& kPlayer = GET_PLAYER(ePlayer); if(kPlayer.isAlive() && kPlayer.isMinorCiv()) { const PlayerTypes eAlly = kPlayer.GetMinorCivAI()->GetAlly(); if(eAlly == m_kPlayer.GetID()) iNumAllies++; } } if(iNumAllies >= 12) { gDLL->UnlockAchievement(ACHIEVEMENT_XP1_27); } } } } } #endif }
//------------------------------------------------------------------------------ void CvDllNetMessageHandler::ResponseChangeWar(PlayerTypes ePlayer, TeamTypes eRivalTeam, bool bWar) { CvPlayerAI& kPlayer = GET_PLAYER(ePlayer); CvTeam& kTeam = GET_TEAM(kPlayer.getTeam()); const TeamTypes eTeam = kPlayer.getTeam(); FAssert(eTeam != eRivalTeam); if(bWar) { kTeam.declareWar(eRivalTeam); } else { kTeam.makePeace(eRivalTeam); } }
//------------------------------------------------------------------------------ void CvDllNetMessageHandler::ResponseUpdateCityCitizens(PlayerTypes ePlayer, int iCityID) { //there was a crash when this was called while the map is uninitialized if (GC.getMap().numPlots()==0) return; CvCity* pCity = GET_PLAYER(ePlayer).getCity(iCityID); if(NULL != pCity && pCity->GetCityCitizens()) { CvCityCitizens* pkCitizens = pCity->GetCityCitizens(); if(pkCitizens != NULL) { pkCitizens->DoVerifyWorkingPlots(); pkCitizens->DoReallocateCitizens(); } } }
// Get the amount of damage a citadel would deal to a unit int CvDangerPlotContents::GetDamageFromFeatures(PlayerTypes ePlayer) const { if (m_pCitadel && ePlayer != NO_PLAYER) { ImprovementTypes eImprovement = m_pCitadel->getImprovementType(); CvTeam& kTeam = GET_TEAM(GET_PLAYER(ePlayer).getTeam()); // Citadel still here and can fire? if (eImprovement != NO_IMPROVEMENT && !m_pCitadel->IsImprovementPillaged() && m_pCitadel->getOwner() != NO_PLAYER && kTeam.isAtWar(m_pCitadel->getTeam())) { return GC.getImprovementInfo(eImprovement)->GetNearbyEnemyDamage(); } } return 0; };
// UNIT STRENGTH ACCESSORS /// Total unit power int CvArmyAI::GetTotalPower() { int iRtnValue = 0; int iUnitID; iUnitID = GetFirstUnitID(); while(iUnitID != ARMYSLOT_NO_UNIT) { UnitHandle pThisUnit = GET_PLAYER(GetOwner()).getUnit(iUnitID); if(pThisUnit) { iRtnValue += pThisUnit->GetPower(); } iUnitID = GetNextUnitID(); } return iRtnValue; }
/// Should this player be ignored when creating the danger plots? bool CvDangerPlots::ShouldIgnorePlayer(PlayerTypes ePlayer) { if(GET_PLAYER(m_ePlayer).isMinorCiv() != GET_PLAYER(ePlayer).isMinorCiv() && !GET_PLAYER(ePlayer).isBarbarian() && !GET_PLAYER(m_ePlayer).isBarbarian()) { CvPlayer* pMinor = NULL; CvPlayer* pMajor; if(GET_PLAYER(m_ePlayer).isMinorCiv()) { pMinor = &GET_PLAYER(m_ePlayer); pMajor = &GET_PLAYER(ePlayer); } else { pMinor = &GET_PLAYER(ePlayer); pMajor = &GET_PLAYER(m_ePlayer); } if(pMinor->GetMinorCivAI()->IsFriends(pMajor->GetID())) { return true; } // if we're a major, we should ignore minors that are not at war with us if (!GET_PLAYER(m_ePlayer).isMinorCiv()) { TeamTypes eMajorTeam = pMajor->getTeam(); TeamTypes eMinorTeam = pMinor->getTeam(); if (!GET_TEAM(eMajorTeam).isAtWar(eMinorTeam)) { return true; } } } return false; }
//------------------------------------------------------------------------------ void CvDllNetMessageHandler::ResponseFoundPantheon(PlayerTypes ePlayer, BeliefTypes eBelief) { CvGame& kGame(GC.getGame()); CvGameReligions* pkGameReligions(kGame.GetGameReligions()); CvBeliefXMLEntries* pkBeliefs = GC.GetGameBeliefs(); CvBeliefEntry* pEntry = pkBeliefs->GetEntry((int)eBelief); // Pantheon belief, or adding one through Reformation? if (pEntry && ePlayer != NO_PLAYER) { if (pEntry->IsPantheonBelief()) { CvGameReligions::FOUNDING_RESULT eResult = pkGameReligions->CanCreatePantheon(ePlayer, true); if(eResult == CvGameReligions::FOUNDING_OK) { #if defined(MOD_TRAITS_ANY_BELIEF) if(pkGameReligions->IsPantheonBeliefAvailable(eBelief, ePlayer)) #else if(pkGameReligions->IsPantheonBeliefAvailable(eBelief)) #endif { pkGameReligions->FoundPantheon(ePlayer, eBelief); } else { CvGameReligions::NotifyPlayer(ePlayer, CvGameReligions::FOUNDING_BELIEF_IN_USE); } } else { CvGameReligions::NotifyPlayer(ePlayer, eResult); } } else if (pEntry->IsReformationBelief()) { CvPlayerAI& kPlayer = GET_PLAYER(ePlayer); if (!pkGameReligions->HasAddedReformationBelief(ePlayer) && kPlayer.GetReligions()->HasCreatedReligion()) { ReligionTypes eReligion = kPlayer.GetReligions()->GetReligionCreatedByPlayer(); pkGameReligions->AddReformationBelief(ePlayer, eReligion, eBelief); } } } }
bool CvSelectionGroupAI::AI_separateImpassable() { CvPlayerAI& kPlayer = GET_PLAYER(getOwner()); bool bSeparated = false; CLLNode<IDInfo>* pEntityNode = headUnitNode(); while (pEntityNode != NULL) { CvUnit* pLoopUnit = ::getUnit(pEntityNode->m_data); pEntityNode = nextUnitNode(pEntityNode); if (kPlayer.AI_unitImpassableCount(pLoopUnit->getUnitType()) > 0) { pLoopUnit->joinGroup(NULL); bSeparated = true; } } return bSeparated; }
/// Is this part of an operation that allows units to be poached by tactical AI? bool CvArmyAI::CanTacticalAIInterruptUnit(int /* iUnitId */) const { // If the operation is still assembling, by all means interrupt it if(m_eAIState == ARMYAISTATE_WAITING_FOR_UNITS_TO_REINFORCE || m_eAIState == ARMYAISTATE_WAITING_FOR_UNITS_TO_CATCH_UP) { return true; } if(m_eOwner >=0 && m_eOwner < MAX_PLAYERS) { CvAIOperation* op = GET_PLAYER(m_eOwner).getAIOperation(m_iOperationID); if(op) { return op->CanTacticalAIInterruptOperation(); } } return false; }
/// Recalculate when each unit will arrive on target void CvArmyAI::UpdateCheckpointTurns() { for(unsigned int iI = 0; iI < m_FormationEntries.size(); iI++) { // No reestimate for units being built if(m_FormationEntries[iI].GetUnitID() != ARMY_NO_UNIT) { CvUnit* pUnit = GET_PLAYER(m_eOwner).getUnit(m_FormationEntries[iI].GetUnitID()); CvPlot* pMusterPlot = GC.getMap().plot(GetX(), GetY()); if(pUnit && pMusterPlot) { int iTurnsToReachCheckpoint = pUnit->TurnsToReachTarget(pMusterPlot, false, true, true); if(iTurnsToReachCheckpoint < MAX_INT) SetEstimatedTurn(iI, iTurnsToReachCheckpoint); else SetEstimatedTurn(iI, ARMYSLOT_UNKNOWN_TURN_AT_CHECKPOINT); } } } }
/// Delete the army void CvArmyAI::Kill() { CvAssert(GetOwner() != NO_PLAYER); CvAssertMsg(GetID() != FFreeList::INVALID_INDEX, "GetID() is not expected to be equal with FFreeList::INVALID_INDEX"); int iUnitID; iUnitID = GetFirstUnitID(); while(iUnitID != ARMY_NO_UNIT) { UnitHandle pThisUnit = GET_PLAYER(GetOwner()).getUnit(iUnitID); if(pThisUnit) { pThisUnit->setArmyID(FFreeList::INVALID_INDEX); } iUnitID = GetNextUnitID(); } m_FormationEntries.clear(); }
/// Recalculate when each unit will arrive on target void CvArmyAI::UpdateCheckpointTurns() { for(unsigned int iI = 0; iI < m_FormationEntries.size(); iI++) { // No reestimate for units being built if(m_FormationEntries[iI].GetUnitID() != ARMY_NO_UNIT) { CvUnit* pUnit = GET_PLAYER(m_eOwner).getUnit(m_FormationEntries[iI].GetUnitID()); CvPlot* pMusterPlot = GC.getMap().plot(GetX(), GetY()); if(pUnit && pMusterPlot) { int iTurnsToReachCheckpoint = TurnsToReachTarget(pUnit, pMusterPlot, true /*bReusePaths*/, true, true); if(iTurnsToReachCheckpoint < MAX_INT) { SetEstimatedTurn(iI, iTurnsToReachCheckpoint); } } } } }
//------------------------------------------------------------------------------ void CvDllNetMessageHandler::ResponseSellBuilding(PlayerTypes ePlayer, int iCityID, BuildingTypes eBuilding) { CvCity* pCity = GET_PLAYER(ePlayer).getCity(iCityID); if(pCity) { pCity->GetCityBuildings()->DoSellBuilding(eBuilding); ICvEngineScriptSystem1* pkScriptSystem = gDLL->GetScriptSystem(); if (pkScriptSystem) { CvLuaArgsHandle args; args->Push(ePlayer); args->Push(iCityID); args->Push(eBuilding); bool bResult; LuaSupport::CallHook(pkScriptSystem, "CitySoldBuilding", args.get(), bResult); } } }
/// Log all potential builds void CvProjectProductionAI::LogPossibleBuilds() { if(GC.getLogging() && GC.getAILogging()) { CvString strOutBuf; CvString strBaseString; CvString strTemp; CvString playerName; CvString cityName; CvString strDesc; CvString strLogName; CvAssert(m_pCity); if(!m_pCity) return; // Find the name of this civ and city playerName = GET_PLAYER(m_pCity->getOwner()).getCivilizationShortDescription(); cityName = m_pCity->getName(); // Open the log file FILogFile* pLog; pLog = LOGFILEMGR.GetLog(m_pCity->GetCityStrategyAI()->GetLogFileName(playerName, cityName), FILogFile::kDontTimeStamp); CvAssert(pLog); if(!pLog) return; // Get the leading info for this line strBaseString.Format("%03d, ", GC.getGame().getElapsedGameTurns()); strBaseString += playerName + ", " + cityName + ", "; // Dump out the weight of each buildable item for(int iI = 0; iI < m_Buildables.size(); iI++) { CvProjectEntry* pProjectEntry = GC.GetGameProjects()->GetEntry(m_Buildables.GetElement(iI)); strDesc = (pProjectEntry != NULL)? pProjectEntry->GetDescription() : "Unknown"; strTemp.Format("Project, %s, %d", strDesc.GetCString(), m_Buildables.GetWeight(iI)); strOutBuf = strBaseString + strTemp; pLog->Msg(strOutBuf); } } }
// TAC - AI Explore from Ship endless loop fix - koma13 - START bool CvArea::isEuropePlayer() const { if (isWater()) { return false; } for (int iI = 0; iI < MAX_PLAYERS; iI++) { CvPlayerAI& kLoopPlayer = GET_PLAYER((PlayerTypes)iI); if (kLoopPlayer.isAlive() && !kLoopPlayer.isNative()) { if (this->getCitiesPerPlayer((PlayerTypes)iI) > 0) { return true; } } } return false; }
CvPlot* CvArmyAI::CheckTargetReached(PlayerTypes eEnemy, bool bNavalOp, int iMaxDistance) { //check if we're at the target CvPlot *pTargetPlot = GetGoalPlot(); CvPlot *pCenterOfMass = GetCenterOfMass(NO_DOMAIN); if(pCenterOfMass && pTargetPlot && plotDistance(*pCenterOfMass,*pTargetPlot) <= iMaxDistance) return pTargetPlot; //check early termination if we ran into the enemy if(GetArmyAIState() == ARMYAISTATE_MOVING_TO_DESTINATION) { CvPlot* pEnemyPlot = DetectNearbyEnemy(eEnemy, bNavalOp); if(pEnemyPlot != NULL) { CvCity* pCity = pEnemyPlot->getWorkingCity(); if(pCity != NULL) { if (bNavalOp && pCity->isCoastal() && pCity->waterArea()==pTargetPlot->area()) pEnemyPlot = pCity->plot(); if (!bNavalOp && pCity->area()==pTargetPlot->area()) pEnemyPlot = pCity->plot(); if (pEnemyPlot!=GetGoalPlot()) { if(GC.getLogging() && GC.getAILogging()) { CvString strMsg; strMsg.Format("Switching target from %d,%d to closest city at %d,%d", GetGoalX(), GetGoalY(), pEnemyPlot->getX(), pEnemyPlot->getY() ); GET_PLAYER(m_eOwner).getAIOperation(m_iOperationID)->LogOperationSpecialMessage(strMsg); } } return pEnemyPlot; } } } return NULL; }