Initial Python documentation

Locutus

King of the Collective
Joined
Oct 30, 2001
Messages
365
Location
Hengelo/Enschede, the Netherlands
I posted this on Apolyton here, I figured I'd better post it here as well. If you have any questions for me, I'd prefer you posted them in the Apolyton thread, since Apolyton is much, much faster than CFC and it's my own site, I hang out there every day (and these days every night as well ;)) and it's best to initially keep what little info there is for now in one place as much as possible (I already answered a bunch of questions there which give more info and examples). I'll swing by here a few times as well though.

General
This will just be the start, much more is to follow, but a combination of having to get the scenarios done in time and RL issues made me fall behind schedule a bit.

There are basically 4 ways to use Python:

1) Map generation - there won't be additional documentation for this in the short run, but the existing scripts are well documented so you can learn a lot by studying those. Creating completely new map scripts is not for the faint-of-heart though, some grasp of OO programming and the mathemetical concepts underlying the scripts is required. You can find the mapscripts in the PublicMaps folder
2) UI modding - documentation here isn't really needed, the code is more or less self-explanatory. You can find the UI files in the Assets/Python/Screens folder
3) Events - the most common way in which you will use Python, there are many different applications, not just for your standard scenario events. A list of available events is below. The core event manager is Assets/Python/CvEventManager.py
4) Overrides - some game functions can be overwritten, for example what can be built in what cities, what civics/techs/religions/etc are available to who (all dynamically, so on a case-by-case and turn-by-turn basis, much more powerful than the static XML files), some AI behaviour, Barbarian spawning, victory conditions, etc. These overrides are in Assets/Python/CvGameUtils.py

There are some other very specific Python applications, but those you'll normally not need. In the short run at least, there will be no documentation for them (just give me and the community time though ;))

A note of caution: please do NOT, I repeat, do NOT mess with the Python files in the default Assets folder, this will cause all kinds of problems with future patching, MP play, tournaments, etc. Please use the mod setup that's also used for the in-game scenarios, see the Mods folder. Here you only need to keep the things you add/change, files that remain unchanged you can leave out, the game will just take the version from the default Assets folder for any file it's missing (similar to CtP modding, for those familiar with it -- only this time it actually works). More detailed info will follow but I think most people will be able to figure this out soon enough, it's pretty simple.

API
As any programmer knows, to help you write Python code that actually interacts with the Civ4 engine, rather than just being a stand-alone application, you will need to use a so-called API (Application Programming Interface) -- basically a list of functions you can use to access routines in the game engine. I made a script to extract this info in HTML form from the SDK, but of course you guys don't have the SDK yet, so I'll just have to publish the HTML files. A few isues to keep in mind:

1) My script can only get info from the SDK, while some of the API calls are not in the SDK (game-engine related stuff). I had to add those functions manually and left them mostly undocumented (for now). Classes that have a lot of bright green ??? in them are basically the ones that are not from the SDK.
2) Documentation on what these functions do is pretty poor, I'm working on more complete info. Most of the time the name of the function pretty much tells you what it does though, so this shouldn't keep anyone from using them (it certainly hasn't kept me).
3) This is for a not-quite-final version of the game, there might be some minor changes in the release version but it should be only really minor stuff, if anything changed at all. For an even-closer-but-still-not-quite-final build my script is FUBARed, I'll have to check what goes wrong there, and then ask Soren or Trip to run my script on the release version of the SDK (which I don't have myself either) to get this fully up-to-date (there are no changes to the API itself between these two builds though). For now this version will work absolutely fine though, at least 99.99% of this should still be accurate.
4) Hmm, there was another issue but I forgot. Oh well, I'll update this post when I remember it.

You can browse the API reference here: http://civilization4.net/files/modding/PythonAPI/
A zip version that you can extract and browse on your own PC is here: http://civilization4.net/files/modding/PythonAPI.zip

Events
As promised, the list of events that's available to you in the game (sorry for the poor formatting, I don't have terribly much time today). This was also generated based on source files (with a few notes from myself) for a not-quite-final build, more detailed and final info will follow:

onKbdEvent
'keypress handler - return 1 if the event was consumed'
arguments: eventType,key,mx,my,px,py

onInit
'Called when Civ starts up'
arguments: -

onUpdate
'Called every frame'
arguments: fDeltaTime

onWindowActivation
'Called when the game window activates or deactivates'
arguements: bActive

onUnInit
'Called when Civ shuts down'
arguments: -

onPreSave
"called before a game is actually saved"
arguments: -

onSaveGame
"return the string to be saved - Must be a string"
arguments: -

onLoadGame
-
arguments: -

onGameStart
'Called at the start of the game'
arguments: -

onGameEnd
'Called at the End of the game'
arguments: -

onBeginGameTurn
'Called at the beginning of the end of each turn'
arguments: iGameTurn

onEndGameTurn
'Called at the end of the end of each turn'
arguments: iGameTurn

onBeginPlayerTurn
'Called at the beginning of a players turn'
arguments: iGameTurn, iPlayer

onEndPlayerTurn
'Called at the end of a players turn'
arguments: iGameTurn, iPlayer

onEndTurnReady
-
arguments: iGameTurn

onFirstContact
'Contact'
arguments: iTeamX,iHasMetTeamY

