Promotion + Building Questions

smeagolheart

Monarch
Joined
Sep 4, 2007
Messages
924
Location
Phoenix, AZ
I've been checking around and haven't seen anything quite like this, though it seems pretty simple idea - a wonder that gives a "untrainable promotion" to all units.

So the basic idea is "As long as you got the wonder, you got the promotion on your whole army."

So obviously this is different than a building like Red Cross.

All existing and any units the wonder builder makes from any city get this promotion as well. If someone captures the wonder, then all that guys units get the promotion and are lost from the first guy.

Once the wonder goes obsolete, all the promotions go away from everybody.

So my questions are does that cover every scenario for the request "You got the wonder, you got the promotion on your whole army." Someone help me get started here for this?
 
Giving a promotion to all new units is easy, this:

All existing and any units the wonder builder makes from any city get this promotion as well. If someone captures the wonder, then all that guys units get the promotion and are lost from the first guy.

Once the wonder goes obsolete, all the promotions go away from everybody.

is not easy (maybe somebody else can help on this).

The first part (giving the promo to all new units):

PHP:
	def onUnitBuilt(self, argsList):
		'Unit Completed'
		city = argsList[0]
		unit = argsList[1]
		player = PyPlayer(city.getOwner())

		pCity = argsList[0]
		pUnit = argsList[1]
		pPlayer = gc.getPlayer(pUnit.getOwner())

## untrainable promotion start ##

		b_BUILDING_X = gc.getInfoTypeForString("BUILDING_X")
		obsoleteTech = gc.getBuildingInfo(b_BUILDING_X).getObsoleteTech()
		if not gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) or obsoleteTech == -1:
			if pPlayer.getBuildingClassCount(gc.getInfoTypeForString("BUILDINGCLASS_X")) > 0:
				iPromo = gc.getInfoTypeForString("PROMOTION_X")
				unit.setHasPromotion(iPromo, true)

## untrainable promotion end ##

Replace X with your building/buildingclass/promotion.
 
