Python Callbacks

Arian

No more ghostbusting!!
Joined
May 10, 2008
Messages
2,088
Location
The Netherlands
I just upgraded my mod from BUG 3.6 to BUG 4.2. All went fine except the Python Callbacks don't work anymore. After talking to EF, I post my files here:

Here's the stripped ANDGameUtils.py. All default functions are removed. They are ofcourse still in the original BTS CvGameUtils.py.
Spoiler :
Code:
## Sid Meier's Civilization 4
## Copyright Firaxis Games 2005
##
## Implementaion of miscellaneous game functions

import CvUtil
from CvPythonExtensions import *
import CvEventInterface

# globals
gc = CyGlobalContext()

class CvGameUtils:
	"Miscellaneous game functions"
	
	def canDeclareWar(self,argsList):
		iAttackingTeam, iDefendingTeam = argsList

## Tesla Start ##

		pTeam = gc.getPlayer(iAttackingTeam)

		b_Tesla = gc.getInfoTypeForString("BUILDING_TESLA")
		obsoleteTech = gc.getBuildingInfo(b_Tesla).getObsoleteTech()

		if ( gc.getTeam(pTeam.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
			for iCity in range(pTeam.getNumCities()):
				ppCity = pTeam.getCity(iCity)
				if ppCity.getNumActiveBuilding(b_Tesla) == true:
					return False

## Tesla End ##

		return True

	def cannotConstruct(self,argsList):
		pCity = argsList[0]
		eBuilding = argsList[1]
		bContinue = argsList[2]
		bTestVisible = argsList[3]
		bIgnoreCost = argsList[4]

		### Petra Mod begins ###
		### Note: the code identifies the first building of a certain buildingclass in the CIV4BuildingInfos.xml file to be the default building
		###########################################################################################

		### find buildings with the same buildingClassType ###
		lgleicheBC = []
		buildingClassType = gc.getBuildingInfo(eBuilding).getBuildingClassType()
		for i in range(gc.getNumBuildingInfos()):
			if ( buildingClassType == gc.getBuildingInfo(i).getBuildingClassType() ):
				lgleicheBC.append(i)

		if ( len(lgleicheBC) >= 2 ):
			### is eBuilding the default building? ###
			if ( eBuilding == lgleicheBC[0] ):
				### do you have a "foreign" UB in the city? ###
				for i in range(len(lgleicheBC)-1):
					if ( pCity.getNumActiveBuilding(lgleicheBC[i +1])==true ):
						return True

		###########################################################################################
		### Petra Mod ends ###

		### MachuPicchu Mod begins ###
		###########################################################################################

		if ( eBuilding == gc.getInfoTypeForString("BUILDING_MACHU_PICCHU") ):

			### find peaks within the city radius controlled by your team ###
			pPlayer = gc.getPlayer(pCity.plot().getOwner())
			iPID = pPlayer.getID()
			iTID = pPlayer.getTeam()
			iX = pCity.getX()
			iY = pCity.getY()
			for iXLoop in range(iX - 2, iX + 3, 1):
				for iYLoop in range(iY - 2, iY + 3, 1):
					pPlot = CyMap().plot(iXLoop, iYLoop)
					if ( pPlot.isPlayerCityRadius(iPID)==true ):
						if ( pPlot.getTeam()==iTID ):
							if ( pPlot.isPeak()==true  ):
								return False
			return True

		###########################################################################################
		### MachuPicchu Mod ends ###

		### Inuksuk begins ###
		###########################################################################################

		if ( eBuilding == gc.getInfoTypeForString("BUILDING_INUKSUK") ):

			### find tundra or ice within the city radius controlled by your team ###
			pPlayer = gc.getPlayer(pCity.plot().getOwner())
			iPID = pPlayer.getID()
			iTID = pPlayer.getTeam()
			iX = pCity.getX()
			iY = pCity.getY()
			for iXLoop in range(iX - 2, iX + 3, 1):
				for iYLoop in range(iY - 2, iY + 3, 1):
					pPlot = CyMap().plot(iXLoop, iYLoop)
					if pPlot.isNone() == False:
						if ( pPlot.isPlayerCityRadius(iPID)==true ):
							if ( pPlot.getTeam()==iTID ):
								if ( pPlot.getTerrainType() == gc.getInfoTypeForString('TERRAIN_TUNDRA') or pPlot.getTerrainType() == gc.getInfoTypeForString('TERRAIN_SNOW') ):
									return False
			return True

		###########################################################################################
		### Inuksuk ends ###

                ### Kharbas Caves begins ###
		###########################################################################################

		if ( eBuilding == gc.getInfoTypeForString("BUILDING_KHARBAS") ):

			### find deserthills within the city radius controlled by your team ###
			pPlayer = gc.getPlayer(pCity.plot().getOwner())
			iPID = pPlayer.getID()
			iTID = pPlayer.getTeam()
			iX = pCity.getX()
			iY = pCity.getY()
			for iXLoop in range(iX - 2, iX + 3, 1):
				for iYLoop in range(iY - 2, iY + 3, 1):
					pPlot = CyMap().plot(iXLoop, iYLoop)
					if pPlot.isNone() == False:
						if ( pPlot.isPlayerCityRadius(iPID)==true ):
							if ( pPlot.getTeam()==iTID ):
								if ( pPlot.getTerrainType() == gc.getInfoTypeForString('TERRAIN_DESERT') and pPlot.isHills()==true  ):
									return False
			return True

		###########################################################################################
		### Kharbas Caves ends ###

                ### Singing Fountain begins ###
		###########################################################################################

		if ( eBuilding == gc.getInfoTypeForString("BUILDING_SINGINGFOUNTAIN") ):

			### find hill within the city radius controlled by your team ###
			pPlayer = gc.getPlayer(pCity.plot().getOwner())
			iPID = pPlayer.getID()
			iTID = pPlayer.getTeam()
			iX = pCity.getX()
			iY = pCity.getY()
			for iXLoop in range(iX - 2, iX + 3, 1):
				for iYLoop in range(iY - 2, iY + 3, 1):
					pPlot = CyMap().plot(iXLoop, iYLoop)
					if ( pPlot.isPlayerCityRadius(iPID)==true ):
						if ( pPlot.getTeam()==iTID ):
							if ( pPlot.isHills()==true  ):
								return False
			return True

		###########################################################################################
		### Singing Fountain ends ###

		### Djenne Start ###

		if ( eBuilding == gc.getInfoTypeForString("BUILDING_DJENNE") ):

			pPlayer = gc.getPlayer(pCity.plot().getOwner())
			iPID = pPlayer.getID()
			iTID = pPlayer.getTeam()
			iX = pCity.getX()
			iY = pCity.getY()
			tt_desert = gc.getInfoTypeForString( 'TERRAIN_DESERT' )

			for iXLoop in range(iX - 2, iX + 3, 1):
				for iYLoop in range(iY - 2, iY + 3, 1):
					pPlot = CyMap().plot(iXLoop, iYLoop)
					if ( pPlot.isPlayerCityRadius(iPID)==true ):
						if ( pPlot.getTeam()==iTID ):
							if ( pPlot.getTerrainType()==tt_desert ):
								return False
			return True

		### Djenne End ###

		### Ice Hotel Start ###

		if ( eBuilding == gc.getInfoTypeForString("BUILDING_ICE_HOTEL") ):

			pPlayer = gc.getPlayer(pCity.plot().getOwner())
			iPID = pPlayer.getID()
			iTID = pPlayer.getTeam()
			iX = pCity.getX()
			iY = pCity.getY()
			tt_desert = gc.getInfoTypeForString( 'TERRAIN_SNOW' )

			for iXLoop in range(iX - 2, iX + 3, 1):
				for iYLoop in range(iY - 2, iY + 3, 1):
					pPlot = CyMap().plot(iXLoop, iYLoop)
					if ( pPlot.isPlayerCityRadius(iPID)==true ):
						if ( pPlot.getTeam()==iTID ):
							if ( pPlot.getTerrainType()==tt_desert ):
								return False
			return True

            ### Ice Hotel End ###
		
		return False


	def canMaintain(self,argsList):
		pCity = argsList[0]
		eProcess = argsList[1]
		bContinue = argsList[2]

## Troyes Start ##

		pPlayer = gc.getPlayer(pCity.getOwner())

		b_Troyes = gc.getInfoTypeForString("BUILDING_TROYES")
		obsoleteTech = gc.getBuildingInfo(b_Troyes).getObsoleteTech()

		if ( eProcess == gc.getInfoTypeForString("PROCESS_WEALTH2") ) or ( eProcess == gc.getInfoTypeForString("PROCESS_CULTURE2") ):
			if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
				for iCity in range(pPlayer.getNumCities()):
					ppCity = pPlayer.getCity(iCity)
					if ppCity.getNumActiveBuilding(b_Troyes) == true:
						return True

## Troyes End ##

		return False

	def cannotMaintain(self,argsList):
		pCity = argsList[0]
		eProcess = argsList[1]
		bContinue = argsList[2]

## Troyes Start ##

		pPlayer = gc.getPlayer(pCity.getOwner())

		b_Troyes = gc.getInfoTypeForString("BUILDING_TROYES")
		obsoleteTech = gc.getBuildingInfo(b_Troyes).getObsoleteTech()

		if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
			for iCity in range(pPlayer.getNumCities()):
				ppCity = pPlayer.getCity(iCity)
				if ppCity.getNumActiveBuilding(b_Troyes) == true:
					if ( eProcess == gc.getInfoTypeForString("PROCESS_WEALTH") ) or ( eProcess == gc.getInfoTypeForString("PROCESS_CULTURE") ):
						return True


		if ( eProcess == gc.getInfoTypeForString("PROCESS_WEALTH2") ) or ( eProcess == gc.getInfoTypeForString("PROCESS_CULTURE2") ):
			if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
				for iCity in range(pPlayer.getNumCities()):
					ppCity = pPlayer.getCity(iCity)
					if ppCity.getNumActiveBuilding(b_Troyes) == false:
						return true
			if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == true or obsoleteTech == 1 ):
				return True
			
## Troyes End ##

		return False
	
	def doPillageGold(self, argsList):
		"controls the gold result of pillaging"
		pPlot = argsList[0]
		pUnit = argsList[1]
		
		iPillageGold = 0
		iPillageGold = CyGame().getSorenRandNum(gc.getImprovementInfo(pPlot.getImprovementType()).getPillageGold(), "Pillage Gold 1")
		iPillageGold += CyGame().getSorenRandNum(gc.getImprovementInfo(pPlot.getImprovementType()).getPillageGold(), "Pillage Gold 2")

		iPillageGold += (pUnit.getPillageChange() * iPillageGold) / 100

## Himeji Samurai Castle Start ##

		pPlayer = gc.getPlayer( pUnit.getOwner( ) )
		pPlayer2 = gc.getPlayer( pPlot.getOwner( ) )

		b_Himeji = gc.getInfoTypeForString("BUILDING_HIMEJI_CASTLE")
		obsoleteTech = gc.getBuildingInfo(b_Himeji).getObsoleteTech()

		if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
			for iCity in range(pPlayer.getNumCities()):
				ppCity = pPlayer.getCity(iCity)
				if ppCity.getNumActiveBuilding(b_Himeji) == true:
					iPillageGold = ( ( 0 ) * 2 ) 
					iPillageGold = ( ( CyGame().getSorenRandNum(gc.getImprovementInfo(pPlot.getImprovementType()).getPillageGold(), "Pillage Gold 1") ) * 2 )
					iPillageGold += ( ( CyGame().getSorenRandNum(gc.getImprovementInfo(pPlot.getImprovementType()).getPillageGold(), "Pillage Gold 2") ) * 2 )

					iPillageGold += ( ( (pUnit.getPillageChange() * iPillageGold) / 100 ) * 2 )

				else:
					iPillageGold = 0
					iPillageGold = CyGame().getSorenRandNum(gc.getImprovementInfo(pPlot.getImprovementType()).getPillageGold(), "Pillage Gold 1")
					iPillageGold += CyGame().getSorenRandNum(gc.getImprovementInfo(pPlot.getImprovementType()).getPillageGold(), "Pillage Gold 2")

					iPillageGold += (pUnit.getPillageChange() * iPillageGold) / 100

		if pPlot.getOwner( ) >= 0:
			if ( gc.getTeam(pPlayer2.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
				for iCity in range(pPlayer2.getNumCities()):
					ppCity = pPlayer2.getCity(iCity)
					if ppCity.getNumActiveBuilding(b_Himeji) == true:
						iPillageGold = 0

## Himeji Samurai Castle End ##
		
		return iPillageGold
	
	def doCityCaptureGold(self, argsList):
		"controls the gold result of capturing a city"
		
		pOldCity = argsList[0]
		
		iCaptureGold = 0
		
		iCaptureGold += gc.getDefineINT("BASE_CAPTURE_GOLD")
		iCaptureGold += (pOldCity.getPopulation() * gc.getDefineINT("CAPTURE_GOLD_PER_POPULATION"))
		iCaptureGold += CyGame().getSorenRandNum(gc.getDefineINT("CAPTURE_GOLD_RAND1"), "Capture Gold 1")
		iCaptureGold += CyGame().getSorenRandNum(gc.getDefineINT("CAPTURE_GOLD_RAND2"), "Capture Gold 2")

		if (gc.getDefineINT("CAPTURE_GOLD_MAX_TURNS") > 0):
			iCaptureGold *= cyIntRange((CyGame().getGameTurn() - pOldCity.getGameTurnAcquired()), 0, gc.getDefineINT("CAPTURE_GOLD_MAX_TURNS"))
			iCaptureGold /= gc.getDefineINT("CAPTURE_GOLD_MAX_TURNS")

## Himeji Samurai Castle Start ##

		pPlayer = gc.getPlayer( pOldCity.getOwner( ) )

		b_Himeji = gc.getInfoTypeForString("BUILDING_HIMEJI_CASTLE")
		obsoleteTech = gc.getBuildingInfo(b_Himeji).getObsoleteTech()

		if ( gc.getTeam(pPlayer.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
			for iCity in range(pPlayer.getNumCities()):
				ppCity = pPlayer.getCity(iCity)
				if ppCity.getNumActiveBuilding(b_Himeji) == true:
					iCaptureGold = 0
		
## Himeji Samurai Castle End ##
		
		return iCaptureGold
	
	def getUnitCostMod(self, argsList):
		iPlayer, iUnit = argsList

## Imp Trait Start - reduce unit cost ##

		pPlayer = gc.getPlayer(iPlayer)
		iTrait = CvUtil.findInfoTypeNum(gc.getTraitInfo,gc.getNumTraitInfos(),'TRAIT_IMPERIALIST')
		
		if (pPlayer.hasTrait(iTrait)):
			return 80	# 80% of normal cost

## Imp Trait End - reduce unit cost##

		iCostMod = -1 # Any value > 0 will be used
		
		return iCostMod

	def getBuildingCostMod(self, argsList):
		iPlayer, iCityID, iBuilding = argsList
		pPlayer = gc.getPlayer(iPlayer)
		pCity = pPlayer.getCity(iCityID)

## Djenne Start ##

		pBuildingInfo = gc.getBuildingInfo(iBuilding)

		iCathedral1 = CvUtil.findInfoTypeNum(gc.getBuildingInfo,gc.getNumBuildingInfos(),'BUILDING_JEWISH_CATHEDRAL')
		iCathedral2 = CvUtil.findInfoTypeNum(gc.getBuildingInfo,gc.getNumBuildingInfos(),'BUILDING_CHRISTIAN_CATHEDRAL')
		iCathedral3 = CvUtil.findInfoTypeNum(gc.getBuildingInfo,gc.getNumBuildingInfos(),'BUILDING_ISLAMIC_CATHEDRAL')
		iCathedral4 = CvUtil.findInfoTypeNum(gc.getBuildingInfo,gc.getNumBuildingInfos(),'BUILDING_HINDU_CATHEDRAL')
		iCathedral5 = CvUtil.findInfoTypeNum(gc.getBuildingInfo,gc.getNumBuildingInfos(),'BUILDING_BUDDHIST_CATHEDRAL')
		iCathedral6 = CvUtil.findInfoTypeNum(gc.getBuildingInfo,gc.getNumBuildingInfos(),'BUILDING_CONFUCIAN_CATHEDRAL')
		iCathedral7 = CvUtil.findInfoTypeNum(gc.getBuildingInfo,gc.getNumBuildingInfos(),'BUILDING_TAOIST_CATHEDRAL')
		iCathedral8 = CvUtil.findInfoTypeNum(gc.getBuildingInfo,gc.getNumBuildingInfos(),'BUILDING_ZOROASTRIAN_CATHEDRAL')

		aiCathedralList = [iCathedral1, iCathedral2, iCathedral3, iCathedral4, iCathedral5, iCathedral6, iCathedral7, iCathedral8]

		pPlayer1 = gc.getPlayer(pCity.plot().getOwner())

		bDjenne = gc.getInfoTypeForString("BUILDING_DJENNE")
		obsoleteTech = gc.getBuildingInfo(bDjenne).getObsoleteTech()
		if ( gc.getTeam(pPlayer1.getTeam()).isHasTech(obsoleteTech) == false or obsoleteTech == -1 ):
			for iCity in range(pPlayer1.getNumCities()):
				ppCity = pPlayer1.getCity(iCity)
				if ppCity.getNumActiveBuilding(bDjenne) == true:
					if (iBuilding in aiCathedralList):
						return 75	# 75% of normal cost

## Djenne End ##
		
		iCostMod = -1 # Any value > 0 will be used
		
		return iCostMod
and init.xml in Config. Added

Code:
	<!-- Added by Arian - 11/29/2009 -->
	<gameutils module="ANDGameUtils"/>
Spoiler :
Code:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
	Main BUG Mod Initialization

	This file initializes the BUG Core and all mods.

	Copyright (c) 2008 The BUG Mod.
-->
<bug>
	
	<!-- BUG Core -->
	
	<load mod="BUG Config"/>
	<load mod="BUG Core"/>
	
	
	<!-- Civilization Core -->
	
	<!-- Domestic and Military Advisors and Civilopedia are chosen by options -->
	<init module="CvScreensInterface"/>
	
	
	<!-- Utility Modules -->
	
	<init module="FontUtil" immediate="True"/>
	<symbol id="war" from="COMMERCE_GOLD" offset="25"/>
	<symbol id="peace"/>
	<symbol id="space"/>  <!-- blank symbol the same size as other standard symbols -->
	<symbol id="militaryinstructor" name="MILITARY_INSTRUCTOR"/>
	<symbol id="land" name="DOMAIN_LAND"/>
	<symbol id="sea" name="DOMAIN_SEA"/>
	<symbol id="air" name="DOMAIN_AIR"/>
	<symbol id="sentry" name="ORDER_SENTRY"/>
	<symbol id="fortify" name="ORDER_FORTIFY"/>
	<symbol id="wait" name="ORDER_WAIT"/>
	<symbol id="upgrade"/>
	<symbol id="cancel"/>
	<symbol id="citizen" from="POWER" offset="1"/>
	<symbol id="greatgeneral" name="GREAT_GENERAL"/>
	
	<init module="AttitudeUtil">
		<!-- Furious, Annoyed, Cautious, Pleased, Friendly -->
		<arg name="colors" type="tuple">
			"COLOR_RED", 
			"COLOR_CYAN", 
			"COLOR_CLEAR", 
			"COLOR_GREEN", 
			"COLOR_YELLOW"
		</arg>
		<!-- Non-memory attitude modifier keys -->
		<arg name="modifiers" type="tuple">
			"TXT_KEY_MISC_ATTITUDE_LAND_TARGET",
			"TXT_KEY_MISC_ATTITUDE_WAR",
			"TXT_KEY_MISC_ATTITUDE_PEACE",
			"TXT_KEY_MISC_ATTITUDE_SAME_RELIGION",
			"TXT_KEY_MISC_ATTITUDE_DIFFERENT_RELIGION",
			"TXT_KEY_MISC_ATTITUDE_BONUS_TRADE",
			"TXT_KEY_MISC_ATTITUDE_OPEN_BORDERS",
			"TXT_KEY_MISC_ATTITUDE_DEFENSIVE_PACT",
			"TXT_KEY_MISC_ATTITUDE_RIVAL_DEFENSIVE_PACT",
			"TXT_KEY_MISC_ATTITUDE_RIVAL_VASSAL",
			"TXT_KEY_MISC_ATTITUDE_SHARE_WAR",
			"TXT_KEY_MISC_ATTITUDE_FAVORITE_CIVIC",
			"TXT_KEY_MISC_ATTITUDE_TRADE",
			"TXT_KEY_MISC_ATTITUDE_RIVAL_TRADE",
			"TXT_KEY_MISC_ATTITUDE_FREEDOM",
			"TXT_KEY_MISC_ATTITUDE_EXTRA_GOOD",
			"TXT_KEY_MISC_ATTITUDE_EXTRA_BAD"
		</arg>
	</init>
	<event type="LanguageChanged" module="AttitudeUtil" function="initModifiers"/>
	<symbol id="furious" name="ATTITUDE_FURIOUS" from="POWER" offset="4"/>
	<symbol id="annoyed" name="ATTITUDE_ANNOYED"/>
	<symbol id="cautious" name="ATTITUDE_CAUTIOUS"/>
	<symbol id="pleased" name="ATTITUDE_PLEASED"/>
	<symbol id="friendly" name="ATTITUDE_FRIENDLY"/>
	
	<init module="ColorUtil">
		<!--
			You can safely modify this list to change the color dropdown menus
			for color options. You can change the text displayed in the menus by
			adding translations for your new colors to Colors_CIV4GameText.xml
			in the XML/Text directory. 
		-->
		<arg name="colors" type="tuple">
			"COLOR_RED",
			"COLOR_YELLOW",
			"COLOR_CYAN",
			"COLOR_GREEN",
			"COLOR_BLUE",
			"COLOR_MAGENTA",
			"COLOR_WHITE",
			"COLOR_LIGHT_GREY",
			"COLOR_GREY",
			"COLOR_DARK_GREY",
			"COLOR_BLACK"
		</arg>
	</init>
	<event type="LanguageChanged" module="ColorUtil" function="createColors"/>
	
	<events module="DealUtil" function="addEvents"/>
	<events module="DiplomacyUtil" function="addEvents"/>
	<init module="GGUtil"/>
	<init module="GPUtil"/>
	<init module="ReligionUtil"/>
	<init module="TechUtil"/>
	<init module="TradeUtil"/>
	<init module="TraitUtil"/>
	<init module="UnitUtil"/>
	<gameutils module="WidgetUtil" handler="getWidgetHelp"/>

	<!-- Added by Arian - 11/29/2009 -->
	<gameutils module="ANDGameUtils"/>
    
	<event type="OnLoad" module="CvTechChooser" function="resetTechPrefs"/>
	<event type="GameStart" module="CvTechChooser" function="resetTechPrefs"/>
	
	
	<!-- Mods -->
	
	<load mod="BUG Main Interface"/>
	<load mod="BUG City Screen"/>
	<load mod="BUG Advisors"/>
	
	<load mod="Customizable Domestic Advisor"/>
	<load mod="Better Espionage"/>
	<load mod="All Eras Dawn of Man Screen"/>
	<load mod="TechWindow"/>
	
	<load mod="Not Just Another Game Clock"/>
	<load mod="Advanced Scoreboard"/>
	<load mod="Plot List Enhancements"/>
	
	<load mod="Autolog"/>
	<load mod="Reminder"/>  <!-- requires Autolog -->
	<load mod="Civ4lerts"/>
	<load mod="MoreCiv4lerts"/>
	<load mod="Unit Naming"/>
	<load mod="FavoriteCivicDetector"/>
	<load mod="EventSigns"/>
	<load mod="Strategy Overlay"/>
	<load mod="StatusDump"/>
	
	<load mod="A New Dawn"/>
	
	<!-- BULL -->
	
	<load mod="BULL Actions"/>
	<load mod="BULL City Bar"/>
	<load mod="BULL Misc Hovers"/>
	
	<load mod="AutoSave"/>
	<load mod="MapFinder"/>
	<load mod="Advanced Combat Odds"/>

	<!-- Options Screens -->
	

	
	<screen id="BUGFull">
		<tab module="BugGeneralOptionsTab"/>
		<tab module="BugMapOptionsTab"/>
		<tab module="BugCityScreenOptionsTab"/>
		
		<tab module="BugAdvisorOptionsTab"/>
		
		<tab module="BugAlertsOptionsTab"/>
		<tab module="BugScoreOptionsTab"/>
		<tab module="BugNJAGCOptionsTab"/>
		
		<tab module="BugPleOptionsTab"/>
		<tab module="BugACOOptionsTab"/>
		<tab module="BugUnitNameOptionsTab"/>
		
		<tab module="BugAutologOptionsTab"/>
		
		<tab module="BugSystemOptionsTab"/>
		<tab module="BugCreditsOptionsTab"/>
	</screen>
</bug>
And here's my PythonCallbackDefines.xml. It has a couple of new entries at the end.
Spoiler :
Code:
<?xml version="1.0"?>
<!-- Sid Meier's Civilization 4 -->
<!-- Copyright Firaxis Games 2005 -->
<!-- -->
<!-- Global Defines -->
<Civ4Defines xmlns="x-schema:CIV4GlobalDefinesSchema.xml">
	<Define>
		<DefineName>USE_CANNOT_FOUND_CITY_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_FOUND_CITIES_ON_WATER_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_IS_PLAYER_RESEARCH_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_RESEARCH_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_DO_CIVIC_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_DO_CIVIC_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_CONSTRUCT_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_CONSTRUCT_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_DECLARE_WAR_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_RESEARCH_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_GET_UNIT_COST_MOD_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_GET_BUILDING_COST_MOD_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_GET_CITY_FOUND_VALUE_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_HANDLE_ACTION_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_BUILD_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_TRAIN_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_TRAIN_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_UNIT_CANNOT_MOVE_INTO_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_SPREAD_RELIGION_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_FINISH_TEXT_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UNIT_SET_XY_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UNIT_SELECTED_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UPDATE_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UNIT_CREATED_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UNIT_LOST_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_UNIT_STATISTICS_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
</Civ4Defines>
The files are in the attachement.
 

Attachments

The name of the class must match the name of the module, or you must tell BUG the name of the class in init.xml.

I recommend the former to avoid confusion:

Code:
class [B][COLOR="Red"]ANDGameUtils[/COLOR][/B]:

If you really wanted to keep the same name as the original class, you can change init.xml:

Code:
<gameutils module="ANDGameUtils" [B][COLOR="Red"]class="CvGameUtils"[/COLOR][/B]/>

You should have seen an error in PythonErr.log or in PythonDbg.log saying something like "module does have 'ANDGameUtils' attribute."
 
OK, I changed
Code:
class CvGameUtils:
to
Code:
class ANDGameUtils:
in ANDGameUtils.py.

PythonErr.log is empty.
PythonErr2.log and PythonDbg.log are attached. In both files ANDGameUtils.py is not mentioned at all.

It's still not working properly :(
 

Attachments

I forgot that with the <callback> element BUG cannot assume the class name if you only provide the module name since you can create module-level functions as well. So change init.xml to this:

Code:
<gameutils module="ANDGameUtils" [B]class="ANDGameUtils"[/B]/>
 
Thanks EmperorFool, it works now as intended :goodjob:
Just one question:
Do I have to do something with the USE_UNIT_STATISTICS_CALLBACK which isn't in the original BTS PythonCallbackDefines.xml or is it OK?
 
I can only guess what that callback does, so this info is pretty general.

Each callback needs to be defined somewhere and if it has a return value, given a default value. BUG has been told about all the original callbacks in CvGameUtil, but you must tell it about any new callbacks that you add. Here I am talking about the definition of the callback itself (name and default return value)--not a specific handler for a pre-existing callback. Those you must of course tell BUG about or BUG won't call them.

That page I linked shows how to define a new callback using the <callback> element.
 
I can only guess what that callback does, so this info is pretty general.

Each callback needs to be defined somewhere and if it has a return value, given a default value. BUG has been told about all the original callbacks in CvGameUtil, but you must tell it about any new callbacks that you add. Here I am talking about the definition of the callback itself (name and default return value)--not a specific handler for a pre-existing callback. Those you must of course tell BUG about or BUG won't call them.

That page I linked shows how to define a new callback using the <callback> element.

USE_UNIT_STATISTICS_CALLBACK is from Teg Navanis' modcomp Unit Statistics. It seems to work fine :)
 
Back
Top Bottom