Platyping's Promotions and Traits

Considering all the existing traits are adjectives like expansive, aggressive.
Considerate or thoughtful sound better than caring or doctor...

Anyway, "double production" of whatever is simple to do, with XML in trait info.
X% healing rate hmm:
1) Make a new promotion with the healing you want.
2) Grant it to the unit class you want.
Pure XML can achieve it simpler.

No python work required.

'Thoughtful' seems nice and thanks for the xml tip.

@Dumanios: Thanks for the 15% idea.
 
We at C2C have it worked out in BUG format for the Heroic Promotion to work, can you pls check and see if it is correct, thx:

Spoiler :
Code:
## By Platyping converted to BUG by StrategyOnly

from CvPythonExtensions import *
import CvEventInterface
import CvUtil
import BugUtil
import PyHelpers

gc = CyGlobalContext()
localText = CyTranslator()
PyPlayer = PyHelpers.PyPlayer
PyInfo = PyHelpers.PyInfo

def onCombatResult(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())

## Heroic Promotion Start ##
	if pLoser.getUnitCombatType() > -1:
		if pWinner.isHasPromotion(gc.getInfoTypeForString("PROMOTION_HEROIC2")):
			if CyGame().getSorenRandNum(20, "Golden Age") == 0:
				pPlayer = gc.getPlayer(pWinner.getOwner())
				pPlayer.changeGoldenAgeTurns((pPlayer.getGoldenAgeLength() / 5))
## Heroic Promotion End ##

def onUnitPromoted(argsList):
	'Unit Promoted'
	pUnit, iPromotion = argsList
	player = PyPlayer(pUnit.getOwner())
## AI Promotion ##
	pPlayer = gc.getPlayer(pUnit.getOwner())
	if not pPlayer.isHuman():
		if CyGame().getSorenRandNum(5, "Platy Promotion") == 0:
			iPromo = gc.getInfoTypeForString("PROMOTION_HEROIC2")
			pUnit.setHasPromotion(iPromotion, false)
			if pUnit.canAcquirePromotion(iPromo):
				pUnit.setHasPromotion(iPromo, true)
			else:
				pUnit.setHasPromotion(iPromotion, true)
## AI Promotion ##
 
So whats the difference between this and mine beside changing the promotion name :D
Anyway, I added a similar domain check for newer ones.
It is to prevent it from triggering when a land unit walks into a city and destroy ships and planes.

As I said, you can remove the AI part when your promotion has many other XML benefits.
 
So whats the difference between this and mine beside changing the promotion name :D
Anyway, I added a similar domain check for newer ones.
It is to prevent it from triggering when a land unit walks into a city and destroy ships and planes.


As I said, you can remove the AI part when your promotion has many other XML benefits.

So the coding is correct then?? And where is this red portion?
 
Means you downloaded an old version :D
Anyway, shouldn't be difficult for your python coders.
Just add a if condition to check winner and loser domain similar.
 
Hi Spi't,
I tried the download and take a peek.
There is nothing wrong in it, you missed out the important part in the python, which is onCombatResult.

For most of them, you can just use Find function and type in the promo name to see where is the commented part, for this case just find leech.

As for the AI part, it is not really important if your Cannibalism promotion has other XML effects.
It is only required if it is a totally python promotion.
 
hmmmm... I did a search for leech in the file and all i could find was the AI bit, I will have another look, clearly I messed something up :D

EDIT: Ok NO Idea how I missed that first time around.... what I get for working sleepy i guess cheers Plat!

Ok I am trying to merge it with a BUG based mod, and I get python errors after combat, I confess I have almost no knowledge of the right way to do things with python.

