Need to combine two MOD Comps into "def onCombatResult"

kiwitt

Road to War Modder
Joined
Jan 11, 2006
Messages
5,599
Location
Auckland, NZ (GMT+12)
I need to combine
Spoiler :
Code:
###respawn part 1 start###

		pPlayer = gc.getPlayer(pLoser.getOwner())
		pPID = pPlayer.getID()
		promotion = []
		promotion.append(gc.getInfoTypeForString('PROMOTION_LIVE2'))
		promotion.append(gc.getInfoTypeForString('PROMOTION_LIVE1'))
		
		if ((pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_LIVE1')))or(pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_LIVE2')))):
                        iUnit = pLoser.getUnitType()                  
                        pCity= pPlayer.getCapitalCity()
        		iX =pCity.getX()
        		iY = pCity.getY()
        		if pLoser.getDomainType ()==gc.getInfoTypeForString('DOMAIN_SEA'):
                                for iCity in range(pPlayer.getNumCities () ):
                                        ppCity = pPlayer.getCity(iCity)
                                        if ppCity.isNone():continue
                                        if ppCity.getOwner()<>pPID:continue
                                        pPlot = CyMap().plot(ppCity.getX(),ppCity.getY())
                                        if pPlot.isCoastalLand ():
                                                iX = ppCity.getX()
                                                iY = ppCity.getY()
                                                break                                

			newUnit = pPlayer.initUnit(iUnit, iX,iY, UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
			pLoser.setDamage(0, False)
			newUnit.convert(pLoser)
        			
                        newUnit.finishMoves()
			counter=0
			CyInterface().addMessage(pPID,false,15,CyTranslator().getText("TXT_KEY_REBORN",()),'',0,'Art/Interface/Buttons/Phoenix.dds',ColorTypes(44), iX, iY, True,True)
			for i in range(2):                                
                                counter=counter+1
                                newUnit.setHasPromotion(promotion[i], False)                                                
                        for i in range(2):
                                if pLoser.isHasPromotion(promotion[i]):
                                        if i==1:
                                                break
                                        newUnit.setHasPromotion(promotion[i+1], True)
                        pLoser.setDamage(100, False)
###respawn part 1 end###
and
Spoiler :
Code:
## mechaerik War Prize ModComp START##
		pPlayer = gc.getPlayer(pWinner.getOwner())
		if not (gc.getPlayer(pWinner.getOwner()).isBarbarian()):
			if (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_NAVAL")) or (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_ARMOR")) or (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_GUN")) or (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_PARATROOP")):
				if (unitY.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_NAVAL")) or (unitY.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_SIEGE")):
					if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):
						if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):
							if CyGame().getSorenRandNum(100, "Bob") <= 25:
								iUnit = pLoser.getUnitType()
								newUnit = pPlayer.initUnit(pLoser.getUnitType(), pWinner.getX(), pWinner.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION)
								newUnit.finishMoves()
								newUnit.setDamage(50, pWinner.getOwner())
## War Prize Modcomp END##
Can some one advise how ?
 
Where's the problem?
You can just put the second code part directly under the first, like you normal merge python code, that should work.

If you have a logical problem, because a unit with the respawn promotion could be doubled, then don't allow this promotion for these units, would be the simplest.
 
Just make sure indentation is in order. Both sets of code must use the same amount of whitespace for each level - and no combining tabs and blank space.
 
Here is the full section
Spoiler :
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())
## mechaerik War Prize ModComp START##
		pPlayer = gc.getPlayer(pWinner.getOwner())
		if not (gc.getPlayer(pWinner.getOwner()).isBarbarian()):
			if (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_NAVAL")) or (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_ARMOR")) or (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_GUN")) or (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_PARATROOP")):
				if (unitY.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_NAVAL")) or (unitY.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_SIEGE")):
					if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):
						if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):
							if CyGame().getSorenRandNum(100, "Bob") <= 25:
								iUnit = pLoser.getUnitType()
								newUnit = pPlayer.initUnit(pLoser.getUnitType(), pWinner.getX(), pWinner.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION)
								newUnit.finishMoves()
								newUnit.setDamage(50, pWinner.getOwner())
