Hooks
static bool BeforeCvUnit_initWithNameOffset(CvUnit* self, int iID, UnitTypes eUnit, int iNameOffset, UnitAITypes eUnitAI, PlayerTypes eOwner, int iX, int iY, DirectionTypes eFacingDirection, bool bNoMove, bool bSetupGraphical, int iMapLayer, int iNumGoodyHutsPopped);static void AfterCvUnit_initWithNameOffset(CvUnit* self, int iID, UnitTypes eUnit, int iNameOffset, UnitAITypes eUnitAI, PlayerTypes eOwner, int iX, int iY, DirectionTypes eFacingDirection, bool bNoMove, bool bSetupGraphical, int iMapLayer, int iNumGoodyHutsPopped);static void ReplaceCvUnit_initWithNameOffset(void (*original)(CvUnit*, int, UnitTypes, int, UnitAITypes, PlayerTypes, int, int, DirectionTypes, bool, bool, int, int), CvUnit* self, int iID, UnitTypes eUnit, int iNameOffset, UnitAITypes eUnitAI, PlayerTypes eOwner, int iX, int iY, DirectionTypes eFacingDirection, bool bNoMove, bool bSetupGraphical, int iMapLayer, int iNumGoodyHutsPopped);CivRegisterBefore<CivHooks::CvUnit_initWithNameOffset>(host, &BeforeCvUnit_initWithNameOffset);CivRegisterAfter<CivHooks::CvUnit_initWithNameOffset>(host, &AfterCvUnit_initWithNameOffset);CivRegisterReplace<CivHooks::CvUnit_initWithNameOffset>(host, &ReplaceCvUnit_initWithNameOffset);
Code
425void CvUnit::initWithNameOffset(int iID, UnitTypes eUnit, int iNameOffset, UnitAITypes eUnitAI, PlayerTypes eOwner, int iX, int iY, DirectionTypes eFacingDirection, bool bNoMove, bool bSetupGraphical, int iMapLayer, int iNumGoodyHutsPopped)426{427 VALIDATE_OBJECT428 CvString strBuffer;429 int iUnitName;430 int iI;431432 CvAssert(NO_UNIT != eUnit);433434 initPromotions();435 m_pReligion->Init();436437 //--------------------------------438 // Init saved data439 reset(iID, eUnit, eOwner);440441 if(eFacingDirection == NO_DIRECTION)442 m_eFacingDirection = DIRECTION_SOUTHEAST;443 else444 m_eFacingDirection = eFacingDirection;445446 // If this is a hovering unit, we must add that promotion before setting XY, or else it'll get the embark promotion (which we don't want)447 PromotionTypes ePromotion;448 for(iI = 0; iI < GC.getNumPromotionInfos(); iI++)449 {450 if(getUnitInfo().GetFreePromotions(iI))451 {452 ePromotion = (PromotionTypes) iI;453454 if(GC.getPromotionInfo(ePromotion)->IsHoveringUnit())455 setHasPromotion(ePromotion, true);456 }457 }458459 // Set the layer of the map the unit resides460 m_iMapLayer = iMapLayer;461 462 // Set num goody huts popped463 m_iNumGoodyHutsPopped = iNumGoodyHutsPopped;464465 //--------------------------------466 // Init containers467468 //--------------------------------469 // Init pre-setup() data470 setXY(iX, iY, false, false, false, false, bNoMove);471472 //--------------------------------473 // Init non-saved data474475 //--------------------------------476 // Init other game data477 plot()->updateCenterUnit();478479 SetGreatWork(NO_GREAT_WORK);480 iUnitName = GC.getGame().getUnitCreatedCount(getUnitType());481 int iNumNames = getUnitInfo().GetNumUnitNames();482#if !defined(MOD_GLOBAL_NO_LOST_GREATWORKS)483 if(iUnitName < iNumNames)484#endif485 {486 if(iNameOffset == -1)487 {488 iNameOffset = GC.getGame().getJonRandNum(iNumNames, "Unit name selection");489 }490 491 for(iI = 0; iI < iNumNames; iI++)492 {493 int iIndex = (iNameOffset + iI) % iNumNames;494 CvString strName = getUnitInfo().GetUnitNames(iIndex);495 496#if defined(MOD_EVENTS_UNIT_DATA)497 if (MOD_EVENTS_UNIT_DATA) {498 if (GAMEEVENTINVOKE_TESTALL(GAMEEVENT_UnitCanHaveName, getOwner(), GetID(), iIndex) == GAMEEVENTRETURN_FALSE) {499 continue;500 }501 }502#endif503504 if(!GC.getGame().isGreatPersonBorn(strName))505 {506#if defined(MOD_EVENTS_UNIT_DATA)507 if (MOD_EVENTS_UNIT_DATA) {508 if (GAMEEVENTINVOKE_TESTALL(GAMEEVENT_UnitCanHaveGreatWork, getOwner(), GetID(), getUnitInfo().GetGreatWorks(iIndex)) == GAMEEVENTRETURN_FALSE) {509 continue;510 }511 }512#endif513 514 setName(strName);515 SetGreatWork(getUnitInfo().GetGreatWorks(iIndex));516 GC.getGame().addGreatPersonBornName(strName);517#if defined(MOD_GLOBAL_NO_LOST_GREATWORKS)518 if (MOD_GLOBAL_NO_LOST_GREATWORKS) {519 // setName strips undesirable characters, but we stored those into the list of GPs born, so we need to keep the original name520 setGreatName(strName);521 }522#endif523 break;524 }525 }526 }527528 setGameTurnCreated(GC.getGame().getGameTurn());529530 GC.getGame().incrementUnitCreatedCount(getUnitType());531532 CvPlayer& kPlayer = GET_PLAYER(getOwner());533534 GC.getGame().incrementUnitClassCreatedCount((UnitClassTypes)(getUnitInfo().GetUnitClassType()));535 GET_TEAM(getTeam()).changeUnitClassCount(((UnitClassTypes)(getUnitInfo().GetUnitClassType())), 1);536 kPlayer.changeUnitClassCount(((UnitClassTypes)(getUnitInfo().GetUnitClassType())), 1);537538 // Builder Limit539 if(getUnitInfo().GetWorkRate() > 0 && getUnitInfo().GetDomainType() == DOMAIN_LAND)540 {541 kPlayer.ChangeNumBuilders(1);542 }543544 // Units can add Unhappiness545 if(GC.getUnitInfo(getUnitType())->GetUnhappiness() != 0)546 {547 kPlayer.ChangeUnhappinessFromUnits(GC.getUnitInfo(getUnitType())->GetUnhappiness());548 }549550 kPlayer.changeExtraUnitCost(getUnitInfo().GetExtraMaintenanceCost());551552 // Add Resource Quantity to Used553 for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)554 {555 if(getUnitInfo().GetResourceQuantityRequirement(iResourceLoop) > 0)556 {557 kPlayer.changeNumResourceUsed((ResourceTypes) iResourceLoop, GC.getUnitInfo(getUnitType())->GetResourceQuantityRequirement(iResourceLoop));558 }559 }560561 if(getUnitInfo().GetNukeDamageLevel() != -1)562 {563 kPlayer.changeNumNukeUnits(1);564 }565566 if(getUnitInfo().IsMilitarySupport())567 {568 kPlayer.changeNumMilitaryUnits(1);569 }570571 // Free Promotions from Unit XML572 for(iI = 0; iI < GC.getNumPromotionInfos(); iI++)573 {574 if(getUnitInfo().GetFreePromotions(iI))575 {576 ePromotion = (PromotionTypes) iI;577578 if(!GC.getPromotionInfo(ePromotion)->IsHoveringUnit()) // Hovering units handled above579 setHasPromotion(ePromotion, true);580 }581 }582583 const UnitCombatTypes unitCombatType = getUnitCombatType();584 if(unitCombatType != NO_UNITCOMBAT)585 {586 // Any free Promotions to apply?587 for(int iJ = 0; iJ < GC.getNumPromotionInfos(); iJ++)588 {589 const PromotionTypes promotionID = (PromotionTypes)iJ;590 if(kPlayer.GetPlayerTraits()->HasFreePromotionUnitCombat(promotionID, unitCombatType))591 {592 setHasPromotion(promotionID, true);593 }594 }595 }596597 // Free Promotions from Policies, Techs, etc.598 for(iI = 0; iI < GC.getNumPromotionInfos(); iI++)599 {600 ePromotion = (PromotionTypes) iI;601602 if(kPlayer.IsFreePromotion(ePromotion))603 {604 // Valid Promotion for this Unit?605 if(::IsPromotionValidForUnitCombatType(ePromotion, getUnitType()))606 {607 setHasPromotion(ePromotion, true);608 }609610 else if(::IsPromotionValidForCivilianUnitType(ePromotion, getUnitType()))611 {612 setHasPromotion(ePromotion, true);613 }614615 }616 }617618 // Give embark promotion for free?619 if(GET_TEAM(getTeam()).canEmbark() || kPlayer.GetPlayerTraits()->IsEmbarkedAllWater())620 {621 PromotionTypes ePromotionEmbarkation = kPlayer.GetEmbarkationPromotion();622623 bool bGivePromotion = false;624625 // Civilians get it for free626 if(getDomainType() == DOMAIN_LAND)627 {628 if(!IsCombatUnit())629 bGivePromotion = true;630 }631632 // Can the unit get this? (handles water units and such)633 if(!bGivePromotion && ::IsPromotionValidForUnitCombatType(ePromotionEmbarkation, getUnitType()))634 bGivePromotion = true;635636 // Some case that gives us the promotion?637 if(bGivePromotion)638 setHasPromotion(ePromotionEmbarkation, true);639 }640 641#if defined(MOD_PROMOTIONS_DEEP_WATER_EMBARKATION)642 // Flip Deep Water Embarkation to Defensive Deep Water Embarkation if the player has the required trait643 if (IsEmbarkDeepWater()) {644 setHasPromotion((PromotionTypes)GC.getPROMOTION_DEEPWATER_EMBARKATION(), false);645 setHasPromotion(kPlayer.GetDeepWaterEmbarkationPromotion(), true);646 }647#endif648649 // Strip off Ocean Impassable promotion because of trait?650 if(kPlayer.GetPlayerTraits()->IsEmbarkedAllWater())651 {652 PromotionTypes ePromotionOceanImpassable = (PromotionTypes)GC.getPROMOTION_OCEAN_IMPASSABLE();653 if(isHasPromotion(ePromotionOceanImpassable))654 {655 setHasPromotion(ePromotionOceanImpassable, false);656 }657 PromotionTypes ePromotionOceanImpassableUntilAstronomy = (PromotionTypes)GC.getPROMOTION_OCEAN_IMPASSABLE_UNTIL_ASTRONOMY();658 if(isHasPromotion(ePromotionOceanImpassableUntilAstronomy))659 {660 setHasPromotion(ePromotionOceanImpassableUntilAstronomy, false);661 }662 }663664 // Any exotic goods that can be sold? (Portuguese unique unit mission)665 if (getUnitInfo().GetNumExoticGoods() > 0)666 {667 changeNumExoticGoods(getUnitInfo().GetNumExoticGoods());668 }669670 // free XP from handicap?671 int iXP = GC.getGame().getHandicapInfo().getAIFreeXP();672 if (iXP && !kPlayer.isHuman() && /*kPlayer.GetID() < MAX_MAJOR_CIVS &&*/ canAcquirePromotionAny())673 {674#if defined(MOD_UNITS_XP_TIMES_100)675 changeExperienceTimes100(iXP * 100);676#else677 changeExperience(iXP);678#endif679 }680681 // bonus xp in combat from handicap?682 int iXPPercent = GC.getGame().getHandicapInfo().getAIFreeXPPercent();683 if (iXPPercent && !kPlayer.isHuman() && /*kPlayer.GetID() < MAX_MAJOR_CIVS &&*/ canAcquirePromotionAny())684 {685 changeExperiencePercent(iXPPercent);686 }687688689 // Is this Unit immobile?690 if(getUnitInfo().IsImmobile())691 {692 SetImmobile(true);693 }694695 setMoves(maxMoves());696697 // Religious unit? If so takes religion from city698 if (getUnitInfo().IsSpreadReligion() || getUnitInfo().IsRemoveHeresy())699 {700 CvCity *pPlotCity = plot()->getPlotCity();701 if (pPlotCity)702 {703 ReligionTypes eReligion = pPlotCity->GetCityReligions()->GetReligiousMajority();704 if (eReligion > RELIGION_PANTHEON)705 {706 GetReligionData()->SetReligion(eReligion);707 GetReligionData()->SetSpreadsLeft(getUnitInfo().GetReligionSpreads() + pPlotCity->GetCityBuildings()->GetMissionaryExtraSpreads());708 GetReligionData()->SetReligiousStrength(getUnitInfo().GetReligiousStrength());709 }710 }711#if defined(MOD_GLOBAL_RELIGIOUS_SETTLERS)712 }713 else if (MOD_GLOBAL_RELIGIOUS_SETTLERS && (getUnitInfo().IsFound() || getUnitInfo().IsFoundAbroad()))714 {715 ReligionTypes eReligion = RELIGION_PANTHEON;716717 CvCity *pPlotCity = plot()->getPlotCity();718 if (pPlotCity)719 {720 CvCityReligions *pCityReligions = pPlotCity->GetCityReligions();721722 int totalFollowers = pPlotCity->getPopulation();723 int randFollower = GC.getGame().getJonRandNum(totalFollowers, "Religious Settlers: Picking a random religion for the settler") + 1;724725 for (int i = RELIGION_PANTHEON; i < GC.getNumReligionInfos(); i++)726 {727 int theseFollowers = pCityReligions->GetNumFollowers((ReligionTypes) i);728729 if (randFollower <= theseFollowers)730 {731 eReligion = (ReligionTypes) i;732 break;733 }734735 randFollower = randFollower - theseFollowers;736 if (randFollower < 0) break;737 }738 }739740 GetReligionData()->SetReligion(eReligion);741#endif742 }743 if (getUnitInfo().GetOneShotTourism() > 0)744 {745 SetTourismBlastStrength(kPlayer.GetCulture()->GetTourismBlastStrength(getUnitInfo().GetOneShotTourism()));746 }747748 int iTourism = kPlayer.GetPlayerPolicies()->GetTourismFromUnitCreation((UnitClassTypes)(getUnitInfo().GetUnitClassType()));749 if (iTourism > 0)750 {751 kPlayer.GetCulture()->AddTourismAllKnownCivs(iTourism);752 }753754 // Recon unit? If so, he sees what's around him755 if(IsRecon())756 {757 setReconPlot(plot());758 }759760 if(getDomainType() == DOMAIN_LAND)761 {762 if(IsCombatUnit())763 {764 if((GC.getGame().getBestLandUnit() == NO_UNIT) || (GetBaseCombatStrength() > GC.getGame().getBestLandUnitCombat()))765 {766 GC.getGame().setBestLandUnit(getUnitType());767 }768 }769 }770771 // Update UI772 if(getOwner() == GC.getGame().getActivePlayer())773 {774 DLLUI->setDirty(GameData_DIRTY_BIT, true);775776 kPlayer.GetUnitCycler().AddUnit( GetID() );777 }778779 // Message for World Unit being born780 if(isWorldUnitClass((UnitClassTypes)(getUnitInfo().GetUnitClassType())))781 {782 for(iI = 0; iI < MAX_PLAYERS; iI++)783 {784 if(GET_PLAYER((PlayerTypes)iI).isAlive() && GC.getGame().getActivePlayer())785 {786 if(GET_TEAM(getTeam()).isHasMet(GET_PLAYER((PlayerTypes)iI).getTeam()))787 {788 strBuffer = GetLocalizedText("TXT_KEY_MISC_SOMEONE_CREATED_UNIT", kPlayer.getNameKey(), getNameKey());789 DLLUI->AddMessage(0, ((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), strBuffer/*, "AS2D_WONDER_UNIT_BUILD", MESSAGE_TYPE_MAJOR_EVENT, getUnitInfo().GetButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_UNIT_TEXT"), getX(), getY(), true, true*/);790 }791 else792 {793 strBuffer = GetLocalizedText("TXT_KEY_MISC_UNKNOWN_CREATED_UNIT", getNameKey());794 DLLUI->AddMessage(0, ((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), strBuffer/*, "AS2D_WONDER_UNIT_BUILD", MESSAGE_TYPE_MAJOR_EVENT, getUnitInfo().GetButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_UNIT_TEXT")*/);795 }796 }797 }798799 strBuffer = GetLocalizedText("TXT_KEY_MISC_SOMEONE_CREATED_UNIT", kPlayer.getNameKey(), getNameKey());800 GC.getGame().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getOwner(), strBuffer, getX(), getY());801 }802803 // Update City Strength804 if(plot()->isCity())805 {806 plot()->getPlotCity()->updateStrengthValue();807 }808809 m_iArmyId = FFreeList::INVALID_INDEX;810811 m_eUnitAIType = eUnitAI;812813 // Update Unit Production Maintenance814 kPlayer.UpdateUnitProductionMaintenanceMod();815816 // Minor Civ quest817 if(!kPlayer.isMinorCiv() && !isBarbarian())818 {819 PlayerTypes eMinor;820 for(int iMinorCivLoop = MAX_MAJOR_CIVS; iMinorCivLoop < MAX_CIV_PLAYERS; iMinorCivLoop++)821 {822 eMinor = (PlayerTypes) iMinorCivLoop;823 if(GET_PLAYER(eMinor).isAlive())824 {825 // Does this Minor want us to spawn a Unit?826 GET_PLAYER(eMinor).GetMinorCivAI()->DoTestActiveQuestsForPlayer(getOwner(), /*bTestComplete*/ true, /*bTestObsolete*/ false, MINOR_CIV_QUEST_GREAT_PERSON);827 }828 }829 }830831 if(bSetupGraphical)832 setupGraphical();833 834#if defined(MOD_EVENTS_UNIT_CREATED)835 if (MOD_EVENTS_UNIT_CREATED) {836 GAMEEVENTINVOKE_HOOK(GAMEEVENT_UnitCreated, getOwner(), GetID(), getUnitType(), getX(), getY());837 }838#endif839}