Dummy Buildings for Traits

Trickster7135

Prince
Joined
Aug 30, 2010
Messages
321
Location
954, Florida
My python skills are weak, and I need help on what to write and where to put it for these effects:

1. How do I code into python to add certain dummy buildings, depending on traits, using onCityBuilt and onCityAquiredandKept?

2. How do I code into python to add a certain dummy building, depending on traits, to only the capital, and to have the single dummy building move with the capital if it is relocated? Alternatively, if that is too much work, would it be easy to simply have different trait based capitals with the dummy building effects on the trait based capitals?
 
I guess you know how to merge python code, right?

If yes, for 1):
PHP:
	def onCityBuilt(self, argsList):
		'City Built'
		city = argsList[0]
###new code start
		pPlayer = gc.getPlayer(city.getOwner())
		if pPlayer.hasTrait(gc.getInfoTypeForString("TRAIT_SOMETRAIT")):
                        city.setNumRealBuilding(gc.getInfoTypeForString("BUILDING_SOMEBUILDING"),1)                                                        
                                        
###new code end
		if (city.getOwner() == gc.getGame().getActivePlayer()):
			self.__eventEditCityNameBegin(city, False)	
		CvUtil.pyPrint('City Built Event: %s' %(city.getName()))


2) are there any effects, which can only be applied globally? (background: Is this really needed?)
 
I guess you know how to merge python code, right?

If yes, for 1):
PHP:
	def onCityBuilt(self, argsList):
		'City Built'
		city = argsList[0]
###new code start
		pPlayer = gc.getPlayer(city.getOwner())
		if pPlayer.hasTrait(gc.getInfoTypeForString("TRAIT_SOMETRAIT")):
                        city.setNumRealBuilding(gc.getInfoTypeForString("BUILDING_SOMEBUILDING"),1)                                                        
                                        
###new code end
		if (city.getOwner() == gc.getGame().getActivePlayer()):
			self.__eventEditCityNameBegin(city, False)	
		CvUtil.pyPrint('City Built Event: %s' %(city.getName()))


2) are there any effects, which can only be applied globally? (background: Is this really needed?)

Thank you for the code, and as for #2, yes. I want my Humanitarian trait to give the Statue of Zeus effect, just scaled down: +25% war weariness for enemies. Also, I want my Industrious trait to have: workers build improvements +25% faster.

EDIT: Which file do I put the code into? I thought it was CvEventManager but that just removed my interface and lagged the hell out of my game. Also, I don't see onCityAquireandKept in the code there, I assumed it was necessary for when you take over a new city for the building to be built?
 
Thank you for the code, and as for #2, yes. I want my Humanitarian trait to give the Statue of Zeus effect, just scaled down: +25% war weariness for enemies. Also, I want my Industrious trait to have: workers build improvements +25% faster.

Easiest way would be to give the civ a unique palace, but that only works if the civ has only 1 leader.

EDIT: Which file do I put the code into? I thought it was CvEventManager

Yes, that's right, you put everything which is labeled "new code" into the same place in the CvEventManager.

but that just removed my interface and lagged the hell out of my game.

Then you did something wrong.
You have to know: The white spaces at the beginning of the lines are important, paste them also in the file.

And please activate python exceptions, that can be done in the .ini file of civilization.

Also, I don't see onCityAquireandKept in the code there, I assumed it was necessary for when you take over a new city for the building to be built?

That will be nearly the same.
 
I guess you know how to merge python code, right?

If yes, for 1):
PHP:
	def onCityBuilt(self, argsList):
		'City Built'
		city = argsList[0]
###new code start
		pPlayer = gc.getPlayer(city.getOwner())
		if pPlayer.hasTrait(gc.getInfoTypeForString("TRAIT_SOMETRAIT")):
                        city.setNumRealBuilding(gc.getInfoTypeForString("BUILDING_SOMEBUILDING"),1)                                                        
                                        
###new code end
		if (city.getOwner() == gc.getGame().getActivePlayer()):
			self.__eventEditCityNameBegin(city, False)	
		CvUtil.pyPrint('City Built Event: %s' %(city.getName()))


2) are there any effects, which can only be applied globally? (background: Is this really needed?)

for 1) you also need code to remove the building in case the city is captured by another player.
 
If a city is gifted (or conceded in war), that check is not done though, and buildings with 100% destruction probabilities remain; so you would need to account for that as well somehow.
 
