Hooks
static bool BeforeCvPlayer_canReceiveGoody(const CvPlayer* self, CvPlot* pPlot, GoodyTypes eGoody, CvUnit* pUnit, bool& result);static void AfterCvPlayer_canReceiveGoody(const CvPlayer* self, CvPlot* pPlot, GoodyTypes eGoody, CvUnit* pUnit, bool& result);static bool ReplaceCvPlayer_canReceiveGoody(bool (*original)(const CvPlayer*, CvPlot*, GoodyTypes, CvUnit*), const CvPlayer* self, CvPlot* pPlot, GoodyTypes eGoody, CvUnit* pUnit);CivRegisterBefore<CivHooks::CvPlayer_canReceiveGoody>(host, &BeforeCvPlayer_canReceiveGoody);CivRegisterAfter<CivHooks::CvPlayer_canReceiveGoody>(host, &AfterCvPlayer_canReceiveGoody);CivRegisterReplace<CivHooks::CvPlayer_canReceiveGoody>(host, &ReplaceCvPlayer_canReceiveGoody);
Code
6315/// Is a Particular Goody ID a valid Goody for a certain plot?6316bool CvPlayer::canReceiveGoody(CvPlot* pPlot, GoodyTypes eGoody, CvUnit* pUnit) const6317{6318 CvCity* pCity;6319 UnitTypes eUnit;6320 bool bTechFound;6321 int iI;63226323 Database::SingleResult kResult;6324 CvGoodyInfo kGoodyInfo;6325 const bool bResult = DB.SelectAt(kResult, "GoodyHuts", eGoody);6326 DEBUG_VARIABLE(bResult);6327 CvAssertMsg(bResult, "Cannot find goody info.");6328 kGoodyInfo.CacheResult(kResult);63296330#if defined(MOD_EVENTS_GOODY_CHOICE)6331 if (MOD_EVENTS_GOODY_CHOICE) {6332 bool bPick = (pUnit && pUnit->isHasPromotion((PromotionTypes)GC.getPROMOTION_GOODY_HUT_PICKER()));6333 int iUnit = pUnit ? pUnit->GetID() : -1;6334 if (GAMEEVENTINVOKE_TESTANY(GAMEEVENT_GoodyHutCanNotReceive, GetID(), iUnit, eGoody, bPick) == GAMEEVENTRETURN_TRUE) {6335 return false;6336 }6337 }6338#endif63396340 if(!CvGoodyHuts::IsCanPlayerReceiveGoody(GetID(), eGoody))6341 {6342 return false;6343 }63446345 // No XP in first 10 turns6346 if(kGoodyInfo.getExperience() > 0)6347 {6348 if((pUnit == NULL) || !(pUnit->canAcquirePromotionAny()) || (GC.getGame().getElapsedGameTurns() < 10))6349 {6350 return false;6351 }6352 }63536354 // Unit Healing6355 if(kGoodyInfo.getDamagePrereq() > 0)6356 {6357 if((pUnit == NULL) || (pUnit->getDamage() < ((pUnit->GetMaxHitPoints() * kGoodyInfo.getDamagePrereq()) / 100)))6358 {6359 return false;6360 }6361 }63626363 // Early pantheon6364 if(kGoodyInfo.isPantheonFaith())6365 {6366 if(GC.getGame().getElapsedGameTurns() < 20)6367 {6368 return false;6369 }6370 else6371 {6372 return (!GetReligions()->HasCreatedPantheon() && !GetReligions()->HasCreatedReligion());6373 }6374 }63756376 // Faith toward Great Prophet6377 if(kGoodyInfo.getProphetPercent() > 0)6378 {6379 if(GC.getGame().getElapsedGameTurns() < 20)6380 {6381 return false;6382 }6383 else6384 {6385 return (GetReligions()->HasCreatedPantheon() && !GetReligions()->HasCreatedReligion());6386 }6387 }63886389 // Population6390 if(kGoodyInfo.getPopulation() > 0)6391 {6392 if(getNumCities() == 0)6393 {6394 return false;6395 }63966397 // Don't give more Population if we're already over our Pop limit6398 if(IsEmpireUnhappy())6399 {6400 return false;6401 }6402 }64036404 // Reveal Nearby Barbs6405 if(kGoodyInfo.getRevealNearbyBarbariansRange() > 0)6406 {6407 int iDX, iDY;6408 int iBarbCampDistance = kGoodyInfo.getRevealNearbyBarbariansRange();6409 CvPlot* pNearbyPlot;64106411 int iNumCampsFound = 0;64126413 ImprovementTypes barbCampType = (ImprovementTypes) GC.getBARBARIAN_CAMP_IMPROVEMENT();64146415 // Look at nearby Plots to make sure another camp isn't too close6416 for(iDX = -(iBarbCampDistance); iDX <= iBarbCampDistance; iDX++)6417 {6418 for(iDY = -(iBarbCampDistance); iDY <= iBarbCampDistance; iDY++)6419 {6420 pNearbyPlot = plotXY(pPlot->getX(), pPlot->getY(), iDX, iDY);64216422 if(pNearbyPlot != NULL)6423 {6424 if(plotDistance(pNearbyPlot->getX(), pNearbyPlot->getY(), pPlot->getX(), pPlot->getY()) <= iBarbCampDistance)6425 {6426 if(pNearbyPlot->getImprovementType() == barbCampType)6427 {6428 iNumCampsFound++;6429 }6430 }6431 }6432 }6433 }64346435 // Needs to be at least 2 nearby Camps6436 if(iNumCampsFound < 2)6437 {6438 return false;6439 }6440 }64416442 // Reveal Unknown Resource6443 if(kGoodyInfo.isRevealUnknownResource())6444 {6445 // Can't get this if you have no Capital City6446 if(getCapitalCity() == NULL)6447 {6448 return false;6449 }64506451 CvResourceInfo* pResource;6452 ResourceClassTypes eResourceClassBonus = (ResourceClassTypes) GC.getInfoTypeForString("RESOURCECLASS_BONUS");64536454 bool bPlayerDoesntKnowOfResource = false;64556456 int iNumResourceInfos = GC.getNumResourceInfos();6457 for(int iResourceLoop = 0; iResourceLoop < iNumResourceInfos; iResourceLoop++)6458 {6459 pResource = GC.getResourceInfo((ResourceTypes) iResourceLoop);64606461 // No "Bonus" Resources (that only give Yield), because those are lame to get from a Hut6462 if(pResource != NULL && pResource->getResourceClassType() != eResourceClassBonus)6463 {6464 if(!GET_TEAM(getTeam()).GetTeamTechs()->HasTech((TechTypes) pResource->getTechReveal()))6465 {6466 bPlayerDoesntKnowOfResource = true;6467 }6468 }6469 }64706471 // If the player already knows where all the Resources are then there's no point in this Goody6472 if(!bPlayerDoesntKnowOfResource)6473 {6474 return false;6475 }6476 }64776478 // Unit Upgrade6479 if(kGoodyInfo.isUpgradeUnit())6480 {6481 if(pUnit == NULL)6482 {6483 return false;6484 }64856486 if(pUnit->IsHasBeenPromotedFromGoody())6487 {6488 return false;6489 }64906491 UnitClassTypes eUpgradeUnitClass = (UnitClassTypes) GC.getUnitInfo(pUnit->getUnitType())->GetGoodyHutUpgradeUnitClass();64926493 if(eUpgradeUnitClass == NO_UNITCLASS)6494 {6495 return false;6496 }64976498 UnitTypes eUpgradeUnit = (UnitTypes) getCivilizationInfo().getCivilizationUnits(eUpgradeUnitClass);64996500 if(eUpgradeUnit == NO_UNIT)6501 {6502 return false;6503 }6504 }65056506 // Tech6507 if(kGoodyInfo.isTech())6508 {6509 bTechFound = false;65106511 int iNumTechInfos = GC.getNumTechInfos();6512 for(iI = 0; iI < iNumTechInfos; iI++)6513 {6514 const TechTypes eTech = static_cast<TechTypes>(iI);6515 CvTechEntry* pkTech = GC.getTechInfo(eTech);6516 if(pkTech != NULL && pkTech->IsGoodyTech())6517 {6518 if(GetPlayerTechs()->CanResearch(eTech))6519 {6520 bool bUseTech = true;6521 ICvEngineScriptSystem1* pkScriptSystem = gDLL->GetScriptSystem();6522 if (pkScriptSystem) 6523 {6524 CvLuaArgsHandle args;6525 args->Push(GetID());6526 args->Push(eTech);65276528 // Attempt to execute the game events.6529 // Will return false if there are no registered listeners.6530 bool bScriptResult = false;6531 if (LuaSupport::CallTestAll(pkScriptSystem, "GoodyHutCanResearch", args.get(), bScriptResult)) 6532 {6533 bUseTech = bResult;6534 }6535 }65366537 if(bUseTech)6538 {6539 bTechFound = true;6540 }6541 break;6542 }6543 }6544 }65456546 if(!bTechFound)6547 {6548 return false;6549 }6550 }65516552 ///////////////////////////////////////6553 ///////////////////////////////////////6554 // Bad Goodies follow beneath this line6555 ///////////////////////////////////////6556 ///////////////////////////////////////65576558 if(kGoodyInfo.isBad())6559 {6560 if((pUnit == NULL) || pUnit->isNoBadGoodies())6561 {6562 return false;6563 }6564 }65656566 if(kGoodyInfo.getUnitClassType() != NO_UNITCLASS)6567 {6568 eUnit = ((UnitTypes)(getCivilizationInfo().getCivilizationUnits(kGoodyInfo.getUnitClassType())));65696570 if(eUnit == NO_UNIT)6571 {6572 return false;6573 }65746575 CvUnitEntry* pUnitInfo = GC.getUnitInfo(eUnit);6576 if(pUnitInfo == NULL)6577 {6578 return false;6579 }65806581 // No combat units in MP in the first 20 turns6582 if(pUnitInfo->GetCombat() > 0)6583 {6584 if(GC.getGame().isGameMultiPlayer() || (GC.getGame().getElapsedGameTurns() < 20))6585 {6586 return false;6587 }6588 }65896590 // Builders6591 if(pUnitInfo->GetWorkRate() > 0)6592 {6593 // Max limit6594 if(GetMaxNumBuilders() > -1 && GetNumBuilders() >= GetMaxNumBuilders())6595 {6596 return false;6597 }65986599 bool bHasTechWhichUnlocksImprovement = false;66006601 // Need a tech which unlocks something to do6602 int iNumTechInfos = GC.getNumTechInfos();6603 int iNumBuildInfos = GC.getNumBuildInfos();6604 for(int iTechLoop = 0; iTechLoop < iNumTechInfos; iTechLoop++)6605 {6606 if(GET_TEAM(getTeam()).GetTeamTechs()->HasTech((TechTypes) iTechLoop))6607 {6608 // Look at Builds6609 for(int iBuildLoop = 0; iBuildLoop < iNumBuildInfos; iBuildLoop++)6610 {6611 CvBuildInfo* pkBuildInfo = GC.getBuildInfo((BuildTypes) iBuildLoop);6612 if(!pkBuildInfo)6613 {6614 continue;6615 }6616 if(pkBuildInfo->getTechPrereq() == (TechTypes) iTechLoop)6617 {6618 if(pkBuildInfo->getImprovement() != NO_IMPROVEMENT || pkBuildInfo->getRoute() != NO_ROUTE)6619 {6620 bHasTechWhichUnlocksImprovement = true;6621 break;6622 }6623 }6624 }6625 }6626 // Already found something6627 if(bHasTechWhichUnlocksImprovement)6628 {6629 break;6630 }6631 }66326633 // Player doesn't have any Tech which allows Improvements6634 if(!bHasTechWhichUnlocksImprovement)6635 {6636 return false;6637 }6638 }66396640 // OCC games - no Settlers6641 if(GetPlayerTraits()->IsNoAnnexing() || (GC.getGame().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && isHuman()))6642 {6643 if(pUnitInfo->IsFound() || pUnitInfo->IsFoundAbroad())6644 {6645 return false;6646 }6647 }6648 }66496650 // Barbarians6651 if(kGoodyInfo.getBarbarianUnitClass() != NO_UNITCLASS)6652 {6653 if(GC.getGame().isOption(GAMEOPTION_NO_BARBARIANS))6654 {6655 return false;6656 }66576658 if(getNumCities() == 0)6659 {6660 return false;6661 }66626663 if(getNumCities() == 1)6664 {6665 pCity = GC.getMap().findCity(pPlot->getX(), pPlot->getY(), NO_PLAYER, getTeam());66666667 if(pCity != NULL)6668 {6669 if(plotDistance(pPlot->getX(), pPlot->getY(), pCity->getX(), pCity->getY()) <= (8 - getNumCities()))6670 {6671 return false;6672 }6673 }6674 }6675 }66766677 return true;6678}