Hooks
static bool BeforeCvBuilderTaskingAI_ConnectCitiesToCapital(CvBuilderTaskingAI* self, CvCity* pPlayerCapital, CvCity* pTargetCity, RouteTypes eRoute);static void AfterCvBuilderTaskingAI_ConnectCitiesToCapital(CvBuilderTaskingAI* self, CvCity* pPlayerCapital, CvCity* pTargetCity, RouteTypes eRoute);static void ReplaceCvBuilderTaskingAI_ConnectCitiesToCapital(void (*original)(CvBuilderTaskingAI*, CvCity*, CvCity*, RouteTypes), CvBuilderTaskingAI* self, CvCity* pPlayerCapital, CvCity* pTargetCity, RouteTypes eRoute);CivRegisterBefore<CivHooks::CvBuilderTaskingAI_ConnectCitiesToCapital>(host, &BeforeCvBuilderTaskingAI_ConnectCitiesToCapital);CivRegisterAfter<CivHooks::CvBuilderTaskingAI_ConnectCitiesToCapital>(host, &AfterCvBuilderTaskingAI_ConnectCitiesToCapital);CivRegisterReplace<CivHooks::CvBuilderTaskingAI_ConnectCitiesToCapital>(host, &ReplaceCvBuilderTaskingAI_ConnectCitiesToCapital);
Code
278void CvBuilderTaskingAI::ConnectCitiesToCapital(CvCity* pPlayerCapital, CvCity* pTargetCity, RouteTypes eRoute)279{280 bool bMajorMinorConnection = false;281 if(pTargetCity->getOwner() != pPlayerCapital->getOwner())282 {283 bMajorMinorConnection = true;284 }285286 bool bIndustrialRoute = false;287 if(GC.getGame().GetIndustrialRoute() == eRoute)288 {289 bIndustrialRoute = true;290 }291292 // if we already have a connection, bail out293 if(bIndustrialRoute && pTargetCity->IsIndustrialRouteToCapital())294 {295 return;296 }297 else if(m_pPlayer->IsCapitalConnectedToCity(pTargetCity, eRoute))298 {299 return;300 }301302 int iGoldForRoute = 0;303 if(!bMajorMinorConnection)304 {305 iGoldForRoute = m_pPlayer->GetTreasury()->GetCityConnectionRouteGoldTimes100(pTargetCity) / 100;306 }307308 CvRouteInfo* pRouteInfo = GC.getRouteInfo(eRoute);309 if(!pRouteInfo)310 {311 return;312 }313 int iMaintenancePerTile = pRouteInfo->GetGoldMaintenance();314 if(iMaintenancePerTile < 0) // div by zero check315 {316 return;317 }318319 // build a path between the two cities320 int iPathfinderFlags = m_pPlayer->GetID();321 int iRouteValue = eRoute + 1;322 // assuming that there are fewer than 256 players323 iPathfinderFlags |= (iRouteValue << 8);324 bool bFoundPath = GC.GetBuildRouteFinder().GeneratePath(pPlayerCapital->plot()->getX(), pPlayerCapital->plot()->getY(), pTargetCity->plot()->getX(), pTargetCity->plot()->getY(), iPathfinderFlags);325326 // if no path, then bail!327 if(!bFoundPath)328 {329 return;330 }331332 // walk the path333 CvPlot* pPlot = NULL;334335 // go through the route to see how long it is and how many plots already have roads336 int iRoadLength = 0;337 int iPlotsNeeded = 0;338 CvAStarNode* pNode = GC.GetBuildRouteFinder().GetLastNode();339 while(pNode)340 {341 pPlot = GC.getMap().plotCheckInvalid(pNode->m_iX, pNode->m_iY);342 pNode = pNode->m_pParent;343 if(!pPlot)344 {345 break;346 }347348 CvCity* pCity = pPlot->getPlotCity();349 if(NULL != pCity && pCity->getTeam() == m_pPlayer->getTeam())350 {351 continue;352 }353354 if(pPlot->getRouteType() == eRoute && !pPlot->IsRoutePillaged())355 {356 // if this is already a trade route or someone else built it, we can count is as free357 if(pPlot->IsTradeRoute(m_pPlayer->GetID()) || pPlot->GetPlayerResponsibleForRoute() != m_pPlayer->GetID())358 {359 continue;360 }361 iRoadLength++;362 }363 else364 {365 iRoadLength++;366 iPlotsNeeded++;367 }368 }369370 // This is very odd371 if(iRoadLength <= 0 || iPlotsNeeded <= 0)372 {373 return;374 }375376377 short sValue = -1;378 int iProfit = iGoldForRoute - (iRoadLength * iMaintenancePerTile);379 if(bIndustrialRoute)380 {381 if(iProfit >= 0)382 {383 sValue = MAX_SHORT;384 }385 else if(m_pPlayer->calculateGoldRate() + iProfit >= 0)386 {387 sValue = pTargetCity->getYieldRate(YIELD_PRODUCTION, false) * GC.getINDUSTRIAL_ROUTE_PRODUCTION_MOD();388 }389 else390 {391 return;392 }393 }394 else if(bMajorMinorConnection)395 {396 sValue = min(GC.getMINOR_CIV_ROUTE_QUEST_WEIGHT() / iPlotsNeeded, MAX_SHORT);397 }398 else // normal route399 {400 // is this route worth building?401 if(iProfit < 0)402 {403 return;404 }405406 int iValue = (iGoldForRoute * 100) / (iRoadLength * (iMaintenancePerTile + 1));407 iValue = (iValue * iRoadLength) / iPlotsNeeded;408 sValue = min(iValue, MAX_SHORT);409 }410411 pPlot = NULL;412 pNode = GC.GetBuildRouteFinder().GetLastNode();413414 int iGameTurn = GC.getGame().getGameTurn();415416 while(pNode)417 {418 pPlot = GC.getMap().plotCheckInvalid(pNode->m_iX, pNode->m_iY);419 pNode = pNode->m_pParent;420421 if(!pPlot)422 {423 break;424 }425426 if(pPlot->getRouteType() == eRoute && !pPlot->IsRoutePillaged())427 {428 continue;429 }430431 // if we already know about this plot, continue on432 if(pPlot->GetBuilderAIScratchPadTurn() == iGameTurn && pPlot->GetBuilderAIScratchPadPlayer() == m_pPlayer->GetID())433 {434 if(sValue > pPlot->GetBuilderAIScratchPadValue())435 {436 pPlot->SetBuilderAIScratchPadValue(sValue);437 pPlot->SetBuilderAIScratchPadRoute(eRoute);438 }439 continue;440 }441442 // mark nodes and reset values443 pPlot->SetBuilderAIScratchPadTurn(iGameTurn);444 pPlot->SetBuilderAIScratchPadPlayer(m_pPlayer->GetID());445 pPlot->SetBuilderAIScratchPadValue(sValue);446 pPlot->SetBuilderAIScratchPadRoute(eRoute);447448 // add nodes that are not in territory to extra list449 // minors should not build out of their borders when they are doing a major/minor connection, only when connecting their two cities450 if(!(m_pPlayer->isMinorCiv() && bMajorMinorConnection))451 {452 if(pPlot->getOwner() != m_pPlayer->GetID())453 {454 m_aiNonTerritoryPlots.push_back(GC.getMap().plotNum(pPlot->getX(), pPlot->getY()));455 }456 }457 }458}