How do I reincarnate a unit a specific number of times?

cfkane

Emperor
Joined
Feb 7, 2006
Messages
1,196
I'm trying to write a program for a unit: Sindbad the Sailor, who works both as a combat ship and a Great Merchant. The goal is to have the Sindbad unit, when either killed or having completed a merchant mission, respawn in one of it's owner's cities a total of six times (that way you can have Seven Voyages of Sindbad).

I'm trying to make a similar program for a James Bond great spy unit where he comes back five times for a total of six missions (Connery, Lazenby, Moore, Dalton, Brosnan, and Craig)

How might I go about doing this?
 
If you add a variable to the UnitInfos for respawning it should be fairly easy to set it up. You could even set it so that your James Bond uses the Unique Names function that Great People do so that he has the Actor Names for each incarnation.


I'd imagine that you set the flag, and then establish a routine in the onTurn function which checks for NumUnitsCreated > 0 of any class with the new reincarnation field > 0. If it finds such a case, then it checks if the unit is still alive, and if it is not, then it creates one in your capital, and decreases the number of reincarnations allowed for the unit by 1.

This would of course only work if you killed the last of that unit which you possessed, but as long as you set a Player or Team Limit of 1 for the unitclass that wouldn't be a huge issue. To avoid that you could set up the function to be called in each of the various possible locations for a unit to be killed instead. I am not certain that it uses the Kill function for all situations (Trade Missions mostly), but I am relatively certain it does. If that is the case then there is only the one location required and that is CONSIDERABLY better than cycling through all units during OnTurn. Plus it lets you play with the new Bond or Sinbad on the same turn you lost the previous one.
 
Alexander isn't great to begin with, you have to up level him through combat. If he dies he gets reincarnated. Here is some of the code:

Code:
		if self.iAlexanderRebirthCounter > -1:
			if self.iAlexanderRebirthCounter == 0:
				self.doPopup("TXT_KEY_ATG_ALEXANDER_HEALTHY")
				self.doCreateAlexander()
			self.iAlexanderRebirthCounter = self.iAlexanderRebirthCounter - 1

Code:
	def doCreateAlexander(self):
		gc.getPlayer(0).initUnit(CvUtil.findInfoTypeNum(gc.getUnitInfo, gc.getNumUnitInfos(),"UNIT_GREAT_GENERAL"), gc.getPlayer(0).getCapitalCity().getX(), gc.getPlayer(0).getCapitalCity().getY(), UnitAITypes.NO_UNITAI)
		self.doNameAlexander()

Code:
	def getAlexanderVariables(self):
		
		pPlayer = gc.getPlayer(0)
		
		# Load Script Data - Score
		szScriptData = pickle.loads(pPlayer.getScriptData())
		
		self.iAlexanderRebirthCounter = szScriptData[0]
		self.bAlexandriaBuilt = szScriptData[1]
		self.bAlexanderJoined = szScriptData[2]
 
Those are only select parts.

It doesn't sound like you know any python (yet!), so starting out then it's probably best to check out some of the python mod comps. The trouble with looking at mod code is that they usually have a lot of mod comps all mashed together, but to start with it's better to see the individual pieces. After you look through a few of these you should get an idea of how to assemble things for the game. Another source of examples is looking through the python that comes with the game. A key one is: ...\Assets\Python\CvEventManager.py Basically there are events in the game, and using python the events can be hooked into in order to accomplish the desired task.

As for python proper, try this: http://www.greenteapress.com/thinkpython/thinkpython.pdf
It's a free textbook.
 
I've thrown together a code for Bond. How does it look?

Code:
		if unit.getUnitType() == gc.getInfoTypeForString('UNIT_JAMES_BOND'):
			i = 5
			if i > 0
				pPlayer = gc.getPlayer(iPlayer)
				newUnit = pPlayer.initUnit(gc.getInfoTypeForString('UNIT_JAMES_BOND'), gc.getPlayer(0).getCapitalCity().getX(), gc.getPlayer(0).getCapitalCity().getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
				i = i - 1
 
The counter variable has to be saved (pickly.dumps) by pickling it. That is the only way to load (pickle.loads) it from a savegame. Try taking a look at Desert War (from civIV, or the recent port to BtS) for Operation Barbarossa as an example of pickle.

Is this in onUnitKilled? If so, then it's pretty close.

in psuedo code:
Code:
if (unit killed =  james bond) then
    load remainingLives
    remainingLives--
    save remainingLives
    if ( remainingLives > 0 ) then
        init unit
 
Note that the above code only works when the human player is the first player (0) in the game. If you play a scenario with set players, it may not be the human. Use gc.getGame().getActivePlayer() to the the player ID or gc.getActivePlayer() to get the CyPlayer.
 
I actually put it under onUnitLost. I've changed my plan so that he'll respawn once he's completed a Great Spy mission, or been caught by enemies (if the game makes this distinction between being killed and being lost). I'll check out Desert war ASAP.

And for the gc.getActivePlayer() line, does that go after pPlayer, in the code to select the spawning city, or both?
 
And for the gc.getActivePlayer() line, does that go after pPlayer, in the code to select the spawning city, or both?

I didn't see the pPlayer line. This line is correct, but then you need to change both gc.getPlayer(0) calls in the next line to pPlayer so the unit is created in the old unit's capital. This is what you want, right?

Also, it helps readability to assign values to local variables that you'll be using multiple times in the function.

BTW, since you assign i a value of 5, the if test will always succeed. I assume this is the part where you will be substituting a stored value using pickle? Since you're just storing an int, the following will work fine:

Code:
eBondType = gc.getInfoTypeForString('UNIT_JAMES_BOND')
if unit.getUnitType() == eBondType:
	sLives = unit.getScriptData()
	if sLives:
		iLives = int(sLives)
	else:
		iLives = 5  # starts with 5 lives
	if iLives > 0:
		pPlayer = gc.getPlayer(iPlayer)
		pCapitalCity = pPlayer.getCapitalCity()
		newUnit = pPlayer.initUnit(eBondType, 
				pCapitalCity.getX(), pCapitalCity.getY(),
				UnitAITypes.NO_UNITAI, 
				DirectionTypes.DIRECTION_SOUTH)
		iLives -= 1
		newUnit.setScriptData(str(iLives))
 
Top Bottom