Sample Python Code

Incase anybody here wanted to know the game uses 1.5 as the square root of 2. And when using the getPathDistance function (which finds the passable distance between 2 plots) it does use pythagoras. Just a very inacurate value.
 
Hey I was wondering if anyone can help me im trying to get the hang on python and understand the concept but it hasn't twigged yet what I can and can't do and how to go about it so I was wondering if someone more knowledgeabla can help me out

Upon reading forums and experimenting I've implemented a terraform mod into the mod i'm making that allows a workboat to turn a sea tile into a land tile

Code:
elif(iImprovement==lowerelev):
			if(pPlot.getPlotType()==PlotTypes.PLOT_LAND):
				numberofunits = pPlot.getNumUnits()
				while(numberofunits > 0):
					pPlot.getUnit(0).jumpToNearestValidPlot()
					numberofunits = pPlot.getNumUnits()
				pPlot.setPlotType(PlotTypes.PLOT_OCEAN, true, true)
			else:
				pPlot.setPlotType(PlotTypes.PLOT_LAND, true, true)
				if(pPlot.getTerrainType()==gc.getInfoTypeForString("TERRAIN_DESERT") and pPlot.isRiver()):
                                        pPlot.setFeatureType(gc.getInfoTypeForString("FEATURE_FLOOD_PLAINS"), 0)
			pPlot.setImprovementType(-1)

(stolen from tywiggins terraform mod)

upon completion of the terraform i'd like either a settler unit or a city to be built on the tile too.

From reading I discovered that something like this
Code:
def onCityBuilt(self, argsList):
	'For player 1, create a Warrior (index 17) in every city that is built'
	city = argsList[0]
	if city.getOwner() == 1:
		city.getOwner().initUnit(17, city.getX(), city.getY(), UnitAITypes.NO_UNITAI)

is responsible for creating a warrior in a city when it was built so what I want to know is how/is it possible to adapt this code and implement it into the above terraform code so that when a tile is improved a unit is created?

Even better would be if when a tile is improved, in this case that means terraformed from an ocean to grass tile, a city is built. However I don't know where to start with city building.

Thanks for your time reading and any help would be wonderful
 
The Butler said:
Hey I was wondering if anyone can help me...

This thread is just for posting working code, please post questions in the creation and customization forum and Im sure people would be glad to help.
 
In celebration of C.Rolands awesome "fire elemental" I give you the code I am using with it in Phase 2 (I call it a Pyre Zombie).

http://forums.civfanatics.com/showthread.php?t=164035


Code:
		if pLoser.getUnitType() == gc.getInfoTypeForString('UNIT_PYRE_ZOMBIE'):
			pPlot = pWinner.plot()
			point = pPlot.getPoint()
			for i in range(pPlot.getNumUnits()):
				pUnit = pPlot.getUnit(i)
				iRnd = CyGame().getSorenRandNum(30, "Bob") - 10
				if pUnit.isHasPromotion('PROMOTION_MAGIC_RESISTANCE'):
					iRnd = iRnd - 10
				if pUnit.isHasPromotion('PROMOTION_FIRE_RESISTANCE'):
					iRnd = iRnd - 10
				if pUnit.isHasPromotion('PROMOTION_VULNERABLE_TO_FIRE'):
					iRnd = iRnd + 10
				if iRnd >= 1:
					pUnit.setDamage(pUnit.getDamage() + iRnd, True)
			CyEngine().triggerEffect(cf.FFHgetEffectInfo('EFFECT_ARTILLERY_SHELL_EXPLODE'),point)
			CyAudioGame().Play3DSound("AS3D_UN_GRENADE_EXPLODE",point.x,point.y,point.z)

What it does:

When the Pyre Zombie is killed he explodes on the stack the winning unit is in. There is a explosion effect and sound that goes along with it. Damage is applied randomly and about 2/3 of the stack will take 0-20% damage from the explosion. This damage is modified by some of the promotions the units have.

Use:

Its really pretty contained code. This function is run out of onCombatResult in the CvEventManager.py file. I like it because its a good short sample that does a lot of interesting stuff and it shows how you can write your own functions to add some detail to game functions (in this case collateral damage) that may not do exactly what you want. I didn't like collateral for this effect because I only wanted it applied when the zombie died and I wanted it adjusted based on some promotions.

