Hooks
static bool BeforeCvPlayer_canTrain(const CvPlayer* self, UnitTypes eUnit, bool bContinue, bool bTestVisible, bool bIgnoreCost, bool bIgnoreUniqueUnitStatus, CvString* toolTipSink, bool& result);static void AfterCvPlayer_canTrain(const CvPlayer* self, UnitTypes eUnit, bool bContinue, bool bTestVisible, bool bIgnoreCost, bool bIgnoreUniqueUnitStatus, CvString* toolTipSink, bool& result);static bool ReplaceCvPlayer_canTrain(bool (*original)(const CvPlayer*, UnitTypes, bool, bool, bool, bool, CvString*), const CvPlayer* self, UnitTypes eUnit, bool bContinue, bool bTestVisible, bool bIgnoreCost, bool bIgnoreUniqueUnitStatus, CvString* toolTipSink);CivRegisterBefore<CivHooks::CvPlayer_canTrain>(host, &BeforeCvPlayer_canTrain);CivRegisterAfter<CivHooks::CvPlayer_canTrain>(host, &AfterCvPlayer_canTrain);CivRegisterReplace<CivHooks::CvPlayer_canTrain>(host, &ReplaceCvPlayer_canTrain);
Code
7649bool CvPlayer::canTrain(UnitTypes eUnit, bool bContinue, bool bTestVisible, bool bIgnoreCost, bool bIgnoreUniqueUnitStatus, CvString* toolTipSink) const7650{7651 CvUnitEntry* pUnitInfoPtr = GC.getUnitInfo(eUnit);7652 if(pUnitInfoPtr == NULL)7653 return false;76547655 CvUnitEntry& pUnitInfo = *pUnitInfoPtr;76567657 const UnitClassTypes eUnitClass = (UnitClassTypes) pUnitInfo.GetUnitClassType();7658 if(eUnitClass == NO_UNITCLASS)7659 {7660 return false;7661 }76627663 CvUnitClassInfo* pkUnitClassInfo = GC.getUnitClassInfo(eUnitClass);7664 if(pkUnitClassInfo == NULL)7665 {7666 return false;7667 }76687669 if (GetPlayerTraits()->NoTrain(eUnitClass))7670 {7671 return false;7672 }76737674 // Should we check whether this Unit has been blocked out by the civ XML?7675 if(!bIgnoreUniqueUnitStatus)7676 {7677 UnitTypes eThisPlayersUnitType = (UnitTypes) getCivilizationInfo().getCivilizationUnits(eUnitClass);76787679 // If the player isn't allowed to train this Unit (via XML) then return false7680 if(eThisPlayersUnitType != eUnit)7681 {7682 return false;7683 }7684 }76857686 if(!bIgnoreCost)7687 {7688 if(pUnitInfo.GetProductionCost() == -1)7689 {7690 return false;7691 }7692 }76937694 // One City Challenge7695 if(pUnitInfo.IsFound() || pUnitInfo.IsFoundAbroad())7696 {7697 if(GC.getGame().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && isHuman())7698 {7699 return false;7700 }7701 }7702 7703 //Policy Requirement7704 PolicyTypes ePolicy = (PolicyTypes)pUnitInfo.GetPolicyType();7705 if (ePolicy != NO_POLICY)7706 {7707 if (!GetPlayerPolicies()->HasPolicy(ePolicy))7708 {7709 return false;7710 }7711 }771277137714 if (GC.getGame().isOption(GAMEOPTION_NO_RELIGION))7715 {7716 if (pUnitInfo.IsFoundReligion() || pUnitInfo.IsSpreadReligion() || pUnitInfo.IsRemoveHeresy())7717 {7718 return false;7719 }7720 }77217722 if(!bContinue)7723 {7724 if(!bTestVisible)7725 {7726 // Builder Limit7727 if(pUnitInfo.GetWorkRate() > 0 && pUnitInfo.GetDomainType() == DOMAIN_LAND)7728 {7729 if(GetMaxNumBuilders() > -1 && GetNumBuilders() >= GetMaxNumBuilders())7730 {7731 return false;7732 }7733 }7734 }7735 }77367737 // Tech requirements7738 if(!(GET_TEAM(getTeam()).GetTeamTechs()->HasTech((TechTypes)(pUnitInfo.GetPrereqAndTech()))))7739 {7740 return false;7741 }77427743 int iI;7744 for(iI = 0; iI < GC.getNUM_UNIT_AND_TECH_PREREQS(); iI++)7745 {7746 if(pUnitInfo.GetPrereqAndTechs(iI) != NO_TECH)7747 {7748 if(!(GET_TEAM(getTeam()).GetTeamTechs()->HasTech((TechTypes)(pUnitInfo.GetPrereqAndTechs(iI)))))7749 {7750 return false;7751 }7752 }7753 }77547755 // Obsolete Tech7756 if((TechTypes)pUnitInfo.GetObsoleteTech() != NO_TECH)7757 {7758 if(GET_TEAM(getTeam()).GetTeamTechs()->HasTech((TechTypes)(pUnitInfo.GetObsoleteTech())))7759 {7760 return false;7761 }7762 }77637764 // Game Unit Class Max7765 if(GC.getGame().isUnitClassMaxedOut(eUnitClass))7766 {7767 return false;7768 }77697770 // Team Unit Class Max7771 if(GET_TEAM(getTeam()).isUnitClassMaxedOut(eUnitClass))7772 {7773 return false;7774 }77757776 // Player Unit Class Max7777 if(isUnitClassMaxedOut(eUnitClass))7778 {7779 return false;7780 }77817782 // Spaceship part we already have?7783 ProjectTypes eProject = (ProjectTypes) pUnitInfo.GetSpaceshipProject();7784 if(eProject != NO_PROJECT)7785 {7786 if(GET_TEAM(getTeam()).isProjectMaxedOut(eProject))7787 return false;77887789 int iUnitAndProjectCount = GET_TEAM(getTeam()).getProjectCount(eProject) + getUnitClassCount(eUnitClass) + GET_TEAM(getTeam()).getUnitClassMaking(eUnitClass) + ((bContinue) ? -1 : 0);7790 if(iUnitAndProjectCount >= pkUnitClassInfo->getMaxPlayerInstances())7791 {7792 return false;7793 }7794 }77957796 if(!bTestVisible)7797 {7798 // Settlers7799 if(pUnitInfo.IsFound() || pUnitInfo.IsFoundAbroad())7800 {7801 if(IsEmpireVeryUnhappy() && GC.getVERY_UNHAPPY_CANT_TRAIN_SETTLERS() == 1)7802 {7803 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_VERY_UNHAPPY_SETTLERS");7804 if(toolTipSink == NULL)7805 return false;7806 }7807 }78087809 // Project required?7810 ProjectTypes ePrereqProject = (ProjectTypes) pUnitInfo.GetProjectPrereq();7811 if(ePrereqProject != NO_PROJECT)7812 {7813 CvProjectEntry* pkProjectInfo = GC.getProjectInfo(ePrereqProject);7814 if(pkProjectInfo)7815 {7816 if(GET_TEAM(getTeam()).getProjectCount(ePrereqProject) == 0)7817 {7818 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_UNIT_PROJECT_REQUIRED", pkProjectInfo->GetDescription());7819 if(toolTipSink == NULL)7820 return false;7821 }7822 }7823 }78247825 // Resource Requirements7826 for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)7827 {7828 const ResourceTypes eResource = static_cast<ResourceTypes>(iResourceLoop);7829 CvResourceInfo* pkResourceInfo = GC.getResourceInfo(eResource);7830 if(pkResourceInfo)7831 {7832 const int iNumResource = pUnitInfo.GetResourceQuantityRequirement(eResource);78337834 if(iNumResource > 0)7835 {7836 // Starting project, need enough Resources plus some to start7837 if(!bContinue && getNumResourceAvailable(eResource) < iNumResource)7838 {7839 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_UNIT_LACKS_RESOURCES", pkResourceInfo->GetIconString(), pkResourceInfo->GetTextKey(), iNumResource);7840 if(toolTipSink == NULL)7841 return false;7842 }7843 // Continuing project, need enough Resources7844 else if(bContinue && (getNumResourceAvailable(eResource) < 0))7845 {7846 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_UNIT_LACKS_RESOURCES", pkResourceInfo->GetIconString(), pkResourceInfo->GetTextKey(), iNumResource);7847 if(toolTipSink == NULL)7848 return false;7849 }7850 }7851 }78527853 }78547855 if(GC.getGame().isUnitClassMaxedOut(eUnitClass, (GET_TEAM(getTeam()).getUnitClassMaking(eUnitClass) + ((bContinue) ? -1 : 0))))7856 {7857 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_GAME_COUNT_MAX", "", "", pkUnitClassInfo->getMaxTeamInstances());7858 if(toolTipSink == NULL)7859 return false;7860 }78617862 if(GET_TEAM(getTeam()).isUnitClassMaxedOut(eUnitClass, (GET_TEAM(getTeam()).getUnitClassMaking(eUnitClass) + ((bContinue) ? -1 : 0))))7863 {7864 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_TEAM_COUNT_MAX", "", "", pkUnitClassInfo->getMaxTeamInstances());7865 if(toolTipSink == NULL)7866 return false;7867 }78687869 if(isUnitClassMaxedOut(eUnitClass, (getUnitClassMaking(eUnitClass) + ((bContinue) ? -1 : 0))))7870 {7871 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_PLAYER_COUNT_MAX", "", "", pkUnitClassInfo->getMaxPlayerInstances());7872 if(toolTipSink == NULL)7873 return false;7874 }78757876 if(GC.getGame().isNoNukes() || !GC.getGame().isNukesValid())7877 {7878 if(pUnitInfo.GetNukeDamageLevel() != -1)7879 {7880 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_NUKES");7881 if(toolTipSink == NULL)7882 return false;7883 }7884 }78857886 if(pUnitInfo.GetNukeDamageLevel() != -1)7887 {7888 if(GC.getGame().GetGameLeagues()->IsNoTrainingNuclearWeapons(GetID()))7889 {7890 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_NUKES_BY_RESOLUTION");7891 if(toolTipSink == NULL)7892 return false;7893 }7894 }78957896 if(pUnitInfo.GetSpecialUnitType() != NO_SPECIALUNIT)7897 {7898 if(!(GC.getGame().isSpecialUnitValid((SpecialUnitTypes)(pUnitInfo.GetSpecialUnitType()))))7899 {7900 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_NO_ACTION_SPECIAL_UNIT");7901 if(toolTipSink == NULL)7902 return false;7903 }7904 }79057906 if (pUnitInfo.IsTrade())7907 {7908 if (GetTrade()->GetNumTradeRoutesRemaining(bContinue) <= 0)7909 {7910 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_TRADE_UNIT_CONSTRUCTION_NO_EXTRA_SLOTS");7911 if (toolTipSink == NULL)7912 return false; 7913 }79147915 DomainTypes eDomain = (DomainTypes)pUnitInfo.GetDomainType();7916 if (!GetTrade()->CanCreateTradeRoute(eDomain))7917 {7918 if (eDomain == DOMAIN_LAND)7919 {7920 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_TRADE_UNIT_CONSTRUCTION_NONE_OF_TYPE_LAND");7921 }7922 else if (eDomain == DOMAIN_SEA)7923 {7924 GC.getGame().BuildCannotPerformActionHelpText(toolTipSink, "TXT_KEY_TRADE_UNIT_CONSTRUCTION_NONE_OF_TYPE_SEA");7925 }7926 if (toolTipSink == NULL)7927 return false;7928 }7929 }7930 }79317932 ICvEngineScriptSystem1* pkScriptSystem = gDLL->GetScriptSystem();7933 if(pkScriptSystem)7934 {7935 CvLuaArgsHandle args;7936 args->Push(GetID());7937 args->Push(eUnit);79387939 // Attempt to execute the game events.7940 // Will return false if there are no registered listeners.7941 bool bResult = false;7942 if(LuaSupport::CallTestAll(pkScriptSystem, "PlayerCanTrain", args.get(), bResult))7943 {7944 // Check the result.7945 if(bResult == false)7946 {7947 return false;7948 }7949 }7950 }79517952 return true;7953}