Hooks
static bool BeforeCvGame_GetRandomUniqueUnitType(CvGame* self, bool bIncludeCivsInGame, bool bIncludeStartEra, bool bIncludeOldEras, bool bIncludeRanged, UnitTypes& result);static void AfterCvGame_GetRandomUniqueUnitType(CvGame* self, bool bIncludeCivsInGame, bool bIncludeStartEra, bool bIncludeOldEras, bool bIncludeRanged, UnitTypes& result);static UnitTypes ReplaceCvGame_GetRandomUniqueUnitType(UnitTypes (*original)(CvGame*, bool, bool, bool, bool), CvGame* self, bool bIncludeCivsInGame, bool bIncludeStartEra, bool bIncludeOldEras, bool bIncludeRanged);CivRegisterBefore<CivHooks::CvGame_GetRandomUniqueUnitType>(host, &BeforeCvGame_GetRandomUniqueUnitType);CivRegisterAfter<CivHooks::CvGame_GetRandomUniqueUnitType>(host, &AfterCvGame_GetRandomUniqueUnitType);CivRegisterReplace<CivHooks::CvGame_GetRandomUniqueUnitType>(host, &ReplaceCvGame_GetRandomUniqueUnitType);
Code
8096UnitTypes CvGame::GetRandomUniqueUnitType(bool bIncludeCivsInGame, bool bIncludeStartEra, bool bIncludeOldEras, bool bIncludeRanged)8097{8098 // Find the unique units that have already been assigned8099 std::set<UnitTypes> setUniquesAlreadyAssigned;8100 for(int iMinorLoop = MAX_MAJOR_CIVS; iMinorLoop < MAX_CIV_PLAYERS; iMinorLoop++)8101 {8102 PlayerTypes eMinorLoop = (PlayerTypes) iMinorLoop;8103 CvPlayer* pMinorLoop = &GET_PLAYER(eMinorLoop);8104 if(pMinorLoop && pMinorLoop->isEverAlive())8105 {8106 UnitTypes eUniqueUnit = pMinorLoop->GetMinorCivAI()->GetUniqueUnit();8107 if(eUniqueUnit != NO_UNIT)8108 {8109 setUniquesAlreadyAssigned.insert(eUniqueUnit);8110 }8111 }8112 }8113 8114 CvWeightedVector<UnitTypes, SAFE_ESTIMATE_NUM_UNITS, true> veUnitRankings;81158116 // Loop through all Unit Classes8117 for(int iUnitLoop = 0; iUnitLoop < GC.getNumUnitInfos(); iUnitLoop++)8118 {8119 const UnitTypes eLoopUnit = (UnitTypes) iUnitLoop;8120 CvUnitEntry* pkUnitInfo = GC.getUnitInfo(eLoopUnit);8121 if(pkUnitInfo == NULL)8122 {8123 continue;8124 }81258126#if defined(MOD_GLOBAL_EXCLUDE_FROM_GIFTS)8127 if (MOD_GLOBAL_EXCLUDE_FROM_GIFTS) {8128 if (pkUnitInfo->IsNoMinorGifts()) {8129 continue;8130 }8131 }8132#endif81338134 bool bValid = (pkUnitInfo->GetCombat() > 0);81358136 // Unit has combat strength, make sure it isn't only defensive (and with no ranged combat ability)8137 if(bValid && pkUnitInfo->GetRange() == 0)8138 {8139 for(int iPromotionLoop = 0; iPromotionLoop < GC.getNumPromotionInfos(); iPromotionLoop++)8140 {8141 const PromotionTypes ePromotion = (PromotionTypes) iPromotionLoop;8142 CvPromotionEntry* pkPromotionInfo = GC.getPromotionInfo(ePromotion);8143 if(pkPromotionInfo)8144 {8145 if(pkUnitInfo->GetFreePromotions(iPromotionLoop))8146 {8147 if(pkPromotionInfo->IsOnlyDefensive())8148 {8149 bValid = false;8150 break;8151 }8152 }8153 }8154 }8155 }8156 if(!bValid)8157 continue;81588159 UnitClassTypes eLoopUnitClass = (UnitClassTypes) pkUnitInfo->GetUnitClassType();8160 CvUnitClassInfo* pkUnitClassInfo = GC.getUnitClassInfo(eLoopUnitClass);81618162 if(pkUnitClassInfo == NULL)8163 {8164 CvAssertMsg(false, "UnitClassInfo is NULL. Please send Anton your save file and version.");8165 continue;8166 }81678168 // We only want unique units8169 if(eLoopUnit == pkUnitClassInfo->getDefaultUnitIndex())8170 continue;81718172 // Is it a unique unit from a civ that is in our game?8173 if (!bIncludeCivsInGame)8174 {8175 for(int iMajorLoop = 0; iMajorLoop < MAX_PLAYERS; iMajorLoop++) // MAX_PLAYERS so that we look at Barbarian UUs (ie. Brute) as well8176 {8177 PlayerTypes eMajorLoop = (PlayerTypes) iMajorLoop;8178 if(GET_PLAYER(eMajorLoop).isAlive())8179 {8180 UnitTypes eUniqueUnitInGame = (UnitTypes) GET_PLAYER(eMajorLoop).getCivilizationInfo().getCivilizationUnits(eLoopUnitClass);8181 if(eLoopUnit == eUniqueUnitInGame)8182 {8183 bValid = false;8184 break;8185 }8186 }8187 }8188 }8189 if(!bValid)8190 continue;81918192 // Avoid Recon units8193 if(pkUnitInfo->GetDefaultUnitAIType() == UNITAI_EXPLORE)8194 continue;81958196 // No Ranged units?8197 if(!bIncludeRanged && pkUnitInfo->GetRangedCombat() > 0)8198 continue;81998200 // Must be land Unit8201 if(pkUnitInfo->GetDomainType() != DOMAIN_LAND)8202 continue;82038204 // Technology level8205 TechTypes ePrereqTech = (TechTypes) pkUnitInfo->GetPrereqAndTech();8206 EraTypes ePrereqEra = NO_ERA;8207 if (ePrereqTech != NO_TECH)8208 {8209 CvTechEntry* pkTechInfo = GC.getTechInfo(ePrereqTech);8210 CvAssertMsg(pkTechInfo, "Tech info not found when picking unique unit for minor civ. Please send Anton your save file and version!");8211 if (pkTechInfo)8212 {8213 ePrereqEra = (EraTypes) pkTechInfo->GetEra();8214 }8215 }82168217 if (ePrereqEra == getStartEra())8218 {8219 if (!bIncludeStartEra)8220 continue;8221 }8222 else if (ePrereqEra < getStartEra()) // Assumption: NO_ERA < 08223 {8224 if (!bIncludeOldEras)8225 continue;8226 }82278228 // Is this Unit already assigned to another minor civ?8229 if (setUniquesAlreadyAssigned.count(eLoopUnit) > 0)8230 continue;82318232 veUnitRankings.push_back(eLoopUnit, 1);8233 }82348235 UnitTypes eChosenUnit = NO_UNIT;82368237 if (veUnitRankings.size() > 0)8238 {8239 veUnitRankings.SortItems();8240 RandomNumberDelegate randFn = MakeDelegate(&GC.getGame(), &CvGame::getJonRandNum);8241 eChosenUnit = veUnitRankings.ChooseByWeight(&randFn, "Choosing random unique unit for minor civ");8242 }82438244 return eChosenUnit;8245}