Could you take a look a tell me ho I messed it up :) If you know :)
Spoiler :
Code:
def onCombatResult(self, argsList):
		if (AutologOpt.isLogCombat()):

			self.UnitKilled = 1

			pWinner,pLoser = argsList
			if (pWinner.getOwner() == CyGame().getActivePlayer()
			or pLoser.getOwner() == CyGame().getActivePlayer()):
				playerX = PyPlayer(pWinner.getOwner())
				playerY = PyPlayer(pLoser.getOwner())
				winnerHealth = float(pWinner.baseCombatStr()) * float(pWinner.currHitPoints()) / float(pWinner.maxHitPoints())
				zsBattleLocn = self.getUnitLocation(pWinner)

				playerXDesc = PyPlayer(pWinner.getVisualOwner()).getCivilizationAdjective()
				playerYDesc = PyPlayer(pLoser.getVisualOwner()).getCivilizationAdjective()

				if (pWinner.getOwner() == CyGame().getActivePlayer()):
					if (self.bHumanPlaying):
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_ATTACKING_DEFEATS", (zsBattleLocn, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), playerYDesc, pLoser.getNameKey(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleWonAttacking = self.iBattleWonAttacking + 1
					else:
						self.fOdds = 100 - self.fOdds
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_DEFENDING_DEFEATS", (zsBattleLocn, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), playerYDesc, pLoser.getNameKey(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleWonDefending = self.iBattleWonDefending + 1

					Logger.writeLog(message, vColor="DarkRed")

				else:
					if (self.bHumanPlaying):
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_ATTACKING_LOSES", (zsBattleLocn, pLoser.getNameKey(), playerXDesc, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleLostAttacking = self.iBattleLostAttacking + 1
					else:
						self.fOdds = 100 - self.fOdds
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_DEFENDING_LOSES", (zsBattleLocn, pLoser.getNameKey(), playerXDesc, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleLostDefending = self.iBattleLostDefending + 1

					Logger.writeLog(message, vColor="Red")
		
## Leech Promotion Start ##
		if pLoser.getUnitCombatType() > -1:
			if pWinner.isHasPromotion(gc.getInfoTypeForString("PROMOTION_LEECH")):
				pWinner.setDamage(pWinner.getDamage() - (pLoser.baseCombatStr() * 20/pWinner.baseCombatStr()), false)
## Leech Promotion End ##

Also would it be possible to add a message when it does it? A basic 'You Ate Him!' Kind of thing.

Cheers :D
 
indentation is wrong.
I guess you have to shift the leech promo codes all by 1 tab to be in line with
pWinner,pLoser = argsList

Another way would be to cut out all the variable definitions,
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())
and define them before that
if (AutologOpt.isLogCombat()):
line, just like what default BTS is doing.

To add a line of message, you can take a look at some existing ones like Rally.
Not at coding computer.
 
Curious about the dynamics you programmed for a few of those more subject to interpretation tag descriptions on your traits.

Particularly:
  • Drafts on city capture - you mean it automatically drafts units from the captured city right? How does it work exactly? (I'm asking about the logic sequence and how it carries out - not the coding.)
  • No Relationship Penalty for Nukes - what's the full extent here? Does this mean you negate diplomatic penalties for owning nukes or for actually using them? Does it count for ALL nuke related penalties, both from the 3rd party nations AND the nation you nuke or something else entirely?
  • 4 Turns of Disorder for cities nuked - Does this mean you actually limit the amount of disorder time once you've captured a city you've nuked or am I off base here?
 
@Spit
To know that it is firing:
1) Use a modern armor.
2) Nuke it.
3) Attack a weak unit like longbowman which you should win without getting damaged.
4) See if it regains some life after battle.

For the message, as I mentioned, there are some promotions which message triggers, one of which is Rally promotion.
I won't be at my modding computer for awhile, so perhaps you can try and see if you can figure it out from that example. It is just one line of python code, plus some text in the text file.

@Thunderbird
Upon city captured, if population > min draft population, the unit that is supposed to be drafted will be created at that place, with drafted experience.
Population is deducted as well, 1 for crap units, 2 for mech infantry, according to XML data.
No drafting anger.
Does not add to drafting limit.
Does take into account resources and trade route though, as you cannot draft an axeman unless it has the copper/iron.

Nuke Penalty:
There was never any relationship penalty for owning them or launching them in BTS I believe.
Penalty is applied only when they are launched successfully.
Those shot down have no effect.
Thus, same for the trait, it only removes all relationship penalty for successful nukes, both to the victim, and the victim's friends.

Nuke Disorder:
Cities in the area of the Nuke, whether it is direct hit, or just adjacent will immediately go into disorder for 4 turns.
Of course, this is cumulative.
Nothing to do with city capture.