I get an error when I have this code in:
def onCityAcquiredAndKept(self, argsList):
'City Acquired and Kept'
iOwner,pCity = argsList
CvUtil.pyPrint('City Acquired and Kept Event: %s' %(pCity.getName()))
## Charismatic Trait Start ##
player = PyPlayer(city.getOwner())
pPlayer = gc.getPlayer(city.getOwner())
iTrait = CvUtil.findInfoTypeNum(gc.getTraitInfo,gc.getNumTraitInfos(),'TRAIT_CHARISMATIC')
if (pPlayer.hasTrait(iTrait)):
city.setNumRealBuilding(gc.getInfoTypeForString("BUILDING_CHARISMATIC"),1)
## Charismatic Trait End ##

However when I use the same code for charismatic in onCityBuilt it works just fine. Help?
 
Ups, yes, there are some differences in the variables.

If you look at onCityBuild, you will see in the next line city = argsList[0].
The "name" of the city is here "city".
If you look at onCityAcquiredAndKept, you will see in the next line iOwner,pCity = argsList.
The "name" of the city is here "pCity". That means, you have to rename "city" to "pCity" here.


And you can delete this line:
PHP:
player = PyPlayer(city.getOwner())

it's redundant.
 
The big mystery here is that argsList isn't a integer value, a class instance or even a "list". Its actually a "tuple" (immutable ordered data structure) containing any number of "values". Each value is indexed in order from zero and up (exactly like a list). In this case the first value is a string (the name) and it is accessed by indexing the tuple with the index number of zero:
Code:
argsList[0]
The next item in the tuple is indexed as 1 and so on.
 
Try this. It's works, but you may want to remove some parts (such as the other traits) and change some references, but the code works.

PHP:
pPlayer = gc.getPlayer(iNewOwner)
		iX = pCity.getX()
		iY = pCity.getY()

		iTraitPrg = gc.getInfoTypeForString('TRAIT_PROGRESSIVE')
		iTraitSpi = gc.getInfoTypeForString('TRAIT_SPIRITUAL')
		iTraitTac = gc.getInfoTypeForString('TRAIT_TACTICAL')

		iBuildingPrg = gc.getInfoTypeForString('BUILDING_TRAIT_PROGRESSIVE')
		iBuildingSpi = gc.getInfoTypeForString('BUILDING_TRAIT_SPIRITUAL')
		iBuildingTac = gc.getInfoTypeForString('BUILDING_TRAIT_TACTICAL')

		if (pPlayer.hasTrait(iTraitPrg)):
			pCity.setNumRealBuilding(iBuildingPrg, 1)
		else:
			if pCity.getNumActiveBuilding(iBuildingPrg) > 0:
				pCity.setNumRealBuilding(iBuildingPrg, 0)

		if (pPlayer.hasTrait(iTraitSpi)):
			pCity.setNumRealBuilding(iBuildingSpi, 1)
		else:
			if pCity.getNumActiveBuilding(iBuildingSpi) > 0:
				pCity.setNumRealBuilding(iBuildingSpi, 0)

		if (pPlayer.hasTrait(iTraitTac)):
			pCity.setNumRealBuilding(iBuildingTac, 1)
		else:
			if pCity.getNumActiveBuilding(iBuildingTac) > 0:
				pCity.setNumRealBuilding(iBuildingTac, 0)
 
Ups, yes, there are some differences in the variables.

If you look at onCityBuild, you will see in the next line city = argsList[0].
The "name" of the city is here "city".
If you look at onCityAcquiredAndKept, you will see in the next line iOwner,pCity = argsList.
The "name" of the city is here "pCity". That means, you have to rename "city" to "pCity" here.


And you can delete this line:
PHP:
player = PyPlayer(city.getOwner())

it's redundant.

Thank you, this worked like a charm!
 
This places a dummy building in every city you found. I'm wondering if you can just have a single dummy building just in your capital city?
Of course, but if you look at the sample code in the second post, the code is part of the definition (starting with the def line) of onCityBuilt(). This in turn is a reference to a "game event". So any time a city is being built in the game there is a Python event triggered. What the sample code does, is it intersects the game at this event and adds the dummy building.

In order to add a building (any building) to the capital, you need to keep track of which city has the Palace National Wonder. And this can be trickier than you'd think. Sure, there is a event called beginGameTurn, so you could basically check what city is the capital every turn and add the building. It would work but is really not a very good implementation.

Instead, you'd wanna use the cityBuilt event to put the dummy building in the first city - the capital. But only once, so this is getting complicated already. Then you need to tap into the buildingBuilt event to check whether or not the Palace has been moved. And if it has, then you also add the dummy building. But you'd still have to figure out what city was the former capital and delete the previous dummy building.

Perhaps you should instead make the Palace itself a dummy building? Because then you don't need to keep track of where it is located all of the time.
 
Top Bottom