onCombatResult
'Combat Result'
arguments: pWinner,pLoser

onCombatCalc
'Combat Result'
arguments: cdAttacker, cdDefender, iDefenderOdds

onCombatHit
'Combat Message'
cdAttacker, cdDefender, iIsAttacker, iDamage

onImprovementBuilt
'Improvement Built'
arguments: iImprovement, iX, iY

onRouteBuilt
'Route Built' (note: routes = road or railroad)
arguments: iRoute, iX, iY

onPlotRevealed
'Plot Revealed'
arguments: pPlot, iTeam

onBuildingBuilt
'Building Completed' (note: building = improvement or wonder)
arguments: pCity, iBuildingType

onProjectBuilt
'Project Completed' (note: project = space ship part, Appollo Program, 1 or 2 other modern wonders)
arguments: pCity, iProjectType

onUnitMove
'unit move'
arguments: pPlot,pUnit

onUnitSetXY
'units xy coords set manually' (note: i.e. teleport)
arguments: pPlot,pUnit

onUnitCreated
'Unit Completed'
arguments: unit

onUnitBuilt
'Unit Completed'
arguments: city, unit

onUnitKilled
'Unit Killed'
arguments: unit, iAttacker

onUnitLost
'Unit Lost'
arguments: unit

onUnitPromoted
'Unit Promoted'
arguments: pUnit, iPromotion

onUnitSelected
'Unit Selected'
arguments: unit

onUnitRename
'Unit is renamed'
arguments: pUnit

onGoodyReceived
'Goody received'
arguments: iPlayer, pPlot, pUnit, iGoodyType

onGreatPersonBorn
'Unit Promoted' (note: obviously not, should be 'Great Peson Born')
arguments: pUnit, iPlayer, pCity

onTechAcquired
'Tech Acquired'
arguments: iTechType, iTeam, iPlayer, bAnnounce

onTechSelected
'Tech Selected'
arguments: iTechType, iPlayer

onReligionFounded
'Religion Founded'
arguments: iReligion, iFounder

onReligionSpread
'Religion Has Spread to a City'
arguments: iReligion, iOwner, pSpreadCity

onGoldenAge
'Golden Age'
arguments: iPlayer

onEndGoldenAge
'End Golden Age'
arguments: iPlayer

onChangeWar
'War Status Changes'
arguments: bIsWar, iPlayer, iRivalTeam

onChat
'Chat Message Event'
arguments: chatMessage

onSetPlayerAlive
'Set Player Alive Event' (note: either when a player dies or is revived (only in scenarios))
arguments: iPlayerID, bNewValue

onCityBuilt
'City Built'
arguments: city

onCityRazed
'City Razed'
arguments: city, iPlayer

onCityAcquired
'City Acquired'
arguments: owner,playerType,city,bConquest,bTrade

onCityLost
'City Lost'
arguments: city

onCultureExpansion
'City Culture Expansion'
arguments: pCity, iPlayer

onCityGrowth
'City Population Growth'
arguments: pCity, iPlayer

onCityDoTurn
'City Production'
arguments: pCity, iPlayer

onCityBuildingUnit
'City begins building a unit'
arguments: pCity, iUnitType

onCityBuildingBuilding
'City begins building a Building'
arguments: pCity, iBuildingType

onCityRename
'City is renamed'
arguments: pCity

onVictory
'Victory'
arguments: iTeam, iVictory

onGameUpdate
'sample generic event, called on each game turn slice' (note: at least in theory about 4 times per second (didn't test it))
arguments: turnSlice

onMouseEvent
'mouse handler - returns 1 if the event was consumed'

arguments: eventType,mx,my,px,py,interfaceConsumed,screens

Example
Finally, I'll give one simple example of how to use all this code in practice. For more examples, see the Python code in the Mods folder, the various scenarios come with a lot of interesting code.

Code:
def onGameStart(self, argsList):
	'Create a popup message at the start of the game'
	popup = PyPopup.PyPopup()
	popup.setBodyString( 'Hello World' )
	popup.launch()

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)

Note that this example overwrites the existing event code, normally you will want to either append to it, or subclass it (more info on that will follow), for simplicity's sake I didn't do that here.

If anyone has any Python-related questions, I'll try to answer them as best as I can. Again, prefer place to post questions: http://apolyton.net/forums/showthread.php?s=&threadid=140611
 
Thanks, I've been looking for some information on these lines. However I don't see the main thing I would like. I am trying to put a predefined map in the Single player - custom. Instead of the random ones. The purpose is to use the flexiability of that area while playing on Earth. So I have looked around for some sort of command that will allow me plot out the X\Y land for earth in a py file. Do you got any ideas? formulas :p
 
I'm not sure what exactly you're asking, you want to know how to get a plot at certain coordinates? That would be CyGlobalContext().getGame().plot(<someX>, <someY>). That gives you the plot, you can then call all kinds of functions (from CyPlot) on it, for example setPlotType() to change the terrain, setBonusType() to add a resource, etc. Is that what you want?
 
Hey, does anyone have the script that extracts the API from the SDK?

Would be nice to have so we don't have to work with a Vanilla API when trying to write BtS code. :)
 
I'm almost done with my API for BtS. And if I get my extraction script working completly I'll upload it too.
 
Top Bottom