## War Prize Modcomp END##
###respawn part 1 start###

		pPlayer = gc.getPlayer(pLoser.getOwner())
		pPID = pPlayer.getID()
		promotion = []
		promotion.append(gc.getInfoTypeForString('PROMOTION_LIVE2'))
		promotion.append(gc.getInfoTypeForString('PROMOTION_LIVE1'))
		
		if ((pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_LIVE1')))or(pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_LIVE2')))):
                        iUnit = pLoser.getUnitType()                  
                        pCity= pPlayer.getCapitalCity()
        		iX =pCity.getX()
        		iY = pCity.getY()
        		if pLoser.getDomainType ()==gc.getInfoTypeForString('DOMAIN_SEA'):
                                for iCity in range(pPlayer.getNumCities () ):
                                        ppCity = pPlayer.getCity(iCity)
                                        if ppCity.isNone():continue
                                        if ppCity.getOwner()<>pPID:continue
                                        pPlot = CyMap().plot(ppCity.getX(),ppCity.getY())
                                        if pPlot.isCoastalLand ():
                                                iX = ppCity.getX()
                                                iY = ppCity.getY()
                                                break                                

			newUnit = pPlayer.initUnit(iUnit, iX,iY, UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
			pLoser.setDamage(0, False)
			newUnit.convert(pLoser)
        			
                        newUnit.finishMoves()
			counter=0
			CyInterface().addMessage(pPID,false,15,CyTranslator().getText("TXT_KEY_REBORN",()),'',0,'Art/Interface/Buttons/Phoenix.dds',ColorTypes(44), iX, iY, True,True)
			for i in range(2):                                
                                counter=counter+1
                                newUnit.setHasPromotion(promotion[i], False)                                                
                        for i in range(2):
                                if pLoser.isHasPromotion(promotion[i]):
                                        if i==1:
                                                break
                                        newUnit.setHasPromotion(promotion[i+1], True)
                        pLoser.setDamage(100, False)
###respawn part 1 end###		
		if (not self.__LOG_COMBAT):
			return
		if playerX and playerX and unitX and playerY:
			CvUtil.pyPrint('Player %d Civilization %s Unit %s has defeated Player %d Civilization %s Unit %s' 
				%(playerX.getID(), playerX.getCivilizationName(), unitX.getDescription(), 
				playerY.getID(), playerY.getCivilizationName(), unitY.getDescription()))

If I put this is, in particular the warprize one. If you have already reached the limit of how many of that unit class you can have, does getting it as a war prize allow you to exceed the limit an cause no crash.
 
While you are at it, you should clean up the code.
The War Prize par has two identical "if" statements, one nested inside the other. This is a waste of disk space, processor time, and everything else.
Code:
					if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):
						if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):
It also goes to the trouble of defining iUnit to be pLoser.getUnitType() and then on the very next line ignores iUnit and calls pLoser.getUnitType() again. Either drop the line that defines iUnit or use it on the following line.

