CivPlayer scripting utility

Baldyr

"Hit It"
Joined
Dec 5, 2009
Messages
5,530
Location
Sweden
CivPlayer is a Python module and a Python scripting utility application. Download here.

What does it do?
CivPlayer has two main features:
1. Making handling various player and team values and instances easy to handle.
2. Has built-in support for storing custom data - both player specific and global data.​

How does it work?
CivPlayer is self-contained in the CivPlayer.py file and there are three things you need to do in order to access the included features:
1. Download and install the module in the \Assets\Python\ folder of your mod.
2. Initiate the setup code by adding function calls from the mod's Python event managing structure.
3. Import the module to any other module using it.​
More details in the installation section.

What are the player/team values, then?
In CivIV each player is a CvPlayer instance and those objects are inherited by the Python scripting environment as CyPlayer instances. In order to do just about anything concerning the players with Python, you need to fetch the CyPlayer instance. So you end up doing this often. Very often. Other times you need the player ID - also known at the PlayerType - for various tasks indirectly affecting a player. So you need to get that value also on-the-fly.

Now, this isn't all there is to handling players. Each player also has a Civilization attribute associated with it. And every player is part of a team - these are known as CvTeam instances or CyTeam instances in Python terms. The same goes here; sometimes you need to get hold of the player's CyTeam object, and other times you need to fetch the teamID/TeamType.

CivPlayer wraps all of this up in a easy-to-use package using something called CivPlayer instances. A CivPlayer is basically a collection of all the values and objects associated with one of game's players or Civilizations. As a bonus, the CivPlayer instance also holds a PyPlayer instance for easy-access. PyPlayer is "helper class" found in the PyHelpers module that ships with the game, and it adds some very useful methods not otherwise available with CivIV Python.

What is the advantage of a CivPlayer instance over a CyPlayer and a CyTeam instance?
It's a matter of convenience as it saves time and results in shorter scripts with less repetition. Because even if you wrap up the main methods of fetching the associated instances and index values, you end up calling these functions over and over again.

With a CivPlayer instance, you can just invoke the CivPlayer.get() method for fetching any value on-the-fly. And there are numerous different and convenient ways of getting hold of the CivPlayer instance itself.

Example of use

This is an example of a Python script that makes one player declare war on another. To make it even more delicate, we need to figure out what player has the CivilizationType.CIVILIZATION_RUSSIA. (We're gonna assume that there is only one player with this CivilizationType in the scenario, and that this player is currently alive.)
Spoiler :
Doing this the old-fashioned way would look something like this:
Code:
def declareOnRussia(ePlayer):
	# get the CyTeam of the attacker
	pPlayer = gc.getPlayer(ePlayer)
	eTeam = pPlayer.getTeam()
	pTeam = gc.getTeam(eTeam)
	# get the TeamType of the Russian player
	eCivRussia = gc.getInfoTypeForString("CIVILIZATION_RUSSIA")
	for eCurrentPlayer in gc.getMAX_CIV_PLAYERS():
		pCurrentPlayer = gc.getPlayer(eCurrentPlayer)
		if pCurrentPlayer.getCivilizationType() == eCivRussia:
			ePlayerRussia = eCurrentPlayer
			break
	pPlayerRussia = gc.getPlayer(ePlayerRussia)
	eTeamRussia = pPlayerRussia.getTeam()
	# declare war
	pTeam.declareWar(eTeamRussia, False, WarPlayTypes.NO_WARPLAN)
Phew! It would be possible to condence this script into fewer lines of code, but the logic would remain the same and the resulting script would be less readable.

Now, using CivPlayer it would be as easy as this to achieve the same thing:
Code:
def declareOnRussia(ePlayer):
	# get the CyTeam of the attacker
	pTeam = getCyTeam(ePlayer)
	# get the TeamType of the Russian player
	eTeamRussia = pointer("Russia", teamID)
	# declare war
	pTeam.declareWar(eTeamRussia, False, WarPlayTypes.NO_WARPLAN)
This example uses the so-called Quick-Access Interface for fetching values, so there are no actual CivPlayer instances directly referenced in the code. The following script is another example where actual CivPlayer instances are assigned to local names:
Code:
def declareOnRussia(ePlayer):
	# get the CyTeam of the attacker
	pAttacker = instance(ePlayer)
	pTeam = pAttacker.get(CyTeam)
	# get the TeamType of the Russian player
	pRussia = Civ("Russia")
	eTeam = pRussia.get(teamID)
	# declare war
	pTeam.declareWar(eTeam, False, WarPlayTypes.NO_WARPLAN)

Installation

1. Download and unzip the CivPlayer.py file into your mod's \Assets\Python\ folder.
2a. With a standard Beyond the Sword setup, add the color coded code into the CvEventManager.py file:
Spoiler :
Code:
from CvPythonExtensions import *
import CvUtil
import CvScreensInterface
import CvDebugTools
import CvWBPopups
import PyHelpers
import Popup as PyPopup
import CvCameraControls
import CvTopCivs
import sys
import CvWorldBuilderScreen
import CvAdvisorUtils
import CvTechChooser

[COLOR="Red"]import CivPlayer[/COLOR]

gc = CyGlobalContext()
localText = CyTranslator()
PyPlayer = PyHelpers.PyPlayer
PyInfo = PyHelpers.PyInfo
Code:
	def onLoadGame(self, argsList):
		CvAdvisorUtils.resetNoLiberateCities()

		[COLOR="Red"]CivPlayer.setupCivPlayer()[/COLOR]

		return 0
Code:
	def onGameStart(self, argsList):
		'Called at the start of the game'

		[COLOR="Red"]CivPlayer.setupCivPlayer()[/COLOR]
2b. If you want to be able to use the built-in data storage features, also add these function calls:
Spoiler :
Code:
	def onPreSave(self, argsList):
		"called before a game is actually saved"

		[COLOR="Red"]CivPlayer.storeData()[/COLOR]

		CvUtil.pyPrint('OnPreSave')
Code:
	def onLoadGame(self, argsList):
		CvAdvisorUtils.resetNoLiberateCities()

		CivPlayer.setupCivPlayer()
		[COLOR="Red"]CivPlayer.retrieveData()[/COLOR]

		return 0
3. Add this line into any module where you wanna be able to access the features of CivPlayer:
Spoiler :
Code:
[COLOR="Red"]from CivPlayer import *[/COLOR]
 
Application Programming Interface

This API section details the various parts of CivPlayer. Each function/method entry consists of a return value type (or several) within brackets, followed by the function name and the available arguments within parenthesis. Arguments are separated by a comma and each argument consists of a type and a name.

Quick-Access Interface
The functions access a global dictionary of CivPlayer instances - without the need to ever create one. The instances are created at startup and ready-to-use at any time. The functions aren't part of any class.
[ CivPlayer ] Civ ( str name )
Returns a ready-to-use CivPlayer class instance for use with instance methods. The name argument
(string) refers to the short form av the Civilization name of the player associated with it.

[ PlayerType, CyPlayer, TeamType, CyTeam, PyPlayer, CivilizationType ] pointer ( str name, int iIndex )
Wraps up the Civ() function and the CivPlayer.get() method into a coherent, easy-to-use
multipurpose function. There are two arguments; name (string) and iIndex (integer).
They refer to the Civilization name short form and the type of reference being requested.
The valid iIndex values are 0-5 but the these names can be used for convenience:
playerID, CyPlayer, teamID, CyTeam, PyPlayer, civID

[ CivPlayer ] instance ( int ePlayer )
Returns a ready-to-use CivPlayer class instances from a index. The ePlayer argument (integer) is
used for indexing. If the argument is invalid the function returns the CivPlayer instance of the
Barbarian player.

[ CivPlayer ] getHuman ( )
Returns the CivPlayer instance of the (current) human player.

[ CyPlayer ] getCyPlayer ( int ePlayer )
Returns the CyPlayer instance corresponding the ePlayer (integer) argument.

[ TeamType ] getTeamID ( int ePlayer)
Returns the TeamType (integer) value of the PlayerType corresponding to the ePlayer (integer) argument.

[ CyTeam ] getCyTeam ( int ePlayer )
Returns the CyTeam instance of the PlayerType corresponding to the ePlayer (integer) argument.

[ PyPlayer ] getPyPlayer ( int ePlayer )
Returns the a PyPlayer instance (from the PyHelpers module) for the ePlayer (integer) argument.

[ CivilizationType ] getCivID ( int ePlayer )
Returns the CivilizationType (integer) value of the PlayerType corresponding to the ePlayer (integer)
argument.
CivPlayer Instance Methods
Each instance of the class represents one player and wraps up all the common player/team references,
including PyPlayer and the CivilizationType. The class also supports storage of arbitrary custom data
with each instance. All methods need to be invoked on a valid CivPlayer instance, not merely the CivPlayer class.
[ None ] __init__ ( int ePlayer )
A new instance of the class in created with the constructor CivPlayer(ePlayer) where ePlayer is a valid
player ID (integer). Note however that it shouldn't be necessary to manually create new instances if the
application has been setup properly, since instances for all players should
already be available for use.

[ PlayerType, CyPlayer, TeamType, CyTeam, PyPlayer, CivilizationType ] get ( int iIndex )
This method is used internally with valid CivPlayer instances to fetch player references. The valid iIndex
values 0-5 are themselves referenced by the names:
playerID, CyPlayer, teamID, CyTeam, PyPlayer, civID

[ str ] getName ( bLong=None )
Returns the Civilization name (string) in it's adjective form by default. By setting the optional bLong
parameter to True the method will instead return the full civilization name, and a False value will in
turn return the short form.

[ bool ] isAlive ( )
Wraps up the CyPlayer.isAlive() method for convenience.

[ bool ] isVassal ( )
Returns True if the player has is currently in any vassal state agreement. Otherwise returns False.

[ bool ] isWartime ( )
Returns True if the player's team is current at war with any team of major players. Otherwise returns False.

[ UnitType ] getConscriptUnit ( )
Returns the UnitType (integer) that would be available in the player's capital - no matter if conscription
is enabled or not at the given time.

[ None ] setData ( str key, varies value )
Used to store custom player data in a dictionary. The key parameter (string) is the identifier or the name
of the value, and the value parameter is the value itself to be stored. Note that no Cy class instances can
be stored as data!

[ varies ] getData ( str key )
Fetches the value corresponding to the key name (string).

[ dict ] getScriptDict ( )
Fetches the entire player dictionary. No parameters are used. Method used for internal operations; the public
methods are CivPlayer.setData() and CivPlayer.getData() above.
CivPlayer Class Methods
These methods wrap up a global dictionary of CivPlayer instances created on initialization.
They are invoked directly on the class - not on instances of the class.
The parameter name (string) must be the short form of the Civilizations name of a valid scenario player.
[ generator ] getPlayers ( bool bMajor=False, int iIndex=None )
Used for iterating CivPlayer instances from the global index. Dead players and the Barbarian player are always
excluded, but setting the optional bMajor parameter to True will also exclude any Minor players. The method
can also be used for automatically accessing the CivPlayer.get() method with the second iIndex parameter.

[ generator ] getCivs ( str name, int iIndex=None )
Used for iterating CivPlayer instances from the global index corresponding to the name (string) CivilizationType.
Dead players are always excluded. The method can also be used for automatically accessing the CivPlayer.get()
method with the second iIndex parameter.

[ int ] getNumCivs ( str name )
Returns the number (integer) of alive players with the CivilizationType corresponding to the name (string) parameter.

[ list ] getCivList ( str name )
Returns a list of CivPlayer intances of all alive players with the CivilizationType corresponding to the name (string)
parameter.

[ bool ] isCiv ( str name, int ePlayer )
Returns True if the name (string) parameter corresponds to the CivilizationType of the PlayerType corresponding to
the ePlayer (integer) parameter. Otherwise returns False.

[ bool ] isCivAlive ( str name )
Returns True if any alive player's CivilizationType corresponds to the name (string) parameter. Otherwise returns False.

[ bool ] isCivCulture ( str name, CyPlot pPlot )
Returns True if the name (string) corresponds to any PlayerType's CivilizationType attribute who's culture reaches
pPlot (CyPlot intance). Otherwise returns False.

[ bool ] isCivOwned ( str name, CyPlot pPlot )
Returns True if the name (string) corresponds to the CivilizationType of the owner of pPlot (CyPlot instance).
Otherwise returns False.

[ bool ] isCivContact ( str name, CyTeam pTeam )
Returns True if any of the players of pTeam (CyTeam instance) has met any of the players of any of the teams that include
a player with the CivilizationType attribute corresponding to the name (string) parameter. Otherwise returns False.

[ PlayerType ] playerID ( str name )
Returns the enumerated player index number (integer) belonging to the name (string) Civilization.

[ CyPlayer ] CyPlayer ( str name )
Returns a CyPlayer class instance of the player connected to the name (string) CivilizationType.

[ TeamType ] teamID ( str name )
Returns the enumerated team index number (integer) that the name (string) PlayerType is associated with.

[ CyTeam ] CyTeam ( str name )
Returns the CyTeam class instance of the team connected to the name (string) CivilizationType.

[ PyPlayer ] PyPlayer ( str name )
Returns a PyPlayer class instance as defined in the PyHelpers module. The whole range of PyPlayer methods are available
through this reference!
Data Storage Interface
These functions wrap up all the essential operations for storing and retrieving custom data. They don't belong to any class and are not invoked on any.
The storeData() and retrieveData() functions need to be hooked up with game events in order for the data storage to work with save/load games.
The rest of the functions are divided into global and player specific operations.
[ None ] storeData ( )
To be called at the onPreSave event to store all data with the save game.

[ None ] retrieveData ( )
To be called at the OnLoad event to retrieve all data from the save game.

[ None ] setPlayerData ( int ePlayer, str key, varies value )
Used to store a custom value (any type) identified by key (string) for the PlayerType corresponding to ePlayer (integer).

[ varies ] getPlayerData ( int ePlayer, str key )
Used to retrieve the stored value for the PlayerType corresponding to ePlayer (integer) identified by key (string).

[ dict ] getPlayerScriptDict ( int ePlayer )
Returns the whole dictionary of keys and values for the PlayerType identified as ePlayer (integer). Intended for internal
use only.

[ None ] setGlobalData ( varies value )
Used to store a custom value (any type) identified by key (string).

[ varies ] getGlobalData ( str key )
Used to retrieve the stored value identfied by key (string).

[ dict ] getGlobalScriptDict ( )
Returns the whole dictionary of keys and values not specific to any PlayerTypes. Intended for internal use only.
Miscellenous Operations
When adding new players to the game at runtime use the addPlayer() function to initiate the new CivPlayer and add it to its class.
[ None ] addPlayer ( int ePlayer )
Initiates a new CivPlayer instance, adds it to the global array of instances and initiates the associated DataStorage instance.
 
Notes

Functions, Class Methods and Instance Methods

First off; a "function" doesn't belong to any "class". The input values used in the function call are called "arguments". Syntax:
Code:
function(argument)
"Methods", on the other hand, are functions belonging to a class, and the arguments are called "parameters". All methods are "invoked" on a class or an instance of a class using "dot notation". Syntax:
Code:
class.method(parameter)
Now, there is a difference between class methods and instance methods, both belonging to the same class. A class method is simply invoked on the name of the class. Example:
Code:
CivPlayer.getCivs("Russia")
The class name here is "CivPlayer", while "getCivs" is the name of the method and the string "Russia" is the parameter.

A instance method, on the other hand, is invoked on an instance of the class. Examples:
Code:
Civ("Russia").isAlive()
Code:
instance(2).isCiv("Russia")
Because the Civ() och instance() functions return CivPlayer instances associated with CivilizationTypes and PlayerTypes respectively.

Several players with the same CivilizationType

CivPlayer can be used both with scenarios that has a fixed set of players with their corresponding CivilizationTypes, and with scenarios with several players with the same CivilizationType. But it can also be used with mods that aren't based on a set scenario. The usage will, of course, differ.

When there are (potentially) several players with the same CivilizationType it makes little sense to use methods that take a Civilization name and returns a single value. Because you might need to fetch several values. This is what the class methods CivPlayer.getCivs() and CivPlayer.getCivList() are intended to be used for. The CivPlayer instances yielded/returned can then be used with all the instance methods.

Examples:
Spoiler :
Code:
for pCivPlayer in CivPlayer.getCivs():
	if pCivPlayer.isWartime():
		print pCivPlayer.getName(False) + " is at war!"
Code:
for pCivPlayer in CivPlayer.getCivList():
	if pCivPlayer.isVassal(pRussiaTeam):
		print pCivPlayer.getName(False) 0 " is a Russian vassal."
The number of players of a specific CivilizationType can be fetched with CivPlayer.getNumCivs() and it is possible to check PlayerTypes against CivilizationTypes with CivPlayer.isCiv(). See the API section for more class methods.

Initiate CivPlayer on reload

Working with Python is very practical since it is possible to edit Python modules while the game is running. Any time you save a .py file and switch back to the game, all Python is being reloaded.

But this is actually a issue with CivPlayer, as the CivPlayer instances that were setup during game start/load has expired! Any code utilizing this application will cease to work until you reload a save or start a new game...

There is, however, a easy fix for this:
Spoiler :
Add this code at the bottom of CvEventManager:
Code:
if gc.getGame().isFinalInitialized():
	CivPlayer.setupCivPlayer()
Now CivPlayer will automatically rebuild all instances any time Python is reloaded during a game!
 
Sample script
This is some of the code I wrote for the Glory & Greatness mod, adding Unique Powers for various Civilizations. Working on this mod actually resulted in the CivPlayer module as a side-effect. I've been using it in other project also, like scripting Python for Jamie's Rome mod. I believe utilizing CivPlayer results in clear and concise code.
PHP:
### main functions - called from CvEventManager/CvGameUtils

def startingCivics(ePlayer, eCivic):
        """
        Enable Civic type from start.
        """
        for name, eStartingCivic in startingCivicDict.iteritems():
                if CivPlayer.isCiv(name, ePlayer) and eCivic == eStartingCivic:
                        return True
        return False

def aztecGold(pUnit, ePlayer):
        """
        Gold for units killed based on experience of unit.
        """
        if CivPlayer.isCiv("Aztec", ePlayer):
                iExperience = pUnit.getExperience()
                iGoldReward = iAztecBaseGold + iExperience * iAztecGoldDenominator
                getCyPlayer(ePlayer).changeGold(iGoldReward)

def carthageVassals(ePlayer):
        """
        Extra gold and Great General points for vassals.
        """
        if not CivPlayer.isCivAlive("Carthage"): return
        pVassalCiv = instance(ePlayer)
        for pMasterCiv in CivPlayer.getCivs("Carthage"):
                if pMasterCiv.get(CyTeam).isVassal(pVassalCiv.get(teamID)):
                        pVassalCiv.get(CyPlayer).changeCombatExperience(iCarthageVassalXP)
                        iGold = pVassalCiv.get(CyPlayer).getGold()
                        iBonusGold = max(1, min(iCarthageVassalGold, iGold / iCarthageVassalGold))
                        grantGold(ePlayer, iBonusGold)
                        break

def colombiaOccupation(pCity, ePlayer, bConquest):
        """
        No Revolting in Captured cities.
        """
        if bConquest and CivPlayer.isCiv("Gran Colombia", ePlayer):
                pCity.setOccupationTimer(0)

def germanyCapture(pWinningUnit, pLosingUnit):
        """
        50 percent chance to capture barbarian units and get gold reward.
        """
        ePlayer = pWinningUnit.getOwner()
        if ( CivPlayer.isCiv("Germany", ePlayer)
             and pLosingUnit.getDomainType() == eLand
             and pLosingUnit.getOwner() == eBarbarian
             and isProbabilityPercent(iGermanProbability, "germany") ):
                captureUnit(ePlayer, pWinningUnit, pLosingUnit)
                grantGold(ePlayer, iGermanGold)
                tStrings = instance(pLosingUnit.getOwner()).getName(), getDescription(pLosingUnit)
                addMessage(germanCaptureMessage, tStrings, ePlayer, tCoords=getCoords(pLosingUnit))

def germanyConscription(pCity):
        """
        No Unhappiness for Drafting.
        """
        eOwner = pCity.getOwner()
        if CivPlayer.isCiv("Germany", eOwner):
                iConscriptTimer = pCity.getConscriptAngerTimer()
                if iConscriptTimer:
                        pCity.changeConscriptAngerTimer(-iConscriptTimer)

def englandMovement():
        """
        +1 Movement to Ships.
        """
        for pTeam in CivPlayer.getCivs("England", CyTeam):
                pTeam.changeExtraMoves(eSea, iEnglandMoves)

def holyRomeTech(eTech, ePlayer):
        """
        Free Tech in the Classical and Renaissance Eras.
        """
        if not CivPlayer.isCiv("Holy Rome", ePlayer): return
        pCivPlayer = instance(ePlayer)
        lHolyRomanEras = pCivPlayer.getData("lFreeTechEras")
        eTechEra = gc.getTechInfo(eTech).getEra()
        ePlayerEra = pCivPlayer.get(CyPlayer).getCurrentEra()
        if lHolyRomanEras[eTechEra]:
                lHolyRomanEras[eTechEra] = None
                giveFreeTech(pCivPlayer.get(CyPlayer))
        
def indiaPopulation(pCity):
        """
        Cities Start with 2 population.
        """
        eOwner = pCity.getOwner()
        if CivPlayer.isCiv("India", eOwner):
                pCity.setPopulation(iIndiaCitySize)

def indiaGrowth(pCity, ePlayer):
        """
        Extra food on city growth.
        """
        if CivPlayer.isCiv("India", ePlayer):
                iFoodOverflow = pCity.getFood()
                iFoodBarSize = pCity.getPopulation() * 2 + 20
                iFoodSurplus = int(iFoodBarSize * iIndiaSurplusPercent / 100.0)
                pCity.changeFood(iFoodOverflow + iFoodSurplus)

def japanHeal(pUnit):
        """
        20 percent chance for a unit to heal fully after combat victory.
        """
        if CivPlayer.isCiv("Japan", pUnit.getOwner()) and isProbabilityPercent(iJapaneseProbability, "japan"):
                pUnit.setDamage(0, False)

def japanCulture(pUnit):
        """
        Units killed in borders add to city culture.
        """
        eOwner = pUnit.getOwner()
        if CivPlayer.isCiv("Japan", eOwner) and pUnit.plot().getOwner() == eOwner :
                iX, iY = pUnit.getX(), pUnit.getY()
                eTeam = getTeamID(eOwner)
                pCity = Map.findCity(iX, iY, eOwner, eTeam, True, False, -1, eNoDirection, CyCity())
                iCulture = iJapaneseBaseCulture + pUnit.getExperience() * iJapaneseCultureDenominator
                pCity.changeCulture(eOwner, iCulture, True)
                print ("***\nPower: Japan (Culture)\nUnit: %s, City: %s, XP: %d, Culture: %d\n***"
                       % (getDescription(pUnit), pCity.getName(), pUnit.getExperience(), iCulture))

def maliTech(pCity):
        """
        Can Select a Free Technology to start the game.
        """
        ePlayer = pCity.getOwner()
        pPlayer = getCyPlayer(ePlayer)
        if ( CivPlayer.isCiv("Mali", ePlayer)
             and not getPlayerData(ePlayer, "bFreeTechGiven") ):
                setPlayerData(ePlayer, "bFreeTechGiven", True)
                giveFreeTech(pPlayer, maliTechMessage)

def mayaEnslave(pWinningUnit, pLosingUnit):
        """
        Enslave - 25 percent chance to get a Worker unit any time a land unit is defeated in combat.
        """
        ePlayer = pWinningUnit.getOwner()
        if ( CivPlayer.isCiv("Maya", ePlayer)
             and pLosingUnit.getDomainType() == eLand
             and isProbabilityPercent(iMayanProbability, "maya")
             and pLosingUnit.getUnitType() >= eWarrior ):
                spawnUnit(ePlayer, pWinningUnit.getX(), pWinningUnit.getY())
                loserAdjective = instance(pWinningUnit.getOwner()).getName()
                tCaptureCoords = getCoords(pWinningUnit)
                addMessage(mayaEnslaveMessage, (loserAdjective,), ePlayer, tCoords=tCaptureCoords)
                addMessage(mayaVictimMessage, (getDescription(pLosingUnit),), pLosingUnit.getOwner(), eRed, tCaptureCoords)

def netherlandsInterest():
        """
        Receive 3 percent interest on gold reserves each game turn (rounded down).
        """
        for pPlayer in CivPlayer.getCivs("Netherlands", CyPlayer):
                if not pPlayer.isAlive(): return
                pPlayer.setGold(int(pPlayer.getGold() * ((iNetherlandsInterest + 100) / 100.0)))

def ottomanCapture(pWinningUnit, pLosingUnit):
        """
        5O percent chance to capture enemy ships and earn gold.
        """
        ePlayer = pWinningUnit.getOwner()
        if ( CivPlayer.isCiv("Ottomans", ePlayer)
             and pLosingUnit.getDomainType() == eSea
             and isProbabilityPercent(iOttomanProbability, "ottoman") ):
                captureUnit(ePlayer, pWinningUnit, pLosingUnit)
                grantGold(ePlayer, iOttomanGold)
                captured = getDescription(pLosingUnit)
                tStrings = getDescription(pWinningUnit), instance(pLosingUnit.getOwner()).getName(), captured
                tCaptureCoords = getCoords(pWinningUnit)
                addMessage(ottomanCaptureMessage, tStrings, ePlayer, tCoords=tCaptureCoords)
                addMessage(ottomanVictimMessage, (captured,), pLosingUnit.getOwner(), eColor=eRed, tCoords=tCaptureCoords)

def ottomanCulture(pCity, ePlayer, bConquest):
        """
        Spread culture in conquered cities.
        """
        if bConquest and CivPlayer.isCiv("Ottomans", ePlayer):
                iTotalCulture = pCity.countTotalCultureTimes100()
                iOttomanCulture = iTotalCulture * iOttomanCulturePercent / 100
                pCity.changeCultureTimes100(ePlayer, iOttomanCulture, True)

def persiaMovement(ePlayer, bActive):
        """
        All land and sea units gain one extra movement point during Golden Ages.
        """
        if not CivPlayer.isCiv("Persia", ePlayer): return
        iExtraMoves = iPersianMoves
        if not bActive:
                iExtraMoves = - iExtraMoves
        for eDomain in tPersianDomains:
                instance(ePlayer).get(CyTeam).changeExtraMoves(eDomain, iExtraMoves)

def romeBuildings(eBuilding, ePlayer):
        """
        +25 percent production of buildings already built in the capital.
        """
        if ( CivPlayer.isCiv("Rome", ePlayer)
             and getCyPlayer(ePlayer).getCapitalCity().isHasBuilding(eBuilding) ):
                return 100 - iRomanConstructionDiscount
        return -1

def romeUpgrade(ePlayer, iUnitID, eUnitType):
        """
        -50 percent cost to upgrade units.
        """
        if CivPlayer.isCiv("Rome", ePlayer):
                iOldUnitTypeCost = getProductionCost(getCyPlayer(ePlayer).getUnit(iUnitID).getUnitType())
                iNewUnitTypeCost = getProductionCost(eUnitType)
                iCostDifference = max(0, iNewUnitTypeCost - iOldUnitTypeCost)
                iDefaultUpgradePrice = iBaseUpgradeCost + iCostDifference * iUpgradeCostPerProduction
                return int(iDefaultUpgradePrice * (100 - iRomanUpgradeDiscount) / 100.0)
        return -1
                
def russiaDamage(pUnit, pPlot):
        """
        Enemy units in Russian territory take damage when either moving or fighting.
        """
        eUnitOwner, ePlotOwner = pUnit.getOwner(), pPlot.getOwner()
        if ( CivPlayer.isCivAlive("Russia")
             and not eUnitOwner == ePlotOwner
             and CivPlayer.isCiv("Russia", ePlotOwner)
             and isAtWar(ePlotOwner, eUnitOwner) ):
                if pUnit.movesLeft() == 0:
                        pUnit.changeDamage(iRussiaDamage, -1)

def scandinaviaPillage(iPillageGold, pUnit):
        """
        Double Gold from pillaging.
        """
        if CivPlayer.isCiv("Scandinavia", pUnit.getOwner()):
                return int(iPillageGold + iPillageGold * iScandinaviaBonusPercent / 100.0)
        return iPillageGold

def spainGoody(ePlayer, eGoody):
        """
        Extra Gold from Goody Huts.
        """
        if CivPlayer.isCiv("Spain", ePlayer):
                iScope = iSpainGoldBonus / 2
                iBonanza = Game.getSorenRandNum(iScope, "bonanza") + iScope + 1
                grantGold(ePlayer, iBonanza)
                capitalName = getCyPlayer(ePlayer).getCapitalCity().getName()
                pHumanCiv = getHuman()
                if pHumanCiv.get(playerID) == ePlayer or pHumanCiv.get(CyTeam).isHasMet(getTeamID(ePlayer)):
                        addMessage(spainGoodyMessage, (capitalName,))
                        
def mongoliaTech(eOldOwner, eNewOwner, bConquest):
        """
        Tech by conquest.
        """
        if not bConquest: return
        if CivPlayer.isCiv("Mongolia", eNewOwner):
                pMongoliaTeam = getCyTeam(eNewOwner)
                pOtherTeam = getCyTeam(eOldOwner)
                for eTech in range(gc.getNumTechInfos()):
                        if pOtherTeam.isHasTech(eTech) and not pMongoliaTeam.isHasTech(eTech):
                                pMongoliaTeam.setHasTech(eTech, True, eNewOwner, False, False)
                                addMessage(mongolTechMessage, (gc.getTechInfo(eTech).getDescription(),), eNewOwner)
                                break
 
good to see this finally realeased! we used this for my mod and it is great :p

edit: does this have anything my version doesn't?
 
does this have anything my version doesn't?
I actually don't know. :dunno: You could try the release version and see what happens, but you might wanna back-up the current (working) version.
 
Wow, this download actually was the best tutorial on the python interface that I have seen so far!

I might use it. I will definetely give you credit for my mod [ in development ].
 
Top Bottom