Just try it out and you will see what I mean :D
 
Thanks for the excellent answers! One more niggle though...

Upon city captured, if population > min draft population, the unit that is supposed to be drafted will be created at that place, with drafted experience.
What defines the unit that is 'supposed' to be drafted?
 
Whatever is defined by the BTS system.
You know, based on what tech and resources player has, as well as whether the unit is draftable based on XML data.
There is a python command to simply check which is the drafted unit for that particular city.
Thus, I simply use it and spawn the unit there.
 
@Spit
Code:
CyInterface().addMessage(iPlayer,true,10,CyTranslator().getText("TXT_EAT",(pWinner.getName(), pLoser.getName(),)),'',0, -1, -1, -1, -1, true,true)
Add this to end of Leech codes.

Make sure indentation (number of tabs) is same as the last line (after all the "if")

Then in the XML text files, add one new entry.
Code:
<TEXT>
	<Tag>TXT_EAT</Tag>
	<English>[COLOR_YELLOW]%s1[COLOR_GREEN] ate [COLOR_UNIT_TEXT]%s2[COLOR_GREEN]![COLOR_REVERT]</English>
</TEXT>

It will then display as Modern Armor ate Warrior! to just the player of the eating unit.
Change colors and wordings as you like.
 
hmmm... it still does not seem to be firing, I get no message...code is below.

The only reference I could find in BUG code to oncombatresult was in the autologEventmanager.py. As opposed to EventManager.py...could that have anything to do with my problems? I don't see why it should, but then I don't see much :-D

Spoiler :
Code:
def onCombatResult(self, argsList):
		if (AutologOpt.isLogCombat()):

			self.UnitKilled = 1

			pWinner,pLoser = argsList
			if (pWinner.getOwner() == CyGame().getActivePlayer()
			or pLoser.getOwner() == CyGame().getActivePlayer()):
				playerX = PyPlayer(pWinner.getOwner())
				playerY = PyPlayer(pLoser.getOwner())
				winnerHealth = float(pWinner.baseCombatStr()) * float(pWinner.currHitPoints()) / float(pWinner.maxHitPoints())
				zsBattleLocn = self.getUnitLocation(pWinner)

				playerXDesc = PyPlayer(pWinner.getVisualOwner()).getCivilizationAdjective()
				playerYDesc = PyPlayer(pLoser.getVisualOwner()).getCivilizationAdjective()

				if (pWinner.getOwner() == CyGame().getActivePlayer()):
					if (self.bHumanPlaying):
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_ATTACKING_DEFEATS", (zsBattleLocn, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), playerYDesc, pLoser.getNameKey(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleWonAttacking = self.iBattleWonAttacking + 1
					else:
						self.fOdds = 100 - self.fOdds
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_DEFENDING_DEFEATS", (zsBattleLocn, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), playerYDesc, pLoser.getNameKey(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleWonDefending = self.iBattleWonDefending + 1

					Logger.writeLog(message, vColor="DarkRed")

				else:
					if (self.bHumanPlaying):
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_ATTACKING_LOSES", (zsBattleLocn, pLoser.getNameKey(), playerXDesc, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleLostAttacking = self.iBattleLostAttacking + 1
					else:
						self.fOdds = 100 - self.fOdds
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_DEFENDING_LOSES", (zsBattleLocn, pLoser.getNameKey(), playerXDesc, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleLostDefending = self.iBattleLostDefending + 1

					Logger.writeLog(message, vColor="Red")
		
## Leech Promotion Start ##
			if pLoser.getUnitCombatType() > -1:
				if pWinner.isHasPromotion(gc.getInfoTypeForString("PROMOTION_LEECH")):
					pWinner.setDamage(pWinner.getDamage() - (pLoser.baseCombatStr() * 20/pWinner.baseCombatStr()), false)
					CyInterface().addMessage(iPlayer,true,10,CyTranslator().getText("TXT_EAT",(pWinner.getName(), pLoser.getName(),)),'',0, -1, -1, -1, -1, true,true)
## Leech Promotion End ##
 
Ah iPlayer was not defined yet.
Add a line iPlayer = pWinner.getOwner()

