diff --git a/(1) Community Patch/Core Files/CoreLua/InGame.lua b/(1) Community Patch/Core Files/CoreLua/InGame.lua index 6a8572081f..c0aad8b2de 100644 --- a/(1) Community Patch/Core Files/CoreLua/InGame.lua +++ b/(1) Community Patch/Core Files/CoreLua/InGame.lua @@ -954,7 +954,7 @@ function OnUpdateSelection( isSelected ) aWorkerSuggestHighlightPlots = player:GetRecommendedWorkerPlots(); -- Player can disable tile recommendations - if (aFounderSuggestHighlightPlots ~= nil and not OptionsManager.IsNoTileRecommendations()) then + if (aWorkerSuggestHighlightPlots ~= nil and not OptionsManager.IsNoTileRecommendations()) then for i, v in ipairs(aWorkerSuggestHighlightPlots) do if (v.plot ~= nil) then local hexID = ToHexFromGrid( Vector2( v.plot:GetX(), v.plot:GetY() ) ); diff --git a/CvGameCoreDLL_Expansion2/CvAIOperation.cpp b/CvGameCoreDLL_Expansion2/CvAIOperation.cpp index 0e335ec62c..2213585611 100644 --- a/CvGameCoreDLL_Expansion2/CvAIOperation.cpp +++ b/CvGameCoreDLL_Expansion2/CvAIOperation.cpp @@ -1615,7 +1615,7 @@ bool CvAIOperationMilitary::CheckTransitionToNextStage() int nVisible = 0; for (CvUnit* pUnit = pThisArmy->GetFirstUnit(); pUnit; pUnit = pThisArmy->GetNextUnit(pUnit)) { - if (GET_PLAYER(pUnit->getOwner()).GetTacticalAI()->IsVisibleToPlayer(pUnit->plot(), GET_PLAYER(m_eEnemy).getTeam())) + if (GET_PLAYER(m_eOwner).GetTacticalAI()->IsVisibleToPlayer(pUnit->plot(), GET_PLAYER(m_eEnemy).getTeam())) nVisible++; } diff --git a/CvGameCoreDLL_Expansion2/CvAStar.cpp b/CvGameCoreDLL_Expansion2/CvAStar.cpp index cea8d26a04..690d295ed2 100644 --- a/CvGameCoreDLL_Expansion2/CvAStar.cpp +++ b/CvGameCoreDLL_Expansion2/CvAStar.cpp @@ -2298,12 +2298,16 @@ int BuildRouteCost(const CvAStarNode* /*parent*/, const CvAStarNode* node, const return iCost; } -static bool IsSafeForRoute(CvPlot* pPlot, CvPlayer* pPlayer) +static bool IsSafeForRoute(CvPlot* pPlot, CvPlayer* pPlayer, RouteTypes eRoute) { TeamTypes ePlotTeam = pPlot->getTeam(); TeamTypes ePlayerTeam = pPlayer->getTeam(); PlayerTypes ePlotOwner = pPlot->getOwner(); + //Free routes from traits are always safe + if (pPlayer->GetBuilderTaskingAI()->GetSameRouteBenefitFromTrait(pPlot, eRoute)) + return TRUE; + // Our plots and surrounding plots are safe if (ePlotTeam == ePlayerTeam || pPlot->isAdjacentTeam(pPlayer->getTeam(), false)) { @@ -2387,15 +2391,11 @@ int BuildRouteValid(const CvAStarNode* parent, const CvAStarNode* node, const SP } } - //Free routes from traits are always safe - if (thisPlayer.GetBuilderTaskingAI()->GetSameRouteBenefitFromTrait(pNewPlot, eRoute)) - return TRUE; - //if the plot and its parent are both too far from our borders, don't build here - if (!IsSafeForRoute(pNewPlot, &thisPlayer)) + if (!IsSafeForRoute(pNewPlot, &thisPlayer, eRoute)) { CvPlot* pFromPlot = GC.getMap().plotUnchecked(parent->m_iX, parent->m_iY); - if (!IsSafeForRoute(pFromPlot, &thisPlayer)) + if (!IsSafeForRoute(pFromPlot, &thisPlayer, eRoute)) return FALSE; } diff --git a/CvGameCoreDLL_Expansion2/CvBuilderTaskingAI.cpp b/CvGameCoreDLL_Expansion2/CvBuilderTaskingAI.cpp index 681b3129f1..2606518607 100644 --- a/CvGameCoreDLL_Expansion2/CvBuilderTaskingAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvBuilderTaskingAI.cpp @@ -323,48 +323,52 @@ void CvBuilderTaskingAI::ConnectCitiesToCapital(CvCity* pPlayerCapital, CvCity* else { int iMaintenancePerTile = pRouteInfo->GetGoldMaintenance()*(100+m_pPlayer->GetImprovementGoldMaintenanceMod()); - int iGoldForRoute = m_pPlayer->GetTreasury()->GetCityConnectionRouteGoldTimes100(pTargetCity); + bool bHasCityConnection = m_pPlayer->IsCityConnectedToCity(pPlayerCapital, pTargetCity, eRoute); + int iGoldForRoute = !bHasCityConnection ? m_pPlayer->GetTreasury()->GetCityConnectionRouteGoldTimes100(pTargetCity) : 0; //route has side benefits also (movement, village gold, trade route range, religion spread) int iSideBenefits = 500 + iRoadLength * 100; //assume one unhappiness is worth gold per turn per city - iSideBenefits += pTargetCity->GetUnhappinessFromIsolation() * (m_pPlayer->IsEmpireUnhappy() ? 200 : 100); + iSideBenefits += bHasCityConnection ? pTargetCity->GetUnhappinessFromIsolation() * (m_pPlayer->IsEmpireUnhappy() ? 200 : 100) : 0; if(GC.getGame().GetIndustrialRoute() == eRoute) { - iSideBenefits += pTargetCity->getYieldRate(YIELD_PRODUCTION, false) * /*25 in CP, 0 in VP*/ GD_INT_GET(INDUSTRIAL_ROUTE_PRODUCTION_MOD); + if (!bHasCityConnection) + { + iSideBenefits += pTargetCity->getYieldRate(YIELD_PRODUCTION, false) * /*25 in CP, 0 in VP*/ GD_INT_GET(INDUSTRIAL_ROUTE_PRODUCTION_MOD); #if defined(MOD_BALANCE_CORE) - // Target city would get a production and gold boost from a train station. - for (int iBuildingIndex = 0; iBuildingIndex < GC.getNumBuildingInfos(); iBuildingIndex++) - { - BuildingTypes eBuilding = (BuildingTypes)iBuildingIndex; - CvBuildingEntry* pkBuilding = GC.getBuildingInfo(eBuilding); - if (pkBuilding == NULL) - continue; + // Target city would get a production and gold boost from a train station. + for (int iBuildingIndex = 0; iBuildingIndex < GC.getNumBuildingInfos(); iBuildingIndex++) + { + BuildingTypes eBuilding = (BuildingTypes)iBuildingIndex; + CvBuildingEntry* pkBuilding = GC.getBuildingInfo(eBuilding); + if (pkBuilding == NULL) + continue; - bool bRequiresRail = pkBuilding->IsRequiresRail(); - if (!bRequiresRail) - continue; + bool bRequiresRail = pkBuilding->IsRequiresRail(); + if (!bRequiresRail) + continue; - int iProductionYield = pTargetCity->getYieldRate(YIELD_PRODUCTION, false); - int iGoldYield = pTargetCity->getYieldRate(YIELD_GOLD, false); - int iProductionYieldRateModifier = pkBuilding->GetYieldModifier(YIELD_PRODUCTION); - int iGoldYieldRateModifier = pkBuilding->GetYieldModifier(YIELD_GOLD); + int iProductionYield = pTargetCity->getYieldRate(YIELD_PRODUCTION, false); + int iGoldYield = pTargetCity->getYieldRate(YIELD_GOLD, false); + int iProductionYieldRateModifier = pkBuilding->GetYieldModifier(YIELD_PRODUCTION); + int iGoldYieldRateModifier = pkBuilding->GetYieldModifier(YIELD_GOLD); - if (pTargetCity->HasBuilding(eBuilding)) - { - iSideBenefits += 100 * iProductionYield * iProductionYieldRateModifier / (100 + iProductionYieldRateModifier); - iSideBenefits += 100 * iGoldYield * iGoldYieldRateModifier / (100 + iGoldYieldRateModifier); - } - else if (m_pPlayer->canConstruct(eBuilding) || eBuilding == pTargetCity->getProductionBuilding()) - { - iSideBenefits += iProductionYield * iProductionYieldRateModifier; - iSideBenefits += iGoldYield * iGoldYieldRateModifier; + if (pTargetCity->HasBuilding(eBuilding)) + { + iSideBenefits += 100 * iProductionYield * iProductionYieldRateModifier / (100 + iProductionYieldRateModifier); + iSideBenefits += 100 * iGoldYield * iGoldYieldRateModifier / (100 + iGoldYieldRateModifier); + } + else if (m_pPlayer->canConstruct(eBuilding) || eBuilding == pTargetCity->getProductionBuilding()) + { + iSideBenefits += iProductionYield * iProductionYieldRateModifier; + iSideBenefits += iGoldYield * iGoldYieldRateModifier; + } } - } #endif + } // railroads have extra benefits over normal roads iSideBenefits += iRoadLength * 150; @@ -2739,21 +2743,33 @@ int CvBuilderTaskingAI::ScorePlotBuild(CvUnit* pUnit, CvPlot* pPlot, Improvement } //Let's get route things on routes, and not elsewhere. - int iRouteScore = 0; + int iRailroadScore = 0; + int iRoadScore = 0; for(int iI = 0; iI < NUM_YIELD_TYPES; iI++) { YieldTypes eYield = (YieldTypes) iI; - iRouteScore += pImprovement->GetRouteYieldChanges(ROUTE_RAILROAD, eYield) * 100; - iRouteScore += pImprovement->GetRouteYieldChanges(ROUTE_ROAD, eYield) * 100; + iRailroadScore += pImprovement->GetRouteYieldChanges(ROUTE_RAILROAD, eYield) * 100; + iRoadScore += pImprovement->GetRouteYieldChanges(ROUTE_ROAD, eYield) * 100; } - if (iRouteScore > 0) + if (iRailroadScore > 0 || iRoadScore > 0) { - // If we don't need a route at this plot, it is about to be removed - if (pPlot->IsCityConnection(m_pPlayer->GetID()) && (pPlot->IsRouteRailroad() || pPlot->IsRouteRoad()) && NeedRouteAtPlot(pPlot)) - iSecondaryScore += iRouteScore; + if (pPlot->IsCityConnection(m_pPlayer->GetID())) + { + bool bHaveAndNeedRailroad = pPlot->IsRouteRailroad() && GetRouteTypeNeededAtPlot(pPlot) == ROUTE_RAILROAD; + bool bHaveAndNeedRoad = pPlot->IsRouteRoad() && GetRouteTypeNeededAtPlot(pPlot) == ROUTE_ROAD && !GetSameRouteBenefitFromTrait(pPlot, ROUTE_ROAD) == ROUTE_ROAD; + + if (bHaveAndNeedRailroad) + iSecondaryScore += iRailroadScore; + else if (bHaveAndNeedRoad) + iSecondaryScore += iRoadScore; + else + iSecondaryScore -= max(iRailroadScore, iRoadScore); + } else - iSecondaryScore -= iRouteScore; + { + iSecondaryScore -= max(iRailroadScore, iRoadScore); + } } //City adjacenct improvement? Ramp it up - other stuff can move somewhere else diff --git a/CvGameCoreDLL_Expansion2/CvTacticalAI.cpp b/CvGameCoreDLL_Expansion2/CvTacticalAI.cpp index edc5cee971..abcb612b01 100644 --- a/CvGameCoreDLL_Expansion2/CvTacticalAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvTacticalAI.cpp @@ -423,13 +423,20 @@ void CvTacticalAI::NewVisiblePlot(CvPlot* pPlot, bool bRevealed=false) { TeamTypes eOtherTeam; CvUnit* pLoopUnit; + PlayerTypes eOtherPlayer; + PlayerTypes eMinorCivAlly = NO_PLAYER; for (int iI = 0; iI < pPlot->getNumUnits(); iI++) { pLoopUnit = pPlot->getUnitByIndex(iI); eOtherTeam = pLoopUnit->getTeam(); + eOtherPlayer = pLoopUnit->getOwner(); if (eOtherTeam != eTeam && !pLoopUnit->isInvisible(eTeam, false)) { + if (GET_TEAM(eOtherTeam).isMinorCiv()) + { + eMinorCivAlly = GET_PLAYER(eOtherPlayer).GetMinorCivAI()->GetAlly(); + } for (int iRange = 2; iRange <= pLoopUnit->visibilityRange(); iRange++) { const vector& vPlots = GC.getMap().GetPlotsAtRangeX(pPlot, iRange, true, true); @@ -440,6 +447,8 @@ void CvTacticalAI::NewVisiblePlot(CvPlot* pPlot, bool bRevealed=false) continue; m_plotsVisibleToOtherPlayer[eOtherTeam].insert(vPlots[iJ]->GetPlotIndex()); + if (eMinorCivAlly != NO_PLAYER) + m_plotsVisibleToOtherPlayer[GET_PLAYER(eMinorCivAlly).getTeam()].insert(vPlots[iJ]->GetPlotIndex()); } } } @@ -479,6 +488,8 @@ void CvTacticalAI::UpdateVisibilityFromBorders(CvPlot* pPlot, bool bRevealed) { TeamTypes eTeam = m_pPlayer->getTeam(); TeamTypes eOtherTeam = pPlot->getTeam(); + PlayerTypes eOtherPlayer = pPlot->getOwner(); + PlayerTypes eMinorCivAlly = NO_PLAYER; CvPlot** aPlotsToCheck = GC.getMap().getNeighborsUnchecked(pPlot); CvPlot* pAdjacentPlot; @@ -486,6 +497,12 @@ void CvTacticalAI::UpdateVisibilityFromBorders(CvPlot* pPlot, bool bRevealed) { // Plot is owned by another player m_plotsVisibleToOtherPlayer[eOtherTeam].insert(pPlot->GetPlotIndex()); + if (GET_TEAM(eOtherTeam).isMinorCiv()) + { + eMinorCivAlly = GET_PLAYER(eOtherPlayer).GetMinorCivAI()->GetAlly(); + if (eMinorCivAlly != NO_PLAYER) + m_plotsVisibleToOtherPlayer[GET_PLAYER(eMinorCivAlly).getTeam()].insert(pPlot->GetPlotIndex()); + } if (bRevealed) { @@ -494,8 +511,12 @@ void CvTacticalAI::UpdateVisibilityFromBorders(CvPlot* pPlot, bool bRevealed) pAdjacentPlot = aPlotsToCheck[iI]; if (pAdjacentPlot != NULL && pAdjacentPlot->isVisible(eTeam)) + { // We knew about this plot before but we may not previously have known that this player was neighboring it m_plotsVisibleToOtherPlayer[eOtherTeam].insert(pAdjacentPlot->GetPlotIndex()); + if (eMinorCivAlly != NO_PLAYER) + m_plotsVisibleToOtherPlayer[GET_PLAYER(eMinorCivAlly).getTeam()].insert(pAdjacentPlot->GetPlotIndex()); + } } } }