Edit: Uh, Cybah has been faster.
But i guess he does not mean give one unit the promotion (that's already a XML tag), he means to give every unit of the owner the promotion.

How much assistance do you need?

There are "only" 5 parts to modify:
CvEventManager, onBuildingBuilt, to give every unit of the owner this promotion
CvEventManager, onCityAcquiredAndKept, to change the promotions to the new owner and remove them from the old owner
CvEventManager, onCityRazed, to remove the promotions after razing
CvEventManager, onTechAcquired, to check, if the wonder has gone obsolete.
CvEventManager, onUnitBuild, to give the promotion to new units

The basic functions behind then will all be the same: Iterating units, to give them a promotion, or to take it.

The only problem i see: What, if the wonder is obsolete for the old owner, but the conquerer doesn't have the technology?...:think: hhmm...no, that can be catched, should not be a real problem.


Oh, and good idea, haven't thought of it yet :goodjob:.
 
??? my code gives the promotion to all new builded units in all cities... there is no city condition.
 
Edit: Uh, Cybah has been faster.
But i guess he does not mean give one unit the promotion (that's already a XML tag), he means to give every unit of the owner the promotion.

How much assistance do you need?

There are "only" 5 parts to modify:
CvEventManager, onBuildingBuilt, to give every unit of the owner this promotion
CvEventManager, onCityAcquiredAndKept, to change the promotions to the new owner and remove them from the old owner
CvEventManager, onCityRazed, to remove the promotions after razing
CvEventManager, onTechAcquired, to check, if the wonder has gone obsolete.
CvEventManager, onUnitBuild, to give the promotion to new units

The basic functions behind then will all be the same: Iterating units, to give them a promotion, or to take it.

The only problem i see: What, if the wonder is obsolete for the old owner, but the conquerer doesn't have the technology?...:think: hhmm...no, that can be catched, should not be a real problem.


Oh, and good idea, haven't thought of it yet :goodjob:.

Yeah I think you covered it all. I can make the code to iterate the units and give or take the promotion, I just wasn't 100% on all the 5 areas in this case.

Let me think... What, if the wonder is obsolete for the old owner, but the conquerer doesn't have the technology?...: Well I was thinking to make the check obsolete the promotion (take it away) on reaching the tech from the tech reacher's army.

That would work I think?
 
Ran into a problem, probably easy but I can't figure it out.

Here's the code I have to iterate the units.

Code:
		if iBuildingType == gc.getInfoTypeForString( 'BUILDING_JAGUAR' ):
		
			pPlayer = gc.getPlayer(pCity.plot().getOwner())
			for iUnit in range(pPlayer.getNumUnits(), -1, -1):
				pUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_GIFT'), True)

Problem seems to me to be pUnit is not an argument for onBuildingBuilt

EDIT:

Found some code from EmperorFool, this seemed to work for this case:

Code:
## Jaguar Temple Start ##
		if iBuildingType == gc.getInfoTypeForString( 'BUILDING_JAGUAR' ):
		
			pPlayer = gc.getPlayer(pCity.plot().getOwner())
			lPlots = []
			(loopUnit, iter) = pPlayer.firstUnit(False)
			# Add promotion, keep track of x,y positions
			while (loopUnit):
				lPlots.append((loopUnit.getX(), loopUnit.getY()))
				loopUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_GIFT'), True)
				(loopUnit, iter) = pPlayer.nextUnit(iter, False)
 
Man! I'm dying here with python.

I'm trying to use Notepad++, I'm running into lots of problems with what I think are indentation errors. Should tabs be set up as tabs or spaces? I am trying to check my variables via CyInterface.addImmediateMessage but that ain't working even and I'm struggling to see if it's because of the tab thing or something else.

Should this work:
Code:
CyInterface.addImmediateMessage("variable 1: %s" % gc.getInfoTypeForString(thisbuilding.getType()), "")

or

CyInterface[COLOR="Red"]()[/COLOR].addImmediateMessage("variable 1: %s" % gc.getInfoTypeForString(thisbuilding.getType()), "")
 
The last one. Tabs should be tabs. It's easier to modify.

I script my immediate messages like this:

PHP:
								szTitle = CyTranslator().getText( "TXT_KEY_BLABLA", (pPlayer.getName(),newUnit.getName(),capital.getName() ) )
								CyInterface().addImmediateMessage( szTitle , None)

%s1 would be playername, %s2 unitname and %s3 city name for example.
 
So I'm on the 2nd of the 5 areas to do.

Here's what I've got, taint working. As you can tell it's nested in another modcomp but it seems fine where it is as the mod comp checks to see if it's a wonder which works cause then I check if it's my building.

Code:
	def onCityAcquiredAndKept(self, argsList):
		'City Acquired and Kept'
		iOwner,pCity = argsList
#### messages - wonder captured start ####		
		NumWonders = pCity.getNumWorldWonders
		if NumWonders ()>0:
			Counter = 0
			for i in range(gc.getNumBuildingInfos ()):
					thisbuilding = gc.getBuildingInfo (i)
					if pCity.getNumBuilding(i)>0:
							iBuildingClass = thisbuilding.getBuildingClassType ()
							thisbuildingclass = gc.getBuildingClassInfo (iBuildingClass)
							if thisbuildingclass.getMaxGlobalInstances ()==1:
									ConquerPlayer = gc.getPlayer(pCity.getOwner())
									iConquerTeam = gc.getPlayer(pCity.getOwner()).getTeam()
									ConquerName = ConquerPlayer.getName ()
									WonderName = thisbuilding.getDescription ()
									iX = pCity.getX()
									iY = pCity.getY()
## Jaguar Start
									pPlayer = gc.getPlayer(pCity.plot().getOwner())
									i_Jaguar = gc.getInfoTypeForString("BUILDING_JAGUAR")
									obsoleteTech = gc.getBuildingInfo(i_Jaguar).getObsoleteTech()
									iBuildingType = gc.getInfoTypeForString(thisbuilding.getType())
									
									# CyInterface().addImmediateMessage("Debug = %s "%obsoleteTech,"")										
									if iBuildingType == i_Jaguar:
											if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
												CyInterface().addImmediateMessage("Working..!","")											
												lPlots = []
												(loopUnit, iter) = pPlayer.firstUnit(False)
												# Add promotion, keep track of x,y positions
												while (loopUnit):
													lPlots.append((loopUnit.getX(), loopUnit.getY()))
													loopUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_GIFT'), True)
													(loopUnit, iter) = pPlayer.nextUnit(iter, False)		
## Jaguar End
									for iPlayer in range (gc.getMAX_CIV_PLAYERS ()):
											ThisPlayer = gc.getPlayer(iPlayer)
											iThisTeam = ThisPlayer.getTeam()
											ThisTeam = gc.getTeam(iThisTeam)
											if ThisTeam.isHasMet(iConquerTeam):
													if iPlayer == pCity.getOwner():
															CyInterface().addMessage(iPlayer,False,15,CyTranslator().getText("TXT_KEY_YOU_CAPTURED_WONDER",(ConquerName,WonderName)),'',0,'Art/Interface/Buttons/General/happy_person.dds',ColorTypes(gc.getInfoTypeForString("COLOR_GREEN")), iX, iY, True,True)
													else:
															CyInterface().addMessage(iPlayer,False,15,CyTranslator().getText("TXT_KEY_CAPTURED_WONDER",(ConquerName,WonderName)),'',0,'Art/Interface/Buttons/General/warning_popup.dds',ColorTypes(gc.getInfoTypeForString("COLOR_RED")), iX, iY, True,True)
#### messages - wonder captured end ####
		CvUtil.pyPrint('City Acquired and Kept Event: %s' %(pCity.getName()))

Here's my error code and I don't see why. Is it indentation or something about pPlayer it doesn't like at this point in it's merry execution of code?

Code:
if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):

It's not getting past this comparison.
 
I guess i know this other modcomp from somewhere :D.


The problem is not the check you mention, it's this line:
PHP:
iBuildingType = gc.getInfoTypeForString(thisbuilding.getType())

thisbuilding.getType() is already the integer you want to compare here
PHP:
if iBuildingType == i_Jaguar:

so after gc.getInfoTypeForString the check is invalid here, because you compare two not more identical values.

But you could also compare it just to i, the parameter of the first loop (shame on me for the name), because it's already iterating the buildings, so no need to get the index again.

For performance: The obsolete check should be moved after the check for the building type, and i_Jaguar = gc.getInfoTypeForString("BUILDING_JAGUAR") maybe before the whole loops.
 
When I debug the output to the screen, it's saying the numbers are the same, in this case 174. I used your i variable as well as the number for the wonder.

So it is getting past that line
Code:
if iBuildingType == i_Jaguar:
I can get a message after it to show up but it is not proceeding past the next bit.

It is not getting to the immediate message below:
Code:
if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
	CyInterface().addImmediateMessage("Working..!","")

The 'working' message never shows

EDIT:

Because I'm silly and saved the game when I had the obsolete tech (Gunpowder). :D
 
BTW, check for obsoleteTech == -1 before the other check (reverse them). Also, if you have

Code:
if [I]<blah blah>[/I] == false:

you can rewrite that as

Code:
if not [I]<blah blah>[/I]:

When trying to diagnose issues, I recommend setting up Python error logging (see the Troubleshooting page in my sig) and post PythonErr.log. That way we don't have to guess about the error.
 
BTW, check for obsoleteTech == -1 before the other check (reverse them). Also, if you have

Code:
if [I]<blah blah>[/I] == false:

you can rewrite that as

Code:
if not [I]<blah blah>[/I]:

When trying to diagnose issues, I recommend setting up Python error logging (see the Troubleshooting page in my sig) and post PythonErr.log. That way we don't have to guess about the error.

I've got python error logging enabled, I'm just getting familiar with what it's telling me. I think some of my inital problems were indentation from Notepad++ possibly because the code was fine but it gave me "SyntaxError: invalid syntax" that didn't seem to be pointing to anything even after copying a piece of code verbatim from somewhere else.

Thanks for the offer to help, I'm sure this wouldn't be that difficult for you all but it's not so easy for me so far! I'll post more code as we go along..
 
Here's all what I've got so far, all seems to be working and covers everything as far as I know. Yes surely some optimization is possible! I'm doing this to change the Jaguar Temple Python Wonder by Tsentom1 to give it's bonus (% chance to heal after combat victory) in promotion form - mainly so it shows up on the units themselves because I've got other promotions that give chances for healing after combat victory. So at a glance you can tell your total % to heal. I'm using TLO's Promotion as well for the basis of the promotion.

Code:
	def onBuildingBuilt(self, argsList):
		'Building Completed'
		pCity, iBuildingType = argsList
		game = gc.getGame()

## Jaguar Temple Start ##
		if iBuildingType == gc.getInfoTypeForString( 'BUILDING_JAGUAR' ):

			pPlayer = gc.getPlayer(pCity.plot().getOwner())
			iX = pCity.getX()
			iY = pCity.getY()
			CyInterface().addMessage(pPlayer.getID(),False,15,CyTranslator().getText("TXT_KEY_JAGUAR_BUILT_TEXT",()),'',0,'Art/Interface/Buttons/Promotions/gift.dds',ColorTypes(44), iX, iY, True,True)  

			lPlots = []
			(loopUnit, iter) = pPlayer.firstUnit(False)
			# Add promotion, keep track of x,y positions
			while (loopUnit):
				lPlots.append((loopUnit.getX(), loopUnit.getY()))
				loopUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_GIFT'), True)
				(loopUnit, iter) = pPlayer.nextUnit(iter, False)		

## Jaguar Temple End ##



	def onCityAcquiredAndKept(self, argsList):
		'City Acquired and Kept'
		iOwner,pCity = argsList
#### messages - wonder captured start ####		
		NumWonders = pCity.getNumWorldWonders		
		if NumWonders ()>0:
			Counter = 0
			for i in range(gc.getNumBuildingInfos ()):
					thisbuilding = gc.getBuildingInfo (i)
					if pCity.getNumBuilding(i)>0:
							iBuildingClass = thisbuilding.getBuildingClassType ()
							thisbuildingclass = gc.getBuildingClassInfo (iBuildingClass)
							if thisbuildingclass.getMaxGlobalInstances ()==1:
									ConquerPlayer = gc.getPlayer(pCity.getOwner())
									iConquerTeam = gc.getPlayer(pCity.getOwner()).getTeam()
									ConquerName = ConquerPlayer.getName ()
									WonderName = thisbuilding.getDescription ()
									iX = pCity.getX()
									iY = pCity.getY()
## Jaguar Start
									pPlayer = gc.getPlayer(pCity.plot().getOwner())
									i_Jaguar = gc.getInfoTypeForString("BUILDING_JAGUAR")
									obsoleteTech = gc.getBuildingInfo(i_Jaguar).getObsoleteTech()

									if i == i_Jaguar:											
											if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
												lPlots = []
												(loopUnit, iter) = pPlayer.firstUnit(False)
												# Add promotion, keep track of x,y positions
												while (loopUnit):
													lPlots.append((loopUnit.getX(), loopUnit.getY()))
													loopUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_GIFT'), True)
													(loopUnit, iter) = pPlayer.nextUnit(iter, False)
											ppPlayer = gc.getPlayer(pCity.getPreviousOwner())
											if (ppPlayer.isAlive()):
												CyInterface().addMessage(gc.getTeam(ppPlayer.getTeam()).getID(),False,15,CyTranslator().getText("TXT_KEY_JAGUAR_LOST_TEXT",()),'',0,'Art/Interface/Buttons/Promotions/gift.dds',ColorTypes(44), iX, iY, True,True)
												lPlots = []												
												(loopUnit, iter) = ppPlayer.firstUnit(False)
												# Remove promotion from loser, keep track of x,y positions
												while (loopUnit):
													lPlots.append((loopUnit.getX(), loopUnit.getY()))
													loopUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_GIFT'), False)
													(loopUnit, iter) = ppPlayer.nextUnit(iter, False)									

## Jaguar End
									for iPlayer in range (gc.getMAX_CIV_PLAYERS ()):
											ThisPlayer = gc.getPlayer(iPlayer)
											iThisTeam = ThisPlayer.getTeam()
											ThisTeam = gc.getTeam(iThisTeam)
											if ThisTeam.isHasMet(iConquerTeam):
													if iPlayer == pCity.getOwner():
															CyInterface().addMessage(iPlayer,False,15,CyTranslator().getText("TXT_KEY_YOU_CAPTURED_WONDER",(ConquerName,WonderName)),'',0,'Art/Interface/Buttons/General/happy_person.dds',ColorTypes(gc.getInfoTypeForString("COLOR_GREEN")), iX, iY, True,True)
## Jaguar Start
															if i == i_Jaguar:
																	CyInterface().addMessage(gc.getTeam(pPlayer.getTeam()).getID(),False,15,CyTranslator().getText("TXT_KEY_JAGUAR_BUILT_TEXT",()),'',0,'Art/Interface/Buttons/Promotions/gift.dds',ColorTypes(44), iX, iY, True,True)  
## Jaguar End																	
													else:
															CyInterface().addMessage(iPlayer,False,15,CyTranslator().getText("TXT_KEY_CAPTURED_WONDER",(ConquerName,WonderName)),'',0,'Art/Interface/Buttons/General/warning_popup.dds',ColorTypes(gc.getInfoTypeForString("COLOR_RED")), iX, iY, True,True)
#### messages - wonder captured end ####
		CvUtil.pyPrint('City Acquired and Kept Event: %s' %(pCity.getName()))

EDIT: Picture worth 1000 lines of code
note how explorer has had promotion applied already, and while you can't see it from the pic, the archer had the promotion but it's been removed.
ss.jpg
 
I will, I'm working on it. I've got the 5 areas done, but they don't work 100% yet :( I extracted it from my mod and am trying to get it to work as a standalone cvEventmanager extension that can be imported, yeah I don't know the fancy terms for that :D

Anyway, once I've got it out and the game doesn't crash when I import it, I'll post what I have so far.
 
Allright, here's the python status on the different areas.

-----------------
eventManager.addEventHandler("techAcquired", self.onTechAcquired)
Not working, I thought it was working but it ain't I'll post code after this

eventManager.addEventHandler("cityRazed", self.onCityRazed)
100% working. Tested and removed promo from AI, haven't got the AI to raze it on me so that's not tested but assumption is it will work.

eventManager.addEventHandler("cityAcquiredAndKept", self.onCityAcquiredAndKept)
100% working. The winner will get all units the promotion and the loser will lose all the promotion. Tested with AI taking it from Human and Human taking the wonder from AI.

eventManager.addEventHandler("unitCreated", self.onUnitCreated)
I went with on unitcreated because I want to cover getting units from other means than being built as well as being built such as from goody huts. I'm after all units.
I tried unitbuilt as well results from the code are same either way, it works for a couple turns. It's weird, I run AIautoplay for 20 turns and then most the army doesn't have it but if I run like 5 turns it's fine. I'll post code below.

eventManager.addEventHandler("buildingBuilt", self.onBuildingBuilt)
100% working for AI and player.
-----------------

Code for Problem areas

Code:
	def onTechAcquired(self, argsList):
		'Tech Acquired'
		iTechType, iTeam, iPlayer, bAnnounce = argsList
		# Note that iPlayer may be NULL (-1) and not a refer to a player object
## Jaguar Start ##	

		pPlayer = gc.getPlayer(iPlayer)
		i_Jaguar = gc.getInfoTypeForString("BUILDING_JAGUAR")
		obsoleteTech = gc.getBuildingInfo(i_Jaguar).getObsoleteTech()			
			
		topkapi = false
		for iCity in range(pPlayer.getNumCities()):
			if topkapi == false:
				ppCity = pPlayer.getCity(iCity)
				if ppCity.getNumActiveBuilding(i_Jaguar) == true:
					topkapi = true
		if ( topkapi == true ):
			lPlots = []
			(loopUnit, iter) = pPlayer.firstUnit(False)
			# Remove promotion, keep track of x,y positions
			while (loopUnit):
				lPlots.append((loopUnit.getX(), loopUnit.getY()))
				loopUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_GIFT'), False)
				(loopUnit, iter) = pPlayer.nextUnit(iter, False)		
		
## Jaguar End ##

	def onUnitCreated(self, argsList):
		'Unit Completed'
		unit = argsList[0]
		player = PyPlayer(unit.getOwner())

## Jaguar Start ##

		i_Jaguar = gc.getInfoTypeForString("BUILDING_JAGUAR")
		obsoleteTech = gc.getBuildingInfo(i_Jaguar).getObsoleteTech()
		pPlayer = gc.getPlayer(unit.getOwner())

		if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
			topkapi = false
			for iCity in range(pPlayer.getNumCities()):
				if topkapi == false:
					ppCity = pPlayer.getCity(iCity)
					if ppCity.getNumActiveBuilding(i_Jaguar) == true:
						unit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_GIFT'), True)
						#CyInterface().addImmediateMessage("Found me one Coach = %s "%topkapi,"")			
## Jaguar End ##

If you guys could point me in the direction of what's up the sooner I can get the whole stuff out. It's getting pretty close to finished methinks.
 
Back
Top Bottom