"Real" Creative Trait (Can Build Other Civilization's Unique Buildings)

Cybah

Emperor
Joined
Jun 22, 2007
Messages
1,481
SDK (You need this new code, otherwise BuildingClassNeededs in CIV4BuildingInfos.xml won't work correctly):

CvCity.cpp:

PHP:
bool CvCity::canConstruct(BuildingTypes eBuilding, bool bContinue, bool bTestVisible, bool bIgnoreCost) const
{
// Cybah Start
	// BuildingTypes ePrereqBuilding;
// Cybah End

...

		if (bRequiresBonus && bNeedsBonus)
		{
			return false;
		}

// Cybah Start
		//for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		//{
			//if (GC.getBuildingInfo(eBuilding).isBuildingClassNeededInCity(iI))
			//{
				//ePrereqBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI)));

				//if (ePrereqBuilding != NO_BUILDING)
				//{
					//if (0 == getNumBuilding(ePrereqBuilding) /* && (bContinue || (getFirstBuildingOrder(ePrereqBuilding) == -1))*/)
					//{
						//return false;
					//}
				//}
			//}
		//}

		BuildingClassTypes eBuildingClass = (BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType()); 
		for (int iP = 0; iP < GC.getNumBuildingInfos(); iP++) 
		{ 
			int iLoopBuildingClass = GC.getBuildingInfo((BuildingTypes)iP).getBuildingClassType(); 
			if (iLoopBuildingClass == eBuildingClass && getNumBuilding((BuildingTypes)iP) > 0) 
			{ 
				return false; 
			} 
		} 

		int iPrereqBuildings = 0;
		int iHasPrereqBuildings = 0;
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			if (GC.getBuildingInfo(eBuilding).isBuildingClassNeededInCity(iI))
			{
				iPrereqBuildings += 1;
				int iPrereqBuildingClass = ((BuildingClassTypes)iI);
				int iJ; 
				for (iJ = 0; iJ < GC.getNumBuildingInfos(); iJ++) 
				{ 
					int iBuildingClass = GC.getBuildingInfo((BuildingTypes)iJ).getBuildingClassType(); 
					if (iPrereqBuildingClass == iBuildingClass && getNumBuilding((BuildingTypes)iJ) > 0) 
					{ 
						iHasPrereqBuildings += 1; 
					} 
				}
			}
		}

		if (iPrereqBuildings != iHasPrereqBuildings) 
		{ 
			return false;
		}
// Cybah End

Python:

CvEventManager.py:

PHP:
	def onBuildingBuilt(self, argsList):

...

# Creative Trait Start -----------------------------------------------------------------------------------------------
		pPlayer = gc.getPlayer(pCity.plot().getOwner())
		iTraitCre = gc.getInfoTypeForString("TRAIT_CREATIVE")
		if pPlayer.hasTrait(iTraitCre):
			l_UniqueBuildings = []
			for iCiv in xrange(gc.getNumCivilizationInfos()):
				for iBuilding in xrange(gc.getNumBuildingClassInfos()):
					iUniqueBuilding = gc.getCivilizationInfo(iCiv).getCivilizationBuildings(iBuilding);
					iDefaultBuilding = gc.getBuildingClassInfo(iBuilding).getDefaultBuildingIndex();
					if (iDefaultBuilding > -1 and iUniqueBuilding > -1 and iDefaultBuilding != iUniqueBuilding):
						if iBuildingType == iDefaultBuilding:
							l_UniqueBuildings.append(iUniqueBuilding)
			if len(l_UniqueBuildings) >= 1:
				## 25% chance
				iForeignUBChance = CyGame().getSorenRandNum(4, "Chance")
				if iForeignUBChance == 0:
					chance = CyGame().getSorenRandNum(len(l_UniqueBuildings), "Random for UniqueBuildings")
					pCity.setNumRealBuilding(iBuildingType,0)
					pCity.setNumRealBuilding(l_UniqueBuildings[chance],1)
# Creative Trait End -----------------------------------------------------------------------------------------------
 
Don't know that wonder. This code makes you able to construct the colossus when you are not malinese and you have their ub instead of the forge. The original code only looks for your own building list every civilization have.
 
I get a warning if I compile the DLL:

||=== CvGameCoreDLL, Final Release Win32 ===|
CvCity.cpp|2056|warning C4101: 'ePrereqBuilding' : unreferenced local variable|
||=== Build finished: 0 errors, 1 warnings ===|

PHP:
bool CvCity::canConstruct(BuildingTypes eBuilding, bool bContinue, bool bTestVisible, bool bIgnoreCost) const
{
	BuildingTypes ePrereqBuilding; // warning
	bool bRequiresBonus;
    ...
Outcommenting removes the warning.
 
Then you did not merge all of my changes, look above:

PHP:
// Cybah Start
    // BuildingTypes ePrereqBuilding;
// Cybah End

;)
 
Okay there was still something missing so civic building happiness/health changes did not work. Here is what you need for that:

CvCity.cpp:

PHP:
			//#1.d: BuildingHappinessChanges
// Cybah START
			if (kCivic.isAnyBuildingHappinessChange())
			{
				for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
				{
					int iTempHappy = kCivic.getBuildingHappinessChanges(iI);
					if (iTempHappy != 0)
					{
						int iHappyBuildingClass = ((BuildingClassTypes)iI);
						int iJ; 
						for (iJ = 0; iJ < GC.getNumBuildingInfos(); iJ++) 
						{
							int iTempHappyBuildingClass = GC.getBuildingInfo((BuildingTypes)iJ).getBuildingClassType();	
							if (iTempHappyBuildingClass == iHappyBuildingClass && getNumBuilding((BuildingTypes)iJ) > 0)
							{					
								iHappy += iTempHappy * getNumBuilding((BuildingTypes)iJ);
							}
						}
					}
				}
			}
			// --- Original Code
			//if (kCivic.isAnyBuildingHappinessChange())
			//{
				//CvCivilizationInfo& kCivilization = GC.getCivilizationInfo(getCivilizationType());
				//for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
				//{
					//int iTempHappy = kCivic.getBuildingHappinessChanges(iI);
					//if (iTempHappy != 0)
					//{

						//BuildingTypes eLoopBuilding = (BuildingTypes)kCivilization.getCivilizationBuildings(iI);
						//if (eLoopBuilding != NO_BUILDING)
						//{
							//iHappy += iTempHappy * getNumBuilding(eLoopBuilding);
						//}
					//}
				//}
			//}
// Cybah End
PHP:
	//#2.d: BuildingHealthChanges
// Cybah START
	if (kCivic.isAnyBuildingHealthChange())
	{
		for (int iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			int iTempHealth = kCivic.getBuildingHealthChanges(iI);
			if (iTempHealth > 0)
			{
				int iHealthBuildingClass = ((BuildingClassTypes)iI);
				int iJ; 
				for (iJ = 0; iJ < GC.getNumBuildingInfos(); iJ++) 
				{
					int iTempHealthBuildingClass = GC.getBuildingInfo((BuildingTypes)iJ).getBuildingClassType();	
					if (iTempHealthBuildingClass == iHealthBuildingClass && getNumBuilding((BuildingTypes)iJ) > 0)
					{
						iGood += iTempHealth * getNumBuilding((BuildingTypes)iJ);
					}


				}
			}
			else if (iTempHealth < 0 && (getBuildingOnlyHealthyCount() <= 0 || kOwner.getBuildingOnlyHealthyCount() <= iIgnoreBuildingOnlyHealthyCount))
			{
				int iHealthBuildingClass = ((BuildingClassTypes)iI);
				int iJ; 
				for (iJ = 0; iJ < GC.getNumBuildingInfos(); iJ++) 
				{
					int iTempHealthBuildingClass = GC.getBuildingInfo((BuildingTypes)iJ).getBuildingClassType();	
					if (iTempHealthBuildingClass == iHealthBuildingClass && getNumBuilding((BuildingTypes)iJ) > 0)
					{
						iTempHealth *= getNumBuilding((BuildingTypes)iJ);
						iBad -= iTempHealth;
						iBadBuilding -= iTempHealth;
						if (kCivic.isBuildingOnlyHealthy())
						{
							iGood += iTempHealth;
						}
					}
				}
			}
		}
	}
	// --- Original Code
	//if (kCivic.isAnyBuildingHealthChange())
	//{
		//CvCivilizationInfo& kCivilization = GC.getCivilizationInfo(getCivilizationType());
		//for (int iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		//{
			//int iTempHealth = kCivic.getBuildingHealthChanges(iI);

			//if (iTempHealth > 0)
			//{
				//BuildingTypes eLoopBuilding = (BuildingTypes)kCivilization.getCivilizationBuildings(iI);
				//if (eLoopBuilding != NO_BUILDING)
				//{
					//iGood += iTempHealth * getNumBuilding(eLoopBuilding);
				//}
			//}
			//else if (iTempHealth < 0 && (getBuildingOnlyHealthyCount() <= 0 || kOwner.getBuildingOnlyHealthyCount() <= iIgnoreBuildingOnlyHealthyCount))
			//{
				//BuildingTypes eLoopBuilding = (BuildingTypes)kCivilization.getCivilizationBuildings(iI);
				//if (eLoopBuilding != NO_BUILDING)
				//{
					//iTempHealth *= getNumBuilding(eLoopBuilding);
					//iBad -= iTempHealth;
					//iBadBuilding -= iTempHealth;
					//if (kCivic.isBuildingOnlyHealthy())
					//{
						//iGood += iTempHealth;
					//}
				//}
			//}
		//}
	//}
// Cybah End


CvPlayer.cpp:

Only with Fuyus Changes ("new civic AI" afaik):

PHP:
// Cybah START
		if (kCivic.isAnyBuildingHappinessChange() || kCivic.isAnyBuildingHealthChange())
		{
			for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
			{
				BuildingTypes eOurBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI);
				BuildingClassTypes eOurBuildingClass = (BuildingClassTypes)(GC.getBuildingInfo(eOurBuilding).getBuildingClassType());
				int iJ; 
				for (iJ = 0; iJ < GC.getNumBuildingInfos(); iJ++)
				{
					int iAnyBuildingClass = GC.getBuildingInfo((BuildingTypes)iJ).getBuildingClassType();
					if ((iAnyBuildingClass == eOurBuildingClass) && (NO_BUILDING != eOurBuilding))
					{
						changeExtraBuildingHappiness(((BuildingTypes)iJ), (kCivic.getBuildingHappinessChanges(iI) * iChange), bLimited);
						changeExtraBuildingHealth(((BuildingTypes)iJ), (kCivic.getBuildingHealthChanges(iI) * iChange), bLimited);
					}
				}
			}
		}
		// --- Original Code
		//if (kCivic.isAnyBuildingHappinessChange() || kCivic.isAnyBuildingHealthChange())
		//{
			//for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
			//{
				//BuildingTypes eOurBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI);
				//if (NO_BUILDING != eOurBuilding)
				//{
					//changeExtraBuildingHappiness(eOurBuilding, (kCivic.getBuildingHappinessChanges(iI) * iChange), bLimited);
					//changeExtraBuildingHealth(eOurBuilding, (kCivic.getBuildingHealthChanges(iI) * iChange), bLimited);
				//}
			//}
		//}
// Cybah End


With & without Fuyus Changes:

PHP:
// Cybah START
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			BuildingTypes eOurBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI);
			BuildingClassTypes eOurBuildingClass = (BuildingClassTypes)(GC.getBuildingInfo(eOurBuilding).getBuildingClassType());
			int iJ; 
			for (iJ = 0; iJ < GC.getNumBuildingInfos(); iJ++) 
			{
				int iAnyBuildingClass = GC.getBuildingInfo((BuildingTypes)iJ).getBuildingClassType();
				if ((iAnyBuildingClass == eOurBuildingClass) && (NO_BUILDING != eOurBuilding))
				{
					changeExtraBuildingHappiness(((BuildingTypes)iJ), (GC.getCivicInfo(eCivic).getBuildingHappinessChanges(iI) * iChange));
					changeExtraBuildingHealth(((BuildingTypes)iJ), (GC.getCivicInfo(eCivic).getBuildingHealthChanges(iI) * iChange));
				}
			}
		}

		// --- Original Code
		//for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		//{
			//BuildingTypes eOurBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI);
			//if (NO_BUILDING != eOurBuilding)
			//{
				//changeExtraBuildingHappiness(eOurBuilding, (GC.getCivicInfo(eCivic).getBuildingHappinessChanges(iI) * iChange));
				//changeExtraBuildingHealth(eOurBuilding, (GC.getCivicInfo(eCivic).getBuildingHealthChanges(iI) * iChange));
			//}
		//}
// Cybah End
 
You need both if you are using better bug ai for example, if not, you only need the last part.

To be more clear: Search for "kCivic.getBuildingHappinessChanges(iI) * iChange), bLimited" in your file, if there is no hit, you only have to merge the second part of the CvPlayer.cpp changes. To do that, search for "GC.getCivicInfo(eCivic).getBuildingHappinessChanges(iI) * iChange".
 
Another problem arises:

In my CvCity.cpp (and in Vanilla BTS either) there's no:

'if (kCivic.isAnyBuildingHappinessChange())' (part 1)
and
'if (kCivic.isAnyBuildingHealthChange())' (part 2)

In my CvPlayer.cpp (and in Vanilla BTS either) there's no:

'if (kCivic.isAnyBuildingHappinessChange() || kCivic.isAnyBuildingHealthChange())' (Fuyu)

Only the last code can I merge (With & without Fuyus Changes) as you said

My Mod uses BUG 4.2 and BetterBTSAI 1.01 iirc
 
Hm...ah okay, I guess you can leave those stated lines then. But you have to merge the rest. Should work with 1 tab less. Just compare my code with the original code and you will see what I've changed. :)
 
Top Bottom