Hooks
static bool BeforeCvMinorCivAI_CalculateBullyMetric(CvMinorCivAI* self, PlayerTypes eBullyPlayer, bool bForUnit, CvString* sTooltipSink, int& result);static void AfterCvMinorCivAI_CalculateBullyMetric(CvMinorCivAI* self, PlayerTypes eBullyPlayer, bool bForUnit, CvString* sTooltipSink, int& result);static int ReplaceCvMinorCivAI_CalculateBullyMetric(int (*original)(CvMinorCivAI*, PlayerTypes, bool, CvString*), CvMinorCivAI* self, PlayerTypes eBullyPlayer, bool bForUnit, CvString* sTooltipSink);CivRegisterBefore<CivHooks::CvMinorCivAI_CalculateBullyMetric>(host, &BeforeCvMinorCivAI_CalculateBullyMetric);CivRegisterAfter<CivHooks::CvMinorCivAI_CalculateBullyMetric>(host, &AfterCvMinorCivAI_CalculateBullyMetric);CivRegisterReplace<CivHooks::CvMinorCivAI_CalculateBullyMetric>(host, &ReplaceCvMinorCivAI_CalculateBullyMetric);
Code
8978// Calculates a basic score for whether the major can bully this minor based on many factors.8979// Negative score if bully attempt is a failure, zero or positive if success.8980// May be modified after return, if the task is easier or harder (ex. bully a worker vs. bully gold)8981int CvMinorCivAI::CalculateBullyMetric(PlayerTypes eBullyPlayer, bool bForUnit, CvString* sTooltipSink)8982{8983 CvString sFactors = "";89848985 int iScore = 0;8986 const int iFailScore = -300;89878988 CvAssertMsg(GetPlayer()->GetID() != eBullyPlayer, "Minor civ and bully civ not expected to have the same ID!");8989 if(GetPlayer()->GetID() == eBullyPlayer)8990 return iFailScore;89918992 CvAssertMsg(eBullyPlayer >= 0, "eBullyPlayer is expected to be non-negative (invalid Index)");8993 CvAssertMsg(eBullyPlayer < MAX_MAJOR_CIVS, "eBullyPlayer is expected to be within maximum bounds (invalid Index)");8994 if(eBullyPlayer < 0 || eBullyPlayer >= MAX_MAJOR_CIVS)8995 return iFailScore;89968997 // Can't bully the dead8998 if(!GetPlayer()->isAlive())8999 return iFailScore;90009001 // **************************9002 // Global military power ranking of major9003 //9004 // +0 ~ +759005 // **************************9006 CvWeightedVector<PlayerTypes, MAX_MAJOR_CIVS, true> veMilitaryRankings;9007 PlayerTypes eMajorLoop;9008 int iGlobalMilitaryScore = 0;9009 for(int iMajorLoop = 0; iMajorLoop < MAX_MAJOR_CIVS; iMajorLoop++)9010 {9011 eMajorLoop = (PlayerTypes) iMajorLoop;9012 if(GET_PLAYER(eMajorLoop).isAlive() && !GET_PLAYER(eMajorLoop).isMinorCiv())9013 {9014 veMilitaryRankings.push_back(eMajorLoop, GET_PLAYER(eMajorLoop).GetMilitaryMight()); // Don't recalculate within a turn, can cause inconsistency9015 }9016 }9017 CvAssertMsg(veMilitaryRankings.size() > 0, "WeightedVector of military might rankings not expected to be size 0");9018 veMilitaryRankings.SortItems();9019 for(int iRanking = 0; iRanking < veMilitaryRankings.size(); iRanking++)9020 {9021 if(veMilitaryRankings.GetElement(iRanking) == eBullyPlayer)9022 {9023 float fRankRatio = (float)(veMilitaryRankings.size() - iRanking) / (float)(veMilitaryRankings.size());9024 iGlobalMilitaryScore = (int)(fRankRatio * 75); // A score between 75*(1 / num majors alive) and 75, with the highest rank major getting 759025 iScore += iGlobalMilitaryScore;9026 break;9027 }9028 }9029 9030 if (sTooltipSink)9031 {9032 Localization::String strPositiveFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_POSITIVE");9033 strPositiveFactor << iGlobalMilitaryScore;9034 strPositiveFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_GLOBAL_MILITARY";9035 sFactors += strPositiveFactor.toUTF8();9036 }90379038 // **************************9039 // Local military power comparison9040 //9041 // +0 ~ +1259042 // **************************9043 int iComparisonRadius = std::max(GC.getMap().getGridWidth() / 10, 5);9044 CvCity* pMinorCapital = GetPlayer()->getCapitalCity();9045 if(pMinorCapital == NULL)9046 return iFailScore;9047 CvPlot* pMinorCapitalPlot = pMinorCapital->plot();9048 if(pMinorCapitalPlot == NULL)9049 return iFailScore;9050 int iMinorCapitalX = pMinorCapitalPlot->getX();9051 int iMinorCapitalY = pMinorCapitalPlot->getY();9052 int iMinorLocalPower = 0;9053 int iBullyLocalPower = 0;9054 CvPlot* pLoopPlot;9055 IDInfo* pUnitNode;9056 CvUnit* pLoopUnit;90579058 // Include the minor's city power9059 iMinorLocalPower += pMinorCapital->GetPower();90609061 for(int iDX = -iComparisonRadius; iDX <= iComparisonRadius; iDX++)9062 {9063 for(int iDY = -iComparisonRadius; iDY <= iComparisonRadius; iDY++)9064 {9065 pLoopPlot = ::plotXYWithRangeCheck(iMinorCapitalX, iMinorCapitalY, iDX, iDY, iComparisonRadius);90669067 if(pLoopPlot != NULL)9068 {9069 // If there are Units here, loop through them9070 if(pLoopPlot->getNumUnits() > 0)9071 {9072 pUnitNode = pLoopPlot->headUnitNode();90739074 while(pUnitNode != NULL)9075 {9076 pLoopUnit = ::getUnit(*pUnitNode);9077 pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);90789079 // Is a combat unit9080 if(pLoopUnit && pLoopUnit->IsCombatUnit())9081 {9082 if(pLoopUnit->getOwner() == eBullyPlayer)9083 {9084 iBullyLocalPower += pLoopUnit->GetPower();9085 }9086 else if(pLoopUnit->getOwner() == GetPlayer()->GetID())9087 {9088 iMinorLocalPower += pLoopUnit->GetPower();9089 }9090 }9091 }9092 }90939094 }9095 }9096 }9097 float fLocalPowerRatio = (float)iBullyLocalPower / (float)iMinorLocalPower;9098 int iLocalPowerScore = 0;9099 if(fLocalPowerRatio >= 3.0)9100 {9101 iLocalPowerScore += 125;9102 }9103 else if(fLocalPowerRatio >= 2.0)9104 {9105 iLocalPowerScore += 100;9106 }9107 else if(fLocalPowerRatio >= 1.5)9108 {9109 iLocalPowerScore += 75;9110 }9111 else if(fLocalPowerRatio >= 1.0)9112 {9113 iLocalPowerScore += 50;9114 }9115 else if(fLocalPowerRatio >= 0.5)9116 {9117 iLocalPowerScore += 25;9118 }9119 iScore += iLocalPowerScore;9120 9121 if (sTooltipSink)9122 {9123 Localization::String strPositiveFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_POSITIVE");9124 strPositiveFactor << iLocalPowerScore;9125 strPositiveFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_MILITARY_PRESENCE";9126 sFactors += strPositiveFactor.toUTF8();9127 }91289129 // **************************9130 // Social Policies9131 //9132 // Modifier to positive scores9133 // **************************9134 int iPoliciesScore = 0;9135 int iPoliciesMod = GET_PLAYER(eBullyPlayer).GetPlayerPolicies()->GetNumericModifier(POLICYMOD_MINOR_BULLY_SCORE_MODIFIER);9136 if (iPoliciesMod != 0)9137 {9138 iPoliciesScore += iGlobalMilitaryScore;9139 iPoliciesScore += iLocalPowerScore;91409141 iPoliciesScore *= iPoliciesMod;9142 iPoliciesScore /= 100;9143 }9144 if (sTooltipSink && iPoliciesScore != 0)9145 {9146 Localization::String strPositiveFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_POSITIVE");9147 strPositiveFactor << iPoliciesScore;9148 strPositiveFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_GUNBOAT_DIPLOMACY";9149 sFactors += strPositiveFactor.toUTF8();9150 }9151 iScore += iPoliciesScore;91529153 // **************************9154 // Base Reluctance9155 //9156 // -1109157 // **************************9158 const int iBaseReluctanceScore = -110;9159 9160 if (sTooltipSink)9161 {9162 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9163 strNegativeFactor << iBaseReluctanceScore;9164 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_BASE_RELUCTANCE";9165 sFactors += strNegativeFactor.toUTF8();9166 }91679168 iScore += iBaseReluctanceScore;91699170 // **************************9171 // Current influence of major9172 //9173 // -999 ~ -09174 // **************************9175 if(GetEffectiveFriendshipWithMajor(eBullyPlayer) < GC.getFRIENDSHIP_THRESHOLD_CAN_BULLY())9176 {9177 int iInfluenceScore = iFailScore;9178 iScore += iInfluenceScore;9179 if (sTooltipSink)9180 {9181 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9182 strNegativeFactor << iInfluenceScore;9183 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_LOW_INFLUENCE";9184 sFactors += strNegativeFactor.toUTF8();9185 }9186 }91879188 // **************************9189 // Previous bully attempts9190 //9191 // -300 ~ -09192 // **************************9193 int iLastBullyTurn = GetTurnLastBulliedByMajor(eBullyPlayer);9194 if(iLastBullyTurn >= 0)9195 {9196 if(iLastBullyTurn + 10 >= GC.getGame().getGameTurn())9197 {9198 int iBulliedVeryRecentlyScore = iFailScore;9199 iScore += iBulliedVeryRecentlyScore;9200 if (sTooltipSink)9201 {9202 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9203 strNegativeFactor << iBulliedVeryRecentlyScore;9204 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_BULLIED_VERY_RECENTLY";9205 sFactors += strNegativeFactor.toUTF8();9206 }9207 }9208 else if(iLastBullyTurn + 20 >= GC.getGame().getGameTurn())9209 {9210 int iBulliedRecentlyScore = -40;9211 iScore += iBulliedRecentlyScore;9212 if (sTooltipSink)9213 {9214 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9215 strNegativeFactor << iBulliedRecentlyScore;9216 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_BULLIED_RECENTLY";9217 sFactors += strNegativeFactor.toUTF8();9218 }9219 }9220 }92219222 // **************************9223 // Tribute type9224 //9225 // -30 ~ -09226 // **************************9227 if (bForUnit)9228 {9229 int iUnitScore = -30;9230 iScore += iUnitScore;9231 if (sTooltipSink)9232 {9233 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9234 strNegativeFactor << iUnitScore;9235 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_UNIT_RELUCTANCE";9236 sFactors += strNegativeFactor.toUTF8();9237 }9238 }92399240 // **************************9241 // City-State population9242 //9243 // -300 ~ -09244 // **************************9245 if (bForUnit)9246 {9247 if (GetPlayer()->getCapitalCity() == NULL || GetPlayer()->getCapitalCity()->getPopulation() < 4)9248 {9249 int iPopulationScore = iFailScore;9250 iScore += iPopulationScore;9251 if (sTooltipSink)9252 {9253 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9254 strNegativeFactor << iPopulationScore;9255 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_LOW_POPULATION";9256 sFactors += strNegativeFactor.toUTF8();9257 }9258 }9259 }92609261 // **************************9262 // Passive Support from other majors9263 //9264 // -10 ~ -09265 // **************************9266 if(GetAlly() != NO_PLAYER && GetAlly() != eBullyPlayer)9267 {9268 int iAllyScore = -10;9269 iScore += iAllyScore;9270 if (sTooltipSink)9271 {9272 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9273 strNegativeFactor << iAllyScore;9274 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_ALLIES";9275 sFactors += strNegativeFactor.toUTF8();9276 }9277 }92789279 // **************************9280 // Pledges of Protection from other majors9281 //9282 // -20 ~ -09283 // **************************9284 for(int iMajorLoop = 0; iMajorLoop < MAX_MAJOR_CIVS; iMajorLoop++)9285 {9286 int iProtectionScore = 0;9287 eMajorLoop = (PlayerTypes) iMajorLoop;9288 if(eMajorLoop != eBullyPlayer && IsProtectedByMajor(eMajorLoop))9289 {9290 iProtectionScore += -20;9291 iScore += iProtectionScore;9292 if (sTooltipSink)9293 {9294 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9295 strNegativeFactor << iProtectionScore;9296 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_PLEDGES_TO_PROTECT";9297 sFactors += strNegativeFactor.toUTF8();9298 }9299 break;9300 }9301 }93029303 // **************************9304 // Minor Civ Type9305 //9306 // -20 ~ -09307 // **************************9308 if(GetPersonality() == MINOR_CIV_PERSONALITY_HOSTILE)9309 {9310 int iHostileScore = -10;9311 iScore += iHostileScore;9312 if (sTooltipSink)9313 {9314 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9315 strNegativeFactor << iHostileScore;9316 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_HOSTILE";9317 sFactors += strNegativeFactor.toUTF8();9318 }9319 }9320 if(GetTrait() == MINOR_CIV_TRAIT_MILITARISTIC)9321 {9322 int iMilitaristicScore = -10;9323 iScore += iMilitaristicScore;9324 if (sTooltipSink)9325 {9326 Localization::String strNegativeFactor = Localization::Lookup("TXT_KEY_POP_CSTATE_BULLY_FACTOR_NEGATIVE");9327 strNegativeFactor << iMilitaristicScore;9328 strNegativeFactor << "TXT_KEY_POP_CSTATE_BULLY_FACTOR_MILITARISTIC";9329 sFactors += strNegativeFactor.toUTF8();9330 }9331 }93329333 if (sTooltipSink != NULL)9334 {9335 (*sTooltipSink) += sFactors;9336 }93379338 return iScore;9339}