Python event: unit creation after losing a battle?

Maniac

Apolyton Sage
Joined
Nov 27, 2004
Messages
5,603
Location
Gent, Belgium
Anyone an idea how I should create this event (for the Fall from Heaven mod)?

1) If you're running the civic Sacrifice the Weak
2) If a unit of yours
a) with the Diseased or Plagued promotion
b) that is not a Diseased Corpse unit
loses in combat
3) then there is a 50% chance (should probably be tested for balance) that a Diseased Corpse is created on the battlesite, or if the battlesite is now occupied by an enemy, on one of the adjacent tiles -> don't know if this is possible though. If not, perhaps in the nearest city or in the capital.

CIVICOPTION_COMPASSION
CIVIC_SACRIFICE_THE_WEAK
PROMOTION_DISEASED
PROMOTION_PLAGUED
UNIT_DISEASED_CORPSE
 
I think it would have been better if you were to post this in the ffh development forum... Not that the ffh people come here but it would have been better answered if you asked the profesionals/creators
 
I've already mentioned the idea there. Creators put it on the list for things to consider for the future. I'd like to try this out now though ;) (as, in case you know something about FfH, using the Diseased Corpse currently is cutting in your own flesh due to the Veil's inability to cure disease). Except for the specifics of the civic, unit and promotions, there's nothing that would prevent people unfamiliar with FfH to help with this, so I thought I'd post it here.
 
I'd check out mrkingkings post in the sample python thread that does about the same thing:

http://forums.civfanatics.com/showpost.php?p=4502328&postcount=56

That should give you most of what you need. There are examples for checking a players civic settings in CvGameInterface.py and checking the unitclass and if the unit has certain promotions in CvEventManager.py.
 
You would have to probably edit either the onCombatResult function or the onUnitKilled function, both in the CvEventManager.py file.

You can use the getCivics function for a player object to determine what civics they're running. You can use the isHasPromotion() function for units to determing if they have a specific promotion.

Use gc.getSorenRandNum to get a random number. Probably get a number between 0 and 99, like this:

iChance = gc.getSorenRandNum(100, "Percent to raise diseased corpse")

As for creating the unit, you use the initUnit. But, creating one in a spot taken by an enemy unit I hear would kill the enemy unit. There were a posts on the boards from the last week about creating new units that deals with the problems of placing them adjacent to a plot with enemies in them.
 
Thanks, I'll check it out. :)

Anyway, I have already at least the first line of the event-to-be:

Code:
if (pPlayer.getCivics(gc.getInfoTypeForString('CIVICOPTION_COMPASSION')) == gc.getInfoTypeForString('CIVIC_SACRIFICE_THE_WEAK')):

Btw, could the event for Loki the Clown fleeing be used for placing units adjacent? Where is it? I can't find it. :(
 
M@ni@c said:
Btw, is there any difference between using:

if X:
.......if Y:

or

if X and Y:

?

No, just whatever is easier to read.
 
M@ni@c said:
Thanks, I'll check it out. :)

Anyway, I have already at least the first line of the event-to-be:

Code:
if (pPlayer.getCivics(gc.getInfoTypeForString('CIVICOPTION_COMPASSION')) == gc.getInfoTypeForString('CIVIC_SACRIFICE_THE_WEAK')):

Btw, could the event for Loki the Clown fleeing be used for placing units adjacent? Where is it? I can't find it. :(

Its in the CustomFunctions.py file.
 
Thanks!
Btw, just started wondering, if you use the Civics condition, does the game check for the civics of the combat winner or loser? Can you use if (pLoser.getCivics...?

Because I didn't know this, I tried something with onUnitKilled, but fully as expected, my computer crashes. I feel like I'm throwing some mechanical parts in a box and hoping to get a working car engine.

Code:
	def onUnitKilled(self, argsList):
		'Unit Killed'
		unit, iAttacker = argsList
		player = PyPlayer(unit.getOwner())
		attacker = PyPlayer(iAttacker)

		iDiseased = gc.getInfoTypeForString('PROMOTION_DISEASED')
		iPlagued = gc.getInfoTypeForString('PROMOTION_PLAGUED')
		iDiseasedCorpse = gc.getInfoTypeForString('UNIT_DISEASED_CORPSE')

		if (pPlayer.getCivics(gc.getInfoTypeForString('CIVICOPTION_COMPASSION')) == gc.getInfoTypeForString('CIVIC_SACRIFICE_THE_WEAK')):
			if pUnit.isHasPromotion(iDiseased) or pUnit.isHasPromotion(iPlagued):
				if (pUnit.getUnitType() != iDiseasedCorpse:
					if CyGame().getSorenRandNum(100, "Maniac") <= 33:
						pPlot = cf.FFHFindClearPlot(-1, pPlot)
						if pPlot != -1:
							newUnit = bPlayer.initUnit(iDiseasedCorpse, pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI)
							CyInterface().addMessage(newUnit.getOwner(),True,25,'Veil necromancy at work. Diseased Corpse raised.','AS2D_DISCOVERBONUS',1,'Art/Interface/Buttons/Units/Diseasedcorpse.dds',ColorTypes(8),newUnit.getX(),newUnit.getY(),True,True)
							newUnit.finishMoves()
							newUnit.setDamage(pUnit.getDamage(), False)
							newUnit.setExperience(pUnit.getExperience(), -1)
							newUnit.setLevel(pUnit.getLevel())
							for iCount in range(gc.getNumPromotionInfos()):
								if (pUnit.isHasPromotion(iCount)):
									newUnit.setHasPromotion(iCount, True)
 
Kael said:
I'd check out mrkingkings post in the sample python thread that does about the same thing:

http://forums.civfanatics.com/showpost.php?p=4502328&postcount=56

I don't understand what the bolder part is for. :confused:

Code:
		if pLoser.getUnitType() == gc.getInfoTypeForString('UNIT_KNIGHT'):
                        CyInterface().addImmediateMessage("Your knight has survived the fall, and gets to his feet", "")
                        [b]deadUnitX = pLoser.getX()
                        deadUnitY = pLoser.getY()[/b]
                        newUnit = playerY.initUnit(gc.getInfoTypeForString('UNIT_SWORDSMAN'), [b]deadUnitX, deadUnitY,[/b] UnitAITypes.NO_UNITAI
 
M@ni@c said:
I don't understand what the bolder part is for. :confused:

Code:
		if pLoser.getUnitType() == gc.getInfoTypeForString('UNIT_KNIGHT'):
                        CyInterface().addImmediateMessage("Your knight has survived the fall, and gets to his feet", "")
                        [b]deadUnitX = pLoser.getX()
                        deadUnitY = pLoser.getY()[/b]
                        newUnit = playerY.initUnit(gc.getInfoTypeForString('UNIT_SWORDSMAN'), [b]deadUnitX, deadUnitY,[/b] UnitAITypes.NO_UNITAI)

Not much, he could have had the same effect from the following, which is probably simpliar:

Code:
		if pLoser.getUnitType() == gc.getInfoTypeForString('UNIT_KNIGHT'):
                        CyInterface().addImmediateMessage("Your knight has survived the fall, and gets to his feet", "")
                        newUnit = playerY.initUnit(gc.getInfoTypeForString('UNIT_SWORDSMAN'), pLoser.getX(), pLoser.getY(), UnitAITypes.NO_UNITAI)
[/QUOTE]
 
I tried anew with onCombatResult, but alas I get an error again. The log says i's a syntax error, but I don't see the problem. :confused:

Code:
	def onCombatResult(self, argsList):
		'Combat Result'
		pWinner,pLoser = argsList
		playerX = PyPlayer(pWinner.getOwner())
		unitX = PyInfo.UnitInfo(pWinner.getUnitType())
		playerY = PyPlayer(pLoser.getOwner())
		unitY = PyInfo.UnitInfo(pLoser.getUnitType())
		pPlayer = gc.getPlayer(pWinner.getOwner())
		bUncaptured = True

		pLPlayer = gc.getPlayer(pLoser.getOwner())
		iDiseased = gc.getInfoTypeForString('PROMOTION_DISEASED')
		iPlagued = gc.getInfoTypeForString('PROMOTION_PLAGUED')
		iDiseasedCorpse = gc.getInfoTypeForString('UNIT_DISEASED_CORPSE')

		if (pLPlayer.getCivics(gc.getInfoTypeForString('CIVICOPTION_COMPASSION')) == gc.getInfoTypeForString('CIVIC_SACRIFICE_THE_WEAK')):
			if pLoser.isHasPromotion(iDiseased) or pLoser.isHasPromotion(iPlagued):
				if (pLoser.getUnitType() != iDiseasedCorpse:
					if CyGame().getSorenRandNum(100, "Maniac") <= 33:
						pPlot = cf.FFHFindClearPlot(-1, pPlot)
						if pPlot != -1:
							newUnit = PlayerY.initUnit(iDiseasedCorpse, pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI)
							CyInterface().addMessage(pWinner.getOwner(),True,25,'Diseased Corpses arise from our slain enemies.','AS2D_DISCOVERBONUS',1,'Art/Interface/Buttons/Units/Diseasedcorpse.dds',ColorTypes(8),pLoser.getX(),pLoser.getY(),True,True)
							CyInterface().addMessage(pLoser.getOwner(),True,25,'Diseased Corpses arise from the battlefield.','AS2D_DISCOVERBONUS',1,'Art/Interface/Buttons/Units/Diseasedcorpse.dds',ColorTypes(8),pLoser.getX(),pLoser.getY(),True,True)
							newUnit.finishMoves()

Bug report. Supposedly the ":"

Code:
  File "CvEventManager", line 940
    if (pLoser.getUnitType() != iDiseasedCorpse:
                                               ^
SyntaxError: invalid syntax

If I try to avoid that : by putting two conditions on the same line:

Code:
  File "CvEventManager", line 940
    if (pLoser.getUnitType() != iDiseasedCorpse and	CyGame().getSorenRandNum(100, "Maniac") <= 33:
                                                                                                 ^
SyntaxError: invalid syntax

:confused:
 
M@ni@c said:
lol but neither do I understand what the pLoser.getX(), pLoser.getY(), is for.

It tells it where to place the new unit (the x and y coordinates of the unit that lost the battle).
 
It looks pretty good. The following code has PeteT's fix in it and one other fix. The FFHFindClearPlot function takes either a unit passed to it or a plot. Most of the time you will want to use a unit (I just added the plot option because occasionally I dont have a unit to work with).

Code:
	def onCombatResult(self, argsList):
		'Combat Result'
		pWinner,pLoser = argsList
		playerX = PyPlayer(pWinner.getOwner())
		unitX = PyInfo.UnitInfo(pWinner.getUnitType())
		playerY = PyPlayer(pLoser.getOwner())
		unitY = PyInfo.UnitInfo(pLoser.getUnitType())
		pPlayer = gc.getPlayer(pWinner.getOwner())
		bUncaptured = True

		pLPlayer = gc.getPlayer(pLoser.getOwner())
		iDiseased = gc.getInfoTypeForString('PROMOTION_DISEASED')
		iPlagued = gc.getInfoTypeForString('PROMOTION_PLAGUED')
		iDiseasedCorpse = gc.getInfoTypeForString('UNIT_DISEASED_CORPSE')

		if (pLPlayer.getCivics(gc.getInfoTypeForString('CIVICOPTION_COMPASSION')) == gc.getInfoTypeForString('CIVIC_SACRIFICE_THE_WEAK')):
			if pLoser.isHasPromotion(iDiseased) or pLoser.isHasPromotion(iPlagued):
				if (pLoser.getUnitType() != iDiseasedCorpse):
					if CyGame().getSorenRandNum(100, "Maniac") <= 33:
						pPlot = cf.FFHFindClearPlot(pLoser, -1)
						if pPlot != -1:
							newUnit = PlayerY.initUnit(iDiseasedCorpse, pPlot.getX(), pPlot.getY(), UnitAITypes.NO_UNITAI)
							CyInterface().addMessage(pWinner.getOwner(),True,25,'Diseased Corpses arise from our slain enemies.','AS2D_DISCOVERBONUS',1,'Art/Interface/Buttons/Units/Diseasedcorpse.dds',ColorTypes(8),pLoser.getX(),pLoser.getY(),True,True)
							CyInterface().addMessage(pLoser.getOwner(),True,25,'Diseased Corpses arise from the battlefield.','AS2D_DISCOVERBONUS',1,'Art/Interface/Buttons/Units/Diseasedcorpse.dds',ColorTypes(8),pLoser.getX(),pLoser.getY(),True,True)
							newUnit.finishMoves()
 
Thanks Kael and PeteT, I get no debugging errors anymore.
Other problem though... the code doesn't seem to do anything... :(
 
M@ni@c said:
Thanks Kael and PeteT, I get no debugging errors anymore.
Other problem though... the code doesn't seem to do anything... :(

For it to work the loser would have to have the sacrifice the weak civic option, the losing unit will have to be a diseased or plagued unit that isnt a diseased corpse. And then it should do something 1/3rd of the time.
 
Then a new unit should be created on the losing units' plot, or if that plot is occupied (ie, by the winner), on an adjacent free plot.

I tried out some stuff in the hope to get it to work, but without result.

I don't understand the FFHFindClearPLot function, but because the order to create a new unit is under the "if pPlot != -1:" condition, I thought maybe a unit was only created if the losing units' plot wasn't free. So I tried out "if pPlot == -1 or pPlot != -1:", but that doesn't work either. Simply removing the FindClearPlot function and creating a new unit doesn't work either. I really don't know what could be the problem. :(
 
Back
Top Bottom