Hooks
static bool BeforeCvCity_GetBuyablePlotList(CvCity* self, std::vector<int>& aiPlotList);static void AfterCvCity_GetBuyablePlotList(CvCity* self, std::vector<int>& aiPlotList);static void ReplaceCvCity_GetBuyablePlotList(void (*original)(CvCity*, std::vector<int>&), CvCity* self, std::vector<int>& aiPlotList);CivRegisterBefore<CivHooks::CvCity_GetBuyablePlotList>(host, &BeforeCvCity_GetBuyablePlotList);CivRegisterAfter<CivHooks::CvCity_GetBuyablePlotList>(host, &AfterCvCity_GetBuyablePlotList);CivRegisterReplace<CivHooks::CvCity_GetBuyablePlotList>(host, &ReplaceCvCity_GetBuyablePlotList);
Code
12088void CvCity::GetBuyablePlotList(std::vector<int>& aiPlotList)12089{12090 VALIDATE_OBJECT12091 aiPlotList.resize(20, -1);12092 int iResultListIndex = 0;1209312094 int iLowestCost = INT_MAX;12095 CvPlot* pLoopPlot = NULL;12096 CvPlot* pThisPlot = plot();12097 const int iMaxRange = /*5*/ GC.getMAXIMUM_ACQUIRE_PLOT_DISTANCE();12098 CvMap& thisMap = GC.getMap();12099 TeamTypes thisTeam = getTeam();1210012101 int iPLOT_INFLUENCE_DISTANCE_MULTIPLIER = /*100*/ GC.getPLOT_INFLUENCE_DISTANCE_MULTIPLIER();12102 int iPLOT_INFLUENCE_RING_COST = /*100*/ GC.getPLOT_INFLUENCE_RING_COST();12103 int iPLOT_INFLUENCE_WATER_COST = /* 25*/ GC.getPLOT_INFLUENCE_WATER_COST();12104 int iPLOT_INFLUENCE_IMPROVEMENT_COST = /* -5*/ GC.getPLOT_INFLUENCE_IMPROVEMENT_COST();12105 int iPLOT_INFLUENCE_ROUTE_COST = /*0*/ GC.getPLOT_INFLUENCE_ROUTE_COST();12106 int iPLOT_INFLUENCE_RESOURCE_COST = /*-105*/ GC.getPLOT_INFLUENCE_RESOURCE_COST();12107 int iPLOT_INFLUENCE_NW_COST = /*-105*/ GC.getPLOT_INFLUENCE_NW_COST();12108 int iPLOT_INFLUENCE_YIELD_POINT_COST = /*-1*/ GC.getPLOT_INFLUENCE_YIELD_POINT_COST();1210912110 int iPLOT_INFLUENCE_NO_ADJACENT_OWNED_COST = /*1000*/ GC.getPLOT_INFLUENCE_NO_ADJACENT_OWNED_COST();1211112112 int iYieldLoop;1211312114 int iDirectionLoop;12115 bool bFoundAdjacentOwnedByCity;1211612117 int iDX, iDY;1211812119 ImprovementTypes eBarbCamptype = (ImprovementTypes)GC.getBARBARIAN_CAMP_IMPROVEMENT();1212012121 for (iDX = -iMaxRange; iDX <= iMaxRange; iDX++)12122 {12123 for (iDY = -iMaxRange; iDY <= iMaxRange; iDY++)12124 {12125 pLoopPlot = plotXYWithRangeCheck(getX(), getY(), iDX, iDY, iMaxRange);12126 if (pLoopPlot != NULL)12127 {12128 if (pLoopPlot->getOwner() != NO_PLAYER)12129 {12130 continue;12131 }1213212133#if defined(MOD_EVENTS_CITY_BORDERS)12134 // This can be used to implement a 12-mile limit12135 if (MOD_EVENTS_CITY_BORDERS) {12136 if (GAMEEVENTINVOKE_TESTALL(GAMEEVENT_CityCanAcquirePlot, getOwner(), GetID(), pLoopPlot->getX(), pLoopPlot->getY()) == GAMEEVENTRETURN_FALSE) {12137 continue;12138 }12139 } else {12140#endif 12141 ICvEngineScriptSystem1* pkScriptSystem = gDLL->GetScriptSystem();12142 if (pkScriptSystem) 12143 {12144 CvLuaArgsHandle args;12145 args->Push(getOwner());12146 args->Push(GetID());12147 args->Push(pLoopPlot->getX());12148 args->Push(pLoopPlot->getY());1214912150 bool bResult = false;12151 if (LuaSupport::CallTestAll(pkScriptSystem, "CityCanAcquirePlot", args.get(), bResult))12152 {12153 if (bResult == false) {12154 continue;12155 }12156 }12157 }12158#if defined(MOD_EVENTS_CITY_BORDERS)12159 }12160#endif 1216112162 // we can use the faster, but slightly inaccurate pathfinder here - after all we are using a rand in the equation12163 int iInfluenceCost = thisMap.calculateInfluenceDistance(pThisPlot, pLoopPlot, iMaxRange, false) * iPLOT_INFLUENCE_DISTANCE_MULTIPLIER;1216412165 if (iInfluenceCost > 0)12166 {12167 // Modifications for tie-breakers in a ring1216812169 // Resource Plots claimed first12170 ResourceTypes eResource = pLoopPlot->getResourceType(thisTeam);12171 if (eResource != NO_RESOURCE)12172 {12173 iInfluenceCost += iPLOT_INFLUENCE_RESOURCE_COST;12174 bool bBonusResource = GC.getResourceInfo(eResource)->getResourceUsage() == RESOURCEUSAGE_BONUS;12175 if (bBonusResource)12176 {12177#if defined(MOD_GLOBAL_CITY_WORKING)12178 if (plotDistance(pLoopPlot->getX(),pLoopPlot->getY(),getX(),getY()) > getWorkPlotDistance())12179#else 12180 if (plotDistance(pLoopPlot->getX(),pLoopPlot->getY(),getX(),getY()) > NUM_CITY_RINGS)12181#endif12182 {12183 // undo the bonus - we can't work this tile from this city12184 iInfluenceCost -= iPLOT_INFLUENCE_RESOURCE_COST;12185 }12186 else12187 {12188 // very slightly decrease value of bonus resources12189 ++iInfluenceCost;12190 }12191 }12192 }12193 else 12194 {1219512196 // Water Plots claimed later12197 if (pLoopPlot->isWater())12198 {12199 iInfluenceCost += iPLOT_INFLUENCE_WATER_COST;12200 }1220112202 // if we can't work this tile in this city make it much less likely to be picked12203#if defined(MOD_GLOBAL_CITY_WORKING)12204 if (plotDistance(pLoopPlot->getX(),pLoopPlot->getY(),getX(),getY()) > getWorkPlotDistance())12205#else 12206 if (plotDistance(pLoopPlot->getX(),pLoopPlot->getY(),getX(),getY()) > NUM_CITY_RINGS)12207#endif12208 {12209 iInfluenceCost += iPLOT_INFLUENCE_RING_COST;12210 }1221112212 }1221312214 // improved tiles get a slight priority (unless they are barbarian camps!)12215 ImprovementTypes thisImprovement = pLoopPlot->getImprovementType();12216 if (thisImprovement != NO_IMPROVEMENT)12217 {12218 if (thisImprovement == eBarbCamptype)12219 {12220 iInfluenceCost += iPLOT_INFLUENCE_RING_COST;12221 }12222 else12223 {12224 iInfluenceCost += iPLOT_INFLUENCE_IMPROVEMENT_COST;12225 }12226 }1222712228 // roaded tiles get a priority - [not any more: weight above is 0 by default]12229 if (pLoopPlot->getRouteType() != NO_ROUTE)12230 {12231 iInfluenceCost += iPLOT_INFLUENCE_ROUTE_COST;12232 }1223312234 // while we're at it grab Natural Wonders quickly also12235 if (pLoopPlot->IsNaturalWonder())12236 {12237 iInfluenceCost += iPLOT_INFLUENCE_NW_COST;12238 }1223912240 // More Yield == more desirable12241 for (iYieldLoop = 0; iYieldLoop < NUM_YIELD_TYPES; iYieldLoop++)12242 {12243 iInfluenceCost += (iPLOT_INFLUENCE_YIELD_POINT_COST * pLoopPlot->getYield((YieldTypes) iYieldLoop));12244 }1224512246 // all other things being equal move towards unclaimed resources12247 bool bUnownedNaturalWonderAdjacentCount = false;12248 for (int iI = 0; iI < NUM_DIRECTION_TYPES; ++iI)12249 {12250 CvPlot* pAdjacentPlot = plotDirection(pLoopPlot->getX(), pLoopPlot->getY(), ((DirectionTypes)iI));1225112252 if (pAdjacentPlot != NULL)12253 {12254 if (pAdjacentPlot->getOwner() == NO_PLAYER)12255 {12256 int iPlotDistance = plotDistance(getX(), getY(), pAdjacentPlot->getX(), pAdjacentPlot->getY());12257 ResourceTypes eAdjacentResource = pAdjacentPlot->getResourceType(thisTeam);12258 if (eAdjacentResource != NO_RESOURCE)12259 {12260 // if we are close enough to work, or this is not a bonus resource12261#if defined(MOD_GLOBAL_CITY_WORKING)12262 if (iPlotDistance <= getWorkPlotDistance() || GC.getResourceInfo(eAdjacentResource)->getResourceUsage() != RESOURCEUSAGE_BONUS)12263#else 12264 if (iPlotDistance <= NUM_CITY_RINGS || GC.getResourceInfo(eAdjacentResource)->getResourceUsage() != RESOURCEUSAGE_BONUS)12265#endif12266 {12267 --iInfluenceCost;12268 }12269 }12270 if (pAdjacentPlot->IsNaturalWonder())12271 {12272#if defined(MOD_GLOBAL_CITY_WORKING)12273 if (iPlotDistance <= getWorkPlotDistance()) // grab for this city12274#else 12275 if (iPlotDistance <= NUM_CITY_RINGS) // grab for this city12276#endif12277 {12278 bUnownedNaturalWonderAdjacentCount = true;12279 }12280 --iInfluenceCost; // but we will slightly grow towards it for style in any case12281 }12282 }12283 }12284 }1228512286 // move towards unclaimed NW12287 iInfluenceCost += bUnownedNaturalWonderAdjacentCount ? -1 : 0;1228812289 // Plots not adjacent to another Plot acquired by this City are pretty much impossible to get12290 bFoundAdjacentOwnedByCity = false;12291 for (iDirectionLoop = 0; iDirectionLoop < NUM_DIRECTION_TYPES; iDirectionLoop++)12292 {12293 CvPlot* pAdjacentPlot = plotDirection(pLoopPlot->getX(), pLoopPlot->getY(), (DirectionTypes) iDirectionLoop);1229412295 if (pAdjacentPlot != NULL)12296 {12297 // Have to check plot ownership first because the City IDs match between different players!!!12298 if (pAdjacentPlot->getOwner() == getOwner() && pAdjacentPlot->GetCityPurchaseID() == GetID())12299 {12300 bFoundAdjacentOwnedByCity = true;12301 break;12302 }12303 }12304 }12305 if (!bFoundAdjacentOwnedByCity)12306 {12307 iInfluenceCost += iPLOT_INFLUENCE_NO_ADJACENT_OWNED_COST;12308 }1230912310#if defined(MOD_UI_CITY_EXPANSION)12311 // Group very similiar "cost" tiles - ie 683 and 684 cost tiles will appear to be the same value12312 int iDivisor = /*5*/ GC.getPLOT_INFLUENCE_COST_VISIBLE_DIVISOR();12313 iInfluenceCost /= iDivisor;12314 iInfluenceCost *= iDivisor;12315#endif1231612317 // Are we cheap enough to get picked next?12318 if (iInfluenceCost < iLowestCost)12319 {12320 // clear reset list12321 for(uint ui = 0; ui < aiPlotList.size(); ui++)12322 {12323 aiPlotList[ui] = -1;12324 }12325 iResultListIndex = 0;12326 iLowestCost = iInfluenceCost;12327 // this will "fall through" to the next conditional12328 }1232912330 if (iInfluenceCost == iLowestCost)12331 {12332 aiPlotList[iResultListIndex] = pLoopPlot->GetPlotIndex();12333 iResultListIndex++;12334 }12335 }12336 }12337 }12338 }1233912340}