Enjoy!
 
Wow that code rocks Kael.... BTW ive used the .getSorenRandNum() function before. What is really suppose to go in the place where you typed "bob"? And does it affect anything besides your own enjoyment?
 
'bob' is the name of the random number generated and is only used by the debug files. How exactly do you create new missions in python? I've heard of mods where a unit could be used to create another unit but how do you do this *cough* Kael-I-know-you-did-this *cough*
 
Lord Olleus said:
'bob' is the name of the random number generated and is only used by the debug files. How exactly do you create new missions in python? I've heard of mods where a unit could be used to create another unit but how do you do this *cough* Kael-I-know-you-did-this *cough*

And I think its always "Bob" in my code because The Great Apple listed a sample way way back and he called it "Bob" so now everyone has Bob in their code for no real reason. :)

Making units is pretty easy, the hard part is what python event do you intercept to do it. I have some in onCombatresult (thats where defeated units are made into slaves, werewolves are created and defeated animals are captured).

But for more user initiated summons I intercept in the promotion function. every turn I reset my spellcasters xp and level so they are set to level. Then they get to pick their "promotion". I intercept the promotion function, see which one they picked and perform some action based on which promotion/spell they picked. Then I strip the promotion away and start over next turn.

The nice thing about the promotion method is the AI understands it. By changing the supposed effect of the promotion (for those of you wondering why the summon demon promotion gives +150% strength when it only lasts for millisecond) you can give the AI a clue as to which one it whould pick. So for example if it can fireball or summon a demon it will summon the demon.

Here is the code:

Code:
		if iPromotion == gc.getInfoTypeForString('PROMOTION_SUMMON_DEMON'):
			newUnit = pPlayer.initUnit(gc.getInfoTypeForString('UNIT_DEMON'), pUnit.getX(), pUnit.getY(), UnitAITypes.NO_UNITAI)
			pUnit.setHasPromotion(gc.getInfoTypeForString('PROMOTION_SUMMON_DEMON'), False)
			cf.FFHApplySpellMods(newUnit, pUnit)
 
For some reason the game doesn't have functions to return the number of turns left before a city advances to the next Culture or Great People level. But it's very easy to find that value and show it on your city's culture or GP bar. see attachments to see new culture and GP bars that show turns to completion.