In the other part, the loop should use the pPlayer.firstCity() and pPlayer.nextCity() to properly loop over the full city list - as it is, it could miss one or more at the end of the list. It should also probably have some provision for what to do if no port city is found (perhaps just putting it into some sea plot, at least) - currently, it'll try to put a reincarnated ship into a land city if there is no port city. (If a civ's only, or last, port city is captured but then one of its existing ships with one of the relevant promotions is destroyed then where will it put the ship?) What happens when you try to init a sea domain unit into a city that is nowhere near a water plot? If the game automatically moves it to the closest water plot then you don't actually have to do anything about this, although you might want to do something so as to avoid things like having battleships reincarnate into a 1 tile lake that you can't connect to the ocean (although this could be funny if that lake was right next to an enemy city that you were about to attack - magic battleship pops in and bombards the city's defenses - it is probably not a good thing in general).
 
Thanks for those fixes for the first part. I don't even have "UNITCLASS_PRIVATEER" in my mod. So I could simply delete these lines, correct ?

RE: the second part, Thanks for that as well. It will be a good ide to to limit the availability of the respawn promotions "PROMOTION_LIVE1", "PROMOTION_LIVE2" to land units only. Reformed "ships" is not realistic, but re-formed "Armies" and "Corps" and "Divisions" seems more so, as this happned quite a lot in WWII.

However, for the first part captured ships is possible as well as captured Fortresses and Static defence unist like "Pillboxes" and "Anti-Tank defences".
 
On the Respawning ... If the unit has a unique name, will the respawned unit retain it's unique name or will it get a new name from the unitinfos <uniquename> list.
 
On the Respawning ... If the unit has a unique name, will the respawned unit retain it's unique name or will it get a new name from the unitinfos <uniquename> list.
The code from onCombatResult doesn't seem to have anything to do with naming units. This would probably be in something like onUnitCreated.

Looking a the code I found this however:
Code:
                                [COLOR="Red"]for iCity in range(pPlayer.getNumCities () ):[/COLOR]
                                        ppCity = pPlayer.getCity(iCity)
                                        if ppCity.[COLOR="Red"]isNone()[/COLOR]:continue
                                        if ppCity.getOwner()[COLOR="Red"]<>[/COLOR]pPID:continue
                                        pPlot = CyMap().plot(ppCity.getX(),ppCity.getY())
                                        if pPlot.isCoastalLand ():
                                                iX = ppCity.getX()
                                                iY = ppCity.getY()
                                                break
Its not optimal to loop through cities by their IDs, since some of the those IDs could belong to cities that are no more. All cities might basically not be included, although the code would appear to work as intended. There could be some rare case where it would cause unintended results however.

Also, I'm not sure if you can use "<>" as a operator in Python v2.4.1... It should probably be "!=" instead.

I realize that this isn't your code, but I'd recommend learning how to do your own instead of merging other peoples stuff. The time you spend on getting these merges right would probably be sufficient to learn how do this yourself. Just a reflection.
 
Thanks for the quick response. When I looked at the description it implied that it will simply respawn back into capital ... The J's description
What it does:
I've added 2 new promotions, respawn1+2.
Every promotion gives the unit +1 life.
If the unit dies, the higher respawn-promotion is lost, and the unit is in the capital reborn.
A unit with respawn2 can die, is reborn, loses respawn2, but still has respawn1. If the unit then again dies, it will lose respawn1, but is still reborn. After that, the unit is a normal unit, but can also again get the respawn-promotions.

As I only need to use it for LAND Units, can the cycling through cities be removed and the unit respawns only in the capital and no where else ?

And yes, I would like to learn python and this is my starting point.
 
Just start with the basics and you'll be able to do whatever you want shortly. Or you could do what I did and bang your head against the wall for a couple of months first, and then learn the basics by picking up a textbook. Because trying to learn it this way is a dead end. It will take forever and you'd still not even know some of the most basic things about Python. So you'll end up being a crappy programmer and not being able to do much of anything. And even the most basic things will take forever to get right, because you don't fully understand what you're doing.

This is a better entry point, but everyone of course does whatever they want.
 
@name: I'm not sure, never tested it with a named unit.
But looking at the code, the unit should stay with it's name.

In the other part, the loop should use the pPlayer.firstCity() and pPlayer.nextCity() to properly loop over the full city list - as it is, it could miss one or more at the end of the list.

Its not optimal to loop through cities by their IDs, since some of the those IDs could belong to cities that are no more. All cities might basically not be included, although the code would appear to work as intended. There could be some rare case where it would cause unintended results however.

I know, i know.
that modcomp is from a time before i knew that.

Also, I'm not sure if you can use "<>" as a operator in Python v2.4.1... It should probably be "!=" instead.

hhmm...at least, it doesn't throw an exception.
It's an artifact from my delphi programming before.

As I only need to use it for LAND Units, can the cycling through cities be removed and the unit respawns only in the capital and no where else ?

Yes, can be done.
Just remove the code, which Baldyr has displayed here, nothing else should have to be modified.



At learning: If you can dissect the code, you're already on a good way, so try it ;).
 
@The_J:

I didn't realize I was actually critiquing your code... So please don't take offense.

I'm thinking that <> works for some compatibility reason only. Like that the developers changed it to != at some point but left the old operator in place so that older code wouldn't get broken.

But what do I know? :dunno:
 
@The_J:

I didn't realize I was actually critiquing your code... So please don't take offense.

Why should i be offended?
What has been mentioned is clearly true, the code is buggy, that's it.
Just wanted to say that i'm not that stupid to make this mistake with knowing it :D.

I'm thinking that <> works for some compatibility reason only. Like that the developers changed it to != at some point but left the old operator in place so that older code wouldn't get broken.

But what do I know? :dunno:

I know exactly the same :dunno: :D.
 
Why should i be offended?
Oh, I was worried that you might think I was being critical of the code just because it was yours - alternatively that I was looking for errors in your code. Just to make it perfectly clear, so that there can be no misunderstanding. Because I'm not out to check any of your work for potential errors or anything. So now you know. ;)
 
Just start with the basics and you'll be able to do whatever you want shortly. Or you could do what I did and bang your head against the wall for a couple of months first, and then learn the basics by picking up a textbook. Because trying to learn it this way is a dead end. It will take forever and you'd still not even know some of the most basic things about Python. So you'll end up being a crappy programmer and not being able to do much of anything. And even the most basic things will take forever to get right, because you don't fully understand what you're doing.

This is a better entry point, but everyone of course does whatever they want.
My only steps in coding decades ago was BASIC, batch files, when I thought I could be a JoT in IT and since moved into specialising in infrastructure as opposed to programming.

These code samples are so critical to my mod, I am required to work out how to implement it and it this stage not understand it as well as I should, hence why I am seeking support. I understand Python is hard language to learn, so looking at code samples will help me learn it. There are hundreds of modcomps of python code available on here and some of which may significantly enhance my mod in later releases. I am currently in the final stages of releasing my mod and need all the support I can get in this critical phase, to ensure that it will work and not break.

Also, I am in two minds about how far I should learn python, with LUA being the new language for Civ 5.
 
While you are at it, you should clean up the code.
The War Prize par has two identical "if" statements, one nested inside the other. This is a waste of disk space, processor time, and everything else.
Code:
					if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):
						if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):