Also, activate python exceptions when you wanna know what went wrong.
Else, "still not working" will not tell you why
 
ok, when I put the code this way round, I get the attached python exception.
I tried a few different methods of using the definitions from the leech file, and not using those defs. also trying it in different locations, and also without using those defs, just adding the one line you said too, in a number of combinations, none of them worked, many of them generated no exceptions...

Python expceptions were always on, i just wasn't getting any error messages..

Spoiler :
Code:
	def onCombatResult(self, argsList):
## Leech Promotion Start ##
		pWinner,pLoser = argsList
		playerX = PyPlayer(pWinner.getOwner())
		unitX = PyInfo.UnitInfo(pWinner.getUnitType())
		playerY = PyPlayer(pLoser.getOwner())
		unitY = PyInfo.UnitInfo(pLoser.getUnitType())
		iPlayer = pWinner.getOwner()
			
		if pLoser.getUnitCombatType() > -1:
			if pWinner.isHasPromotion(gc.getInfoTypeForString("PROMOTION_LEECH")):
				pWinner.setDamage(pWinner.getDamage() - (pLoser.baseCombatStr() * 20/pWinner.baseCombatStr()), false)
				CyInterface().addMessage(iPlayer,true,10,CyTranslator().getText("TXT_EAT",(pWinner.getName(), pLoser.getName(),)),'',0, -1, -1, -1, -1, true,true)
## Leech Promotion End ##
	
		if (AutologOpt.isLogCombat()):

			self.UnitKilled = 1
						
			pWinner,pLoser = argsList
			if (pWinner.getOwner() == CyGame().getActivePlayer()
			or pLoser.getOwner() == CyGame().getActivePlayer()):
				playerX = PyPlayer(pWinner.getOwner())
				playerY = PyPlayer(pLoser.getOwner())
				winnerHealth = float(pWinner.baseCombatStr()) * float(pWinner.currHitPoints()) / float(pWinner.maxHitPoints())
				zsBattleLocn = self.getUnitLocation(pWinner)

				playerXDesc = PyPlayer(pWinner.getVisualOwner()).getCivilizationAdjective()
				playerYDesc = PyPlayer(pLoser.getVisualOwner()).getCivilizationAdjective()

				if (pWinner.getOwner() == CyGame().getActivePlayer()):
					if (self.bHumanPlaying):
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_ATTACKING_DEFEATS", (zsBattleLocn, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), playerYDesc, pLoser.getNameKey(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleWonAttacking = self.iBattleWonAttacking + 1
					else:
						self.fOdds = 100 - self.fOdds
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_DEFENDING_DEFEATS", (zsBattleLocn, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), playerYDesc, pLoser.getNameKey(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleWonDefending = self.iBattleWonDefending + 1

					Logger.writeLog(message, vColor="DarkRed")

				else:
					if (self.bHumanPlaying):
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_ATTACKING_LOSES", (zsBattleLocn, pLoser.getNameKey(), playerXDesc, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleLostAttacking = self.iBattleLostAttacking + 1
					else:
						self.fOdds = 100 - self.fOdds
						message = BugUtil.getText("TXT_KEY_AUTOLOG_WHILE_DEFENDING_LOSES", (zsBattleLocn, pLoser.getNameKey(), playerXDesc, pWinner.getNameKey(), BugUtil.formatFloat(winnerHealth, 2), pWinner.baseCombatStr(), BugUtil.formatFloat(self.fOdds, 1), lPercent))
						self.iBattleLostDefending = self.iBattleLostDefending + 1

					Logger.writeLog(message, vColor="Red")
 

Attachments

  • Civ4ScreenShot0022.JPG
    Civ4ScreenShot0022.JPG
    141.1 KB · Views: 140
Booster
Spoiler :


There is a reason why it is only available for Helicopters...


Happy Chinese New Year

@Spit
Code:
CyInterface().addMessage(iPlayer,true,10,CyTranslator().getText("TXT_EAT",(pWinner.getName(), pLoser.getName(),)),'',0, '',-1, -1, -1, true,true)

Replace one of the -1 with the ''.
This is what happens when I am not at modding computer :D
 
Top Bottom