First open CvMainInterface.py (backup if necessary) and look for these strings:
screen.setLabel( "CultureText",
screen.setLabel( "GreatPeopleText",

These are the labels you see on the city screen that say something like [Culture_Icon]: Poor ( +2/Turn ). We're gonna append the turns left.

So we find the value for turns left for culture. Thus:
PHP:
## FU edit start -- append Turns to Complete
					iCulRate =  pHeadSelectedCity.getCommerceRate(CommerceTypes.COMMERCE_CULTURE)
					if ( iCulRate > 0 ):
						iCulNext = pHeadSelectedCity.getCultureThreshold()
						iCulNow = pHeadSelectedCity.getCulture(pHeadSelectedCity.getOwner())
						iCulTurns = (iCulNext-iCulNow+iCulRate-1)/iCulRate
						szTurnsToComplete = " %d Turns" %(iCulTurns)
						szBuffer = szBuffer + szTurnsToComplete
						szTurnsToComplete = ""
## FU edit end
					screen.setLabel( "CultureText", "Background", szBuffer, CvUtil.FONT_CENTER_JUSTIFY, 125, yResolution - 184, -1.3, FontTypes.GAME_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1 )

szBuffer holds the string that shows up on screen. We put together szBuffer + szTurnsToComplete.

We do the same for Great People.

PHP:
## FU edit start -- append turns to completion
					iGPRate = pHeadSelectedCity.getGreatPeopleRate()
					if ( iGPRate > 0 ):
						iGPNext = gc.getPlayer( pHeadSelectedCity.getOwner() ).greatPeopleThreshold()
						iGPNow = pHeadSelectedCity.getGreatPeopleProgress()
						iGPTurns = (iGPNext-iGPNow+iGPRate-1)/iGPRate
						szTurnsToComplete = " %d Turns" %(iGPTurns)
						szBuffer = szBuffer + szTurnsToComplete
						szTurnsToComplete = ""
## FU edit end
					screen.setLabel( "GreatPeopleText", "Background", szBuffer, CvUtil.FONT_CENTER_JUSTIFY, xResolution - 146, yResolution - 176, -1.3, FontTypes.GAME_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1 )

iCulTurns and iGPTurns have those equations so that we don't have to import math and use ceil function. With math.ceil, it would be iGPTurns = math.ceil(float(iGPNext-iGPNow)/iGPRate)
 

Attachments

  • culture.jpg
    culture.jpg
    3.4 KB · Views: 565
  • gpbar.jpg
    gpbar.jpg
    2.8 KB · Views: 498
Someone should sticky this thread. I know I find it very usefull and its a nuissance to have to keep looking for it.
 
Code:
def startWar(iPlayer,i2Player):
	iTeam = gc.getPlayer(iPlayer).getTeam()
	i2Team = gc.getPlayer(i2Player).getTeam()
	eTeam = gc.getTeam(iTeam)
	if (eTeam.isAtWar(i2Team) == False and iTeam != i2Team):
		eTeam.declareWar(i2Team, False)

What it does:

This is a very simple function, it literally just causes iPlayer to declare war on i2Player. Both of the players have to be passed to the function. The function checks to make sure they aren't already at war and that they aren't on the same team (which also keeps players from declaring war on themselves, a problem I had in early FfH versions).

Use:

It may seem werid to have such a simple function seperated out. But I found that as I made more and more functions that caused players to declare war on each other that it was very handy to have one function that did all the hard work. Also the fact that players don't declare war on player's teams declare war on teams was always confusing me and it seemed like I always made a mistake when I tried to rewrite these functions. Mostly because a "Team object" delcares war on a "Team int" instead of another team object.

Note that the first player passed to the function declares war on the 2nd, which is significant when pacts and such are calculated.
 
I want to add my part to that thread with that function below. It is used in the next version of my Plot List Enhancements and calculates the heal factor of a unit. The heal factor is needed to calculate the number of turns a wounded units needs to get 100% healed.

The function is called with only the unit to be examined as parameter.

Here is the code:

PHP:
def getPlotHealFactor(pUnit):

	# heal rates for certain areas. They are usually stored in the GlobalDefines.XML but can't be read out with a standard API function.
	# So I placed them here as constants.
	ENEMY_HEAL_RATE				= 5
	NEUTRAL_HEAL_RATE			= 10
	FRIENDLY_HEAL_RATE			= 15
	CITY_HEAL_RATE				= 20

	
	# set/reset some variables
	pPlot = pUnit.plot()
	iSameTileHealFactor 		= 0
	iAdjacentTileHealFactor 	= 0
	iBuildingHealFactor 		= 0
	iSelfHealFactor 			= 0
	iPromotionHealFactor 		= 0
	iTileHealFactor 			= 0
	iActivePlayer 				= CyGame().getActivePlayer()
	pActivePlayer 				= gc.getPlayer(iActivePlayer)
	iActivePlayerTeam 			= pActivePlayer.getTeam()
	eDomain 					= gc.getUnitInfo(pUnit.getUnitType()).getDomainType()
	
	# a sea or air unit in a city, behaves like a land unit
	if pPlot.isCity():
		eDomain = DomainTypes.DOMAIN_LAND

	# calculate the adjacent-tile heal-factor caused by other units (only the unit with the highest factor counts)
	for dx in range(-1, 2):
		for dy in range(-1, 2):
			# ignore same tile. Adjacent-tile healing does not work on the same tile.
			if not (dx == 0 and dy == 0):
				pLoopPlot = CyMap().plot(pPlot.getX()+dx, pPlot.getY()+dy)
				# loop through all units on the plot
				for i in range(pLoopPlot.getNumUnits()):
					pLoopUnit = pLoopPlot.getUnit(i)
					eLoopUnitDomain = gc.getUnitInfo(pLoopUnit.getUnitType()).getDomainType()
					# a sea or air unit in a city, behaves like a land unit
					if ((eDomain == DomainTypes.DOMAIN_SEA) or (eDomain == DomainTypes.DOMAIN_AIR)) and pLoopPlot.isCity():
						eLoopUnitDomain = DomainTypes.DOMAIN_LAND
					# adjacent-tile heal does only work if the units have the same domain type
					if (eDomain == eLoopUnitDomain):
						if (pLoopUnit.getTeam() == iActivePlayerTeam):
							if (pLoopUnit.getAdjacentTileHeal() > iAdjacentTileHealFactor):
								iAdjacentTileHealFactor = pLoopUnit.getAdjacentTileHeal()
	
	# calculate the same-tile heal-factor caused by other or same unit (only the unit with the highest factor counts)
	# the same-tile healing is also a kind of self-healing. Means : the promotion Medic I has also effect on the owner unit
	for i in range(pPlot.getNumUnits()):
		pLoopUnit = pPlot.getUnit(i)
		eLoopUnitDomain = gc.getUnitInfo(pLoopUnit.getUnitType()).getDomainType()
		# a sea or air unit in a city, behaves like a land unit
		if pLoopPlot.isCity():
			eLoopUnitDomain = DomainTypes.DOMAIN_LAND
		# same tile heal does only work if the units are of the same domain type
		if (eDomain == eLoopUnitDomain):
			if (pLoopUnit.getTeam() == iActivePlayerTeam):
				if (pLoopUnit.getSameTileHeal() > iSameTileHealFactor):
					iSameTileHealFactor = pLoopUnit.getSameTileHeal()
				
	# only the highest value counts
	iTileHealFactor = max(iAdjacentTileHealFactor, iSameTileHealFactor)

	# calculate the self heal factor by the location and promotion
	iTeam = pPlot.getTeam()
	pTeam = gc.getTeam(iTeam)		
	iSelfHealFactor 		= NEUTRAL_HEAL_RATE
	iPromotionHealFactor 	= pUnit.getExtraNeutralHeal()
	if pPlot.isCity():
		iSelfHealFactor 		= CITY_HEAL_RATE
		iPromotionHealFactor 	= pUnit.getExtraFriendlyHeal()
	elif (iTeam == iActivePlayerTeam):
		iSelfHealFactor 		= FRIENDLY_HEAL_RATE
		iPromotionHealFactor 	= pUnit.getExtraFriendlyHeal()
	elif (iTeam != TeamTypes.NO_TEAM):
		if (pTeam.isAtWar(iActivePlayerTeam)):
			iSelfHealFactor 		= ENEMY_HEAL_RATE
			iPromotionHealFactor 	= pUnit.getExtraEnemyHeal()
	
	# calculate the heal factor by city buildings
	if pPlot.isCity():
		if (pPlot.getTeam() == iActivePlayerTeam):
			pCity = pPlot.getPlotCity()
			# loop for all buldings
			for iBuilding in range(gc.getNumBuildingClassInfos()):
				# check if city has that building
				if pCity.hasBuilding(iBuilding):
					# sum up all heal rates 
					iBuildingHealFactor += gc.getBuildingInfo(iBuilding).getHealRateChange()

	# return the sum of all heal factors
	return iTileHealFactor + iBuildingHealFactor + iSelfHealFactor + iPromotionHealFactor

Lets step through the main parts :

first few lines are used to set some variables and constants. Nothing special here:

PHP:
	# heal rates for certain areas. They are usually stored in the GlobalDefines.XML but can't be read out with a standard API function.
	# So I placed them here as constants.
	ENEMY_HEAL_RATE				= 5
	NEUTRAL_HEAL_RATE			= 10
	FRIENDLY_HEAL_RATE			= 15
	CITY_HEAL_RATE				= 20

	
	# set/reset some variables
	pPlot = pUnit.plot()
	iSameTileHealFactor 		= 0
	iAdjacentTileHealFactor 	= 0
	iBuildingHealFactor 		= 0
	iSelfHealFactor 			= 0
	iPromotionHealFactor 		= 0
	iTileHealFactor 			= 0
	iActivePlayer 				= CyGame().getActivePlayer()
	pActivePlayer 				= gc.getPlayer(iActivePlayer)
	iActivePlayerTeam 			= pActivePlayer.getTeam()
	eDomain 					= gc.getUnitInfo(pUnit.getUnitType()).getDomainType()

This one is quite important to know. A sea or air unit can be healed by a land unit, but only when its in a city. This leads to 2 major conclusions :
- a sea unit with promotion Medic I (same tile heal +10%) located in a city can heal a land unit located in the city and can also heal a land unit with Medic II (adjacent tile heal + 10%) if the unit is on a cities adjacent tile.
- a sea unit on the coast with Medic II can't heal a land unit on an adjacent tile.
Due to that I set the units domain to DOMAIN_LAND when the units to be examined it is located in a city.
PHP:
	# a sea or air unit in a city, behaves like a land unit
	if pPlot.isCity():
		eDomain = DomainTypes.DOMAIN_LAND


Next the adjacent tile heal is watched. A loop though all adjacent tiles for a friendly (own or teammate) unit which has a protmotion with adjacent tile heal. I don't look for the promotion itself, but for its effects on the heal factor with the function CyUnit.getAdjacentTileHeal(). This makes the function mod friendly.
Two things to be mentioned :
- the same tile is ignored, because the adjacent tile heal has no effect on the same tile!!!
- if the adjacent plot is a city, also the air and sea units are considered.
PHP:
	# calculate the adjacent-tile heal-factor caused by other units (only the unit with the highest factor counts)
	for dx in range(-1, 2):
		for dy in range(-1, 2):
			# ignore same tile. Adjacent-tile healing does not work on the same tile.
			if not (dx == 0 and dy == 0):
				pLoopPlot = CyMap().plot(pPlot.getX()+dx, pPlot.getY()+dy)
				# loop through all units on the plot
				for i in range(pLoopPlot.getNumUnits()):
					pLoopUnit = pLoopPlot.getUnit(i)
					eLoopUnitDomain = gc.getUnitInfo(pLoopUnit.getUnitType()).getDomainType()
					# a sea or air unit in a city, behaves like a land unit
					if pLoopPlot.isCity():
						eLoopUnitDomain = DomainTypes.DOMAIN_LAND
					# adjacent-tile heal does only work if the units have the same domain type
					if (eDomain == eLoopUnitDomain):
						if (pLoopUnit.getTeam() == iActivePlayerTeam):
							if (pLoopUnit.getAdjacentTileHeal() > iAdjacentTileHealFactor):
								iAdjacentTileHealFactor = pLoopUnit.getAdjacentTileHeal()

Now we examine the friendly units on the same plot. More or less the same stuff as before. One thing to be mentioned here :
- the same tile healing (as it is with the promotion Medic I) is also a self healing. Means : it has also effect on the promotions owner unit!!.
PHP:
	# calculate the same-tile heal-factor caused by other or same unit (only the unit with the highest factor counts)
	# the same-tile healing is also a kind of self-healing. Means : the promotion Medic I has also effect on the owner unit
	for i in range(pPlot.getNumUnits()):
		pLoopUnit = pPlot.getUnit(i)
		eLoopUnitDomain = gc.getUnitInfo(pLoopUnit.getUnitType()).getDomainType()
		# a sea or air unit in a city, behaves like a land unit
		if pLoopPlot.isCity():
			eLoopUnitDomain = DomainTypes.DOMAIN_LAND
		# same tile heal does only work if the units are of the same domain type
		if (eDomain == eLoopUnitDomain):
			if (pLoopUnit.getTeam() == iActivePlayerTeam):
				if (pLoopUnit.getSameTileHeal() > iSameTileHealFactor):
					iSameTileHealFactor = pLoopUnit.getSameTileHeal()

Because the two values adjacent tile heal factor and same tile heal factor are not summed up, we can only use the largest of both values.
PHP:
	# only the highest value counts
	iTileHealFactor = max(iAdjacentTileHealFactor, iSameTileHealFactor)

Next we are looking on the self healing factor. It is influenced by two factors : the territory (friendly, neutral or enemy) the unit is located on and several promotions which could increase this territory factor. Which territory the unit is currently on is determined by the plot's owner. If it's the player or a teammate we have friendly territory, if it's somebody we have war with it's enemy territory. Anything else is neutral.
PHP:
	# calculate the self heal factor by the location and promotion
	iTeam = pPlot.getTeam()
	pTeam = gc.getTeam(iTeam)		
	iSelfHealFactor 		= NEUTRAL_HEAL_RATE
	iPromotionHealFactor 	= pUnit.getExtraNeutralHeal()
	if pPlot.isCity():
		iSelfHealFactor 		= CITY_HEAL_RATE
		iPromotionHealFactor 	= pUnit.getExtraFriendlyHeal()
	elif (iTeam == iActivePlayerTeam):
		iSelfHealFactor 		= FRIENDLY_HEAL_RATE
		iPromotionHealFactor 	= pUnit.getExtraFriendlyHeal()
	elif (iTeam != TeamTypes.NO_TEAM):
		if (pTeam.isAtWar(iActivePlayerTeam)):
			iSelfHealFactor 		= ENEMY_HEAL_RATE
			iPromotionHealFactor 	= pUnit.getExtraEnemyHeal()

Finally we are looking at the buildings which may have influence to the healing. Of course, this is only done when we are in a players or teammates city. Then we loop through all buildings in the city looking for the buildings influence on healing. Currently there is only one standard building doing so : the hospital.
PHP:
	# calculate the heal factor by city buildings
	if pPlot.isCity():
		if (pPlot.getTeam() == iActivePlayerTeam):
			pCity = pPlot.getPlotCity()
			# loop for all buldings
			for iBuilding in range(gc.getNumBuildingClassInfos()):
				# check if city has that building
				if pCity.hasBuilding(iBuilding):
					# sum up all heal rates 
					iBuildingHealFactor += gc.getBuildingInfo(iBuilding).getHealRateChange()

Last thing is to sum up all the single heal factors and return the value.
PHP:
	# return the sum of all heal factors
	return iTileHealFactor + iBuildingHealFactor + iSelfHealFactor + iPromotionHealFactor

The value returned by this function can now be used to calculate the number of turns a unit needs to be 100% healed. An implemenation may be as follows:

PHP:
if (eUnitDomain == DomainTypes.DOMAIN_AIR):
	fCurrStrength 	= float(pUnit.airCurrCombatStr()*0.01)
	fMaxStrength 	= float(pUnit.airMaxCombatStr()*0.01)
else:
	fCurrStrength 	= float(pUnit.baseCombatStr())*float(1.0-pUnit.getDamage()*0.01)
	fMaxStrength 	= float(pUnit.baseCombatStr())		

iTurnsToHeal 	= int((fMaxStrength-fCurrStrength)/float(fMaxStrength*float(mt.getPlotHealFactor(pUnit))*0.01)+0.999) # force to round up


The python used here is very likly not the best possible. As many others here, I learnt python with civ4, allthough I have some years of experience as professional programmer. But this is 10 years away now.
The knowledge about healing in civ4 I gained by try and error and lots of investigations and experiments with a random map and the world builder. There still may be some details about healing not covered by this function, but I think it offers a quite good overview about the civ4 healing details and some python basics.
 
Thats an amazing contribution 12monkeys! Not only excellent code but a great example of how to implement a whole concept in python. Thanks for sharing it!
 
12monkeys, if you set the domain of sea and air units to land while in a city, doesn't that mean that air units will not work as they were created ever again? Because air units by default stay in cities and bomb from there, but as land units, they can move, which is against the "city rule"... Sorry if that's wrong...
 
Also, since it is here...

This piece of code is so simple that I'm not sure if it's even worthy of putting here, but it was my first successful venture into Python, and I'm actually kind of proud of it. :crazyeye:

Code:
	def onLoadGame(self, argsList):
#Displays the "Welcome Back!" Message when a saved game loads.
                        CyInterface().addImmediateMessage("Welcome back!","")
#ENDLoadGame
		return 0

What it does:
This code prints a simple message when the game is loaded, giving a "homely" feel. :D

Use:
Giving your code that extra touch of human emotion.
 
IVZanIV said:
Also, since it is here...

This piece of code is so simple that I'm not sure if it's even worthy of putting here,,,,,

Trust me this is very useful. I started programming pretty much from scratch a month ago just so i could mod python civ files.. It took me a week just to figure out how to put up a message like yours. So hopefully you'll save someone else a week of time... heh.

Heres another useful message contribution that can be used at any interrupt point. IVe found it invaluable when learning python and trying to figure out if my programs are actually working or not:
Code:
myResult = "whatever the heck your trying to test"

CyInterface().addMessage(CyGame().getActivePlayer(),True,10,"%s" %(myResult),'',
1,'',ColorTypes(8),-1,-1,True,True)

What it does: Prints a message thats based on a variable, in this case myResult.

Use: If you got some long complex function that gives no python errors yet doesnt seem to be working it can be frustrating debugging it. This allows you to test if the result your trying to achieve is actually happening in the first place and if so what its value is. Especially good if you got some function that involves lots of math or got some loop error you are trying to track down.
 
IVZanIV said:
12monkeys, if you set the domain of sea and air units to land while in a city, doesn't that mean that air units will not work as they were created ever again? Because air units by default stay in cities and bomb from there, but as land units, they can move, which is against the "city rule"... Sorry if that's wrong...

I don't change the unit itself. I just treat them in the code as land units, to simplify the handling. So there is no problem.
 
naf4ever said:
I started programming pretty much from scratch a month ago just so i could mod python civ files...

Exact same thing for me, and I like it so much now, I don't feel like stopping. :mischief:

12monkeys said:
I don't change the unit itself. I just treat them in the code as land units, to simplify the handling. So there is no problem.

Ah, ok, that makes sense. Thanks.
 
Hey, which file do you write these codes into for them to actually do anything? Do you put them in the CvEventManager.py file only?

This is very useful, iv learnt a lot so far but iv yet to program my first successful python event (mainly due to my fear it will all go badly wrong)

mrkingkong
 
naf4ever said:
Trust me this is very useful. I started programming pretty much from scratch a month ago just so i could mod python civ files.. It took me a week just to figure out how to put up a message like yours. So hopefully you'll save someone else a week of time... heh.

Heres another useful message contribution that can be used at any interrupt point. IVe found it invaluable when learning python and trying to figure out if my programs are actually working or not:
Code:
myResult = "whatever the heck your trying to test"

CyInterface().addMessage(CyGame().getActivePlayer(),True,10,"%s" %(myResult),'',
1,'',ColorTypes(8),-1,-1,True,True)

What it does: Prints a message thats based on a variable, in this case myResult.

Use: If you got some long complex function that gives no python errors yet doesnt seem to be working it can be frustrating debugging it. This allows you to test if the result your trying to achieve is actually happening in the first place and if so what its value is. Especially good if you got some function that involves lots of math or got some loop error you are trying to track down.


naf4ever that is good but this gives you a lot more flexibility.
Basically this is a file almost completely gutted except for the important code and example. Lets call this file CvFoo.py.

Code:
# Import statements
# ...
# ...

# Global variables 
# ...
# ...

# Change this to enable or disable debug messages
g_bDebug = true

LOG_ONLY = 1
SCREEN_ONLY = 2
LOG_AND_SCREEN = 3

# Change to redirect the debug messages to the logs, screen or both.
g_iDebugMessageTarget = LOG_ONLY

class CvFoo:

	def fooBar(self):

		# Debug code - Start
		if(g_bDebug):
			self.printDebugMessage("Hello, World!")
		# Debug code - End		

		return iHangingBodyCount


	# Prints the debug message to the logs, screen or both	
	def printDebugMessage(self, strMessage):
	
		if(g_iDebugMessageTarget == LOG_ONLY):
			CvUtil.pyPrint(strMessage)
		elif(g_iDebugMessageTarget == SCREEN_ONLY):
			CyInterface().addImmediateMessage(strMessage)
		else:
			CvUtil.pyPrint(strMessage)
			CyInterface().addImmediateMessage(strMessage)
 
Top Bottom