Yeah, thats an error. One of those should be unitX, instead of two unitYs.


Everything else is just my noobishness.
 
These code samples are so critical to my mod, I am required to work out how to implement it and it this stage not understand it as well as I should, hence why I am seeking support. I understand Python is hard language to learn, so looking at code samples will help me learn it. There are hundreds of modcomps of python code available on here and some of which may significantly enhance my mod in later releases. I am currently in the final stages of releasing my mod and need all the support I can get in this critical phase, to ensure that it will work and not break
I appreciate that you wanna utilize as many good mods as possible, but merging Python is still really a programmer's task. So you basically need a programmer to do this work for you.

And who said Python was difficult to learn? Its only difficult if you go about learning it this way...
 
Spoiler :
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())
## mechaerik War Prize ModComp START##
		pPlayer = gc.getPlayer(pWinner.getOwner())
		if not (gc.getPlayer(pWinner.getOwner()).isBarbarian()):
			if (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_NAVAL")) or (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_ARMOR")) or (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_GUN")) or (unitX.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_PARATROOP")):
				if (unitY.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_NAVAL")) or (unitY.getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_SIEGE")):
					if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):
						if not (unitY.getUnitClassType() == gc.getInfoTypeForString("UNITCLASS_PRIVATEER")):
							if CyGame().getSorenRandNum(100, "Bob") <= 25:
								iUnit = pLoser.getUnitType()
								newUnit = pPlayer.initUnit(pLoser.getUnitType(), pWinner.getX(), pWinner.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION)
								newUnit.finishMoves()
								newUnit.setDamage(50, pWinner.getOwner())
## War Prize Modcomp END##
###respawn part 1 start###

		pPlayer = gc.getPlayer(pLoser.getOwner())
		pPID = pPlayer.getID()
		promotion = []
		promotion.append(gc.getInfoTypeForString('PROMOTION_LIVE2'))
		promotion.append(gc.getInfoTypeForString('PROMOTION_LIVE1'))
		
		if ((pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_LIVE1')))or(pLoser.isHasPromotion(gc.getInfoTypeForString('PROMOTION_LIVE2')))):
                        iUnit = pLoser.getUnitType()                  
                        pCity = pPlayer.getCapitalCity()
        		iX = pCity.getX()
        		iY = pCity.getY()
        		if pLoser.getDomainType ()==gc.getInfoTypeForString('DOMAIN_SEA'):
                                for iCity in range(pPlayer.getNumCities () ):
                                        ppCity = pPlayer.getCity(iCity)
                                        if ppCity.isNone():continue
                                        if ppCity.getOwner()<>pPID:continue
                                        pPlot = CyMap().plot(ppCity.getX(),ppCity.getY())
                                        if pPlot.isCoastalLand ():
                                                iX = ppCity.getX()
                                                iY = ppCity.getY()
                                                break                                

			newUnit = pPlayer.initUnit(iUnit, iX,iY, UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_NORTH)
			pLoser.setDamage(0, False)
			newUnit.convert(pLoser)
        			
                        newUnit.finishMoves()
			counter=0
			CyInterface().addMessage(pPID,false,15,CyTranslator().getText("TXT_KEY_REBORN",()),'',0,'Art/Interface/Buttons/Phoenix.dds',ColorTypes(44), iX, iY, True,True)
			for i in range(2):                                
                                counter=counter+1
                                newUnit.setHasPromotion(promotion[i], False)                                                
                        for i in range(2):
                                if pLoser.isHasPromotion(promotion[i]):
                                        if i==1:
                                                break
                                        newUnit.setHasPromotion(promotion[i+1], True)
                        pLoser.setDamage(100, False)
###respawn part 1 end###		
		if (not self.__LOG_COMBAT):
			return
		if playerX and playerX and unitX and playerY:
			CvUtil.pyPrint('Player %d Civilization %s Unit %s has defeated Player %d Civilization %s Unit %s' 
				%(playerX.getID(), playerX.getCivilizationName(), unitX.getDescription(), 
				playerY.getID(), playerY.getCivilizationName(), unitY.getDescription()))

@Baldyr - I agree, I should learn Python, there are a lot of benefits. ... but as I said earlier, I just need to get these two into it initially.

The advantage of using other Civ4 code examples is that I can focus my learning on how Python works with Civ4. i.e. XML references in addition to C++ calls. Both of which a "generic" python tutorial will not benefit me with at this time.
 
Instead of a "generic" Python tutorial, you could use a CivIV specific one. ;)

And there is no such thing as CivIV only Python - you still need to know 90% of the basics - because it all still applies to modding.
 
Agreed !!! - I will look through your Tutorial as soon as I can.

In the meantime I just try understand this piece of code to get it into my mod. e.g. "pPlayer" is defined twice.
Spoiler :
Code:
pPlayer = gc.getPlayer(pWinner.getOwner())
...
pPlayer = gc.getPlayer(pLoser.getOwner())
when I would think it may be better to define to separate variables. e.g. pPlayerW and pPlayerL

Not sure how that will impact on subsequent code that uses the original variables, as they will need to be changed.
 
Top Bottom