Help with python error needed again

Alrik2002

Warlord
Joined
May 24, 2012
Messages
214
Location
Berlin, Germany
Hi,

when I start the world builder in my mod I got the error message I´ve added a screenshot of.

That´s the code it refers to, the red line is line 2367:
Code:
	def refreshPlayerTabCtrl(self):
		
		initWBToolPlayerControl()
		
		self.m_normalPlayerTabCtrl = getWBToolNormalPlayerTabCtrl()

		self.m_normalPlayerTabCtrl.setNumColumns((gc.getNumUnitInfos()/10)+2);
		self.m_normalPlayerTabCtrl.addTabSection(localText.getText("TXT_KEY_WB_UNITS",()));
		self.m_iUnitTabID = 0
		self.m_iNormalPlayerCurrentIndexes.append(0)

		self.m_normalPlayerTabCtrl.setNumColumns((gc.getNumBuildingInfos()/10)+1);
		self.m_normalPlayerTabCtrl.addTabSection(localText.getText("TXT_KEY_WB_BUILDINGS",()));
		self.m_iBuildingTabID = 1
		self.m_iNormalPlayerCurrentIndexes.append(0)

		self.m_normalPlayerTabCtrl.setNumColumns((gc.getNumTechInfos()/10)+1);
		self.m_normalPlayerTabCtrl.addTabSection(localText.getText("TXT_KEY_WB_TECHNOLOGIES",()));
		self.m_iTechnologyTabID = 2
		self.m_iNormalPlayerCurrentIndexes.append(0)
		
	[COLOR="Red"]	addWBPlayerControlTabs()[/COLOR]
		return

The file isn´t part of the mod. It´s the file in the python-folder of BtS, so I´m a little bit confused.
 

Attachments

  • Civ4ScreenShot0042.JPG
    Civ4ScreenShot0042.JPG
    308.2 KB · Views: 78
And here is the second:sad:

The Code (line 2378 is red):
Code:
	def updateSelectionButtons( self ):
	
		global SELECTION_BUTTON_COLUMNS
		global MAX_SELECTION_BUTTONS
		global g_pSelectedUnit

		screen = CyGInterfaceScreen( "MainInterface", CvScreenEnums.MAIN_INTERFACE )
		
		pHeadSelectedCity = CyInterface().getHeadSelectedCity()
		pHeadSelectedUnit = CyInterface().getHeadSelectedUnit()
		
		global g_NumEmphasizeInfos
		global g_NumCityTabTypes
		global g_NumHurryInfos
		global g_NumUnitClassInfos
		global g_NumBuildingClassInfos
		global g_NumProjectInfos
		global g_NumProcessInfos
		global g_NumActionInfos
		
		# Find out our resolution
		xResolution = screen.getXResolution()
		yResolution = screen.getYResolution()
		
# BUG - Build/Action Icon Size - start
		if MainOpt.isBuildIconSizeLarge():
			screen.addMultiListControlGFC( "BottomButtonContainer", u"", iMultiListXL, yResolution - 113 + 18, xResolution - (iMultiListXL+iMultiListXR), 64, 4, 64, 64, TableStyles.TABLE_STYLE_STANDARD )
		elif MainOpt.isBuildIconSizeMedium():
			screen.addMultiListControlGFC( "BottomButtonContainer", u"", iMultiListXL, yResolution - 113, xResolution - (iMultiListXL+iMultiListXR), 100, 4, 48, 48, TableStyles.TABLE_STYLE_STANDARD )
		else:
			screen.addMultiListControlGFC( "BottomButtonContainer", u"", iMultiListXL, yResolution - 113, xResolution - (iMultiListXL+iMultiListXR), 114, 4, 36, 36, TableStyles.TABLE_STYLE_STANDARD )
		# EF: minimum icon size for disabled buttons to work is 33 so these sizes won't fly
#		screen.addMultiListControlGFC( "BottomButtonContainer", u"", iMultiListXL, yResolution - 113, xResolution - (iMultiListXL+iMultiListXR), 102, 4, 32, 32, TableStyles.TABLE_STYLE_STANDARD )
#		screen.addMultiListControlGFC( "BottomButtonContainer", u"", iMultiListXL, yResolution - 113, xResolution - (iMultiListXL+iMultiListXR), 104, 4, 24, 24, TableStyles.TABLE_STYLE_STANDARD )
# BUG - Build/Action Icon Size - end
		screen.clearMultiList( "BottomButtonContainer" )
		screen.hide( "BottomButtonContainer" )
		
		# All of the hides...	
		self.setMinimapButtonVisibility(False)

		screen.hideList( 0 )

		for i in range (g_NumEmphasizeInfos):
			szButtonID = "Emphasize" + str(i)
			screen.hide( szButtonID )

		# Hurry button show...
		for i in range( g_NumHurryInfos ):
			szButtonID = "Hurry" + str(i)
			screen.hide( szButtonID )

		# Conscript Button Show
		screen.hide( "Conscript" )
		#screen.hide( "Liberate" )
		screen.hide( "AutomateProduction" )
		screen.hide( "AutomateCitizens" )

		if (not CyEngine().isGlobeviewUp() and pHeadSelectedCity):
		
			self.setMinimapButtonVisibility(True)

			if ((pHeadSelectedCity.getOwner() == gc.getGame().getActivePlayer()) or gc.getGame().isDebugMode()):
			
				iBtnX = xResolution - 284
				iBtnY = yResolution - 177
				iBtnW = 64
				iBtnH = 30

				# Liberate button
				#szText = "<font=1>" + localText.getText("TXT_KEY_LIBERATE_CITY", ()) + "</font>"
				#screen.setButtonGFC( "Liberate", szText, "", iBtnX, iBtnY, iBtnW, iBtnH, WidgetTypes.WIDGET_LIBERATE_CITY, -1, -1, ButtonStyles.BUTTON_STYLE_STANDARD )
				#screen.setStyle( "Liberate", "Button_CityT1_Style" )
				#screen.hide( "Liberate" )

				iBtnSX = xResolution - 284
				
				iBtnX = iBtnSX
				iBtnY = yResolution - 140
				iBtnW = 64
				iBtnH = 30

				# Conscript button
				szText = "<font=1>" + localText.getText("TXT_KEY_DRAFT", ()) + "</font>"
				screen.setButtonGFC( "Conscript", szText, "", iBtnX, iBtnY, iBtnW, iBtnH, WidgetTypes.WIDGET_CONSCRIPT, -1, -1, ButtonStyles.BUTTON_STYLE_STANDARD )
				screen.setStyle( "Conscript", "Button_CityT1_Style" )
				screen.hide( "Conscript" )

				iBtnY += iBtnH
				iBtnW = 32
				iBtnH = 28
				
				# Hurry Buttons		
				screen.setButtonGFC( "Hurry0", "", "", iBtnX, iBtnY, iBtnW, iBtnH, WidgetTypes.WIDGET_HURRY, 0, -1, ButtonStyles.BUTTON_STYLE_STANDARD )
				screen.setStyle( "Hurry0", "Button_CityC1_Style" )
				screen.hide( "Hurry0" )

				iBtnX += iBtnW

				screen.setButtonGFC( "Hurry1", "", "", iBtnX, iBtnY, iBtnW, iBtnH, WidgetTypes.WIDGET_HURRY, 1, -1, ButtonStyles.BUTTON_STYLE_STANDARD )
				screen.setStyle( "Hurry1", "Button_CityC2_Style" )
				screen.hide( "Hurry1" )
			
				iBtnX = iBtnSX
				iBtnY += iBtnH
			
				# Automate Production Button
				screen.addCheckBoxGFC( "AutomateProduction", "", "", iBtnX, iBtnY, iBtnW, iBtnH, WidgetTypes.WIDGET_AUTOMATE_PRODUCTION, -1, -1, ButtonStyles.BUTTON_STYLE_STANDARD )
				screen.setStyle( "AutomateProduction", "Button_CityC3_Style" )

				iBtnX += iBtnW

				# Automate Citizens Button
				screen.addCheckBoxGFC( "AutomateCitizens", "", "", iBtnX, iBtnY, iBtnW, iBtnH, WidgetTypes.WIDGET_AUTOMATE_CITIZENS, -1, -1, ButtonStyles.BUTTON_STYLE_STANDARD )
				screen.setStyle( "AutomateCitizens", "Button_CityC4_Style" )

				iBtnY += iBtnH
				iBtnX = iBtnSX

				iBtnW	= 22
				iBtnWa	= 20
				iBtnH	= 24
				iBtnHa	= 27
			
				# Set Emphasize buttons
				i = 0
				szButtonID = "Emphasize" + str(i)
				screen.addCheckBoxGFC( szButtonID, "", "", iBtnX, iBtnY, iBtnW, iBtnH, WidgetTypes.WIDGET_EMPHASIZE, i, -1, ButtonStyles.BUTTON_STYLE_LABEL )
				szStyle = "Button_CityB" + str(i+1) + "_Style"
				screen.setStyle( szButtonID, szStyle )
				screen.hide( szButtonID )

				i+=1
				szButtonID = "Emphasize" + str(i)
				screen.addCheckBoxGFC( szButtonID, "", "", iBtnX+iBtnW, iBtnY, iBtnWa, iBtnH, WidgetTypes.WIDGET_EMPHASIZE, i, -1, ButtonStyles.BUTTON_STYLE_LABEL )
				szStyle = "Button_CityB" + str(i+1) + "_Style"
				screen.setStyle( szButtonID, szStyle )
				screen.hide( szButtonID )

				i+=1
				szButtonID = "Emphasize" + str(i)
				screen.addCheckBoxGFC( szButtonID, "", "", iBtnX+iBtnW+iBtnWa, iBtnY, iBtnW, iBtnH, WidgetTypes.WIDGET_EMPHASIZE, i, -1, ButtonStyles.BUTTON_STYLE_LABEL )
				szStyle = "Button_CityB" + str(i+1) + "_Style"
				screen.setStyle( szButtonID, szStyle )
				screen.hide( szButtonID )

				iBtnY += iBtnH
				
				i+=1
				szButtonID = "Emphasize" + str(i)
				screen.addCheckBoxGFC( szButtonID, "", "", iBtnX, iBtnY, iBtnW, iBtnHa, WidgetTypes.WIDGET_EMPHASIZE, i, -1, ButtonStyles.BUTTON_STYLE_LABEL )
				szStyle = "Button_CityB" + str(i+1) + "_Style"
				screen.setStyle( szButtonID, szStyle )
				screen.hide( szButtonID )

				i+=1
				szButtonID = "Emphasize" + str(i)
				screen.addCheckBoxGFC( szButtonID, "", "", iBtnX+iBtnW, iBtnY, iBtnWa, iBtnHa, WidgetTypes.WIDGET_EMPHASIZE, i, -1, ButtonStyles.BUTTON_STYLE_LABEL )
				szStyle = "Button_CityB" + str(i+1) + "_Style"
				screen.setStyle( szButtonID, szStyle )
				screen.hide( szButtonID )

				i+=1
				szButtonID = "Emphasize" + str(i)
				screen.addCheckBoxGFC( szButtonID, "", "", iBtnX+iBtnW+iBtnWa, iBtnY, iBtnW, iBtnHa, WidgetTypes.WIDGET_EMPHASIZE, i, -1, ButtonStyles.BUTTON_STYLE_LABEL )
				szStyle = "Button_CityB" + str(i+1) + "_Style"
				screen.setStyle( szButtonID, szStyle )
				screen.hide( szButtonID )
				
				g_pSelectedUnit = 0
				screen.setState( "AutomateCitizens", pHeadSelectedCity.isCitizensAutomated() )
				screen.setState( "AutomateProduction", pHeadSelectedCity.isProductionAutomated() )
				
				for i in range (g_NumEmphasizeInfos):
					szButtonID = "Emphasize" + str(i)
					screen.show( szButtonID )
					if ( pHeadSelectedCity.AI_isEmphasize(i) ):
						screen.setState( szButtonID, True )
					else:
						screen.setState( szButtonID, False )

				# City Tabs
				for i in range( g_NumCityTabTypes ):
					szButtonID = "CityTab" + str(i)
					screen.show( szButtonID )

				# Hurry button show...
				for i in range( g_NumHurryInfos ):
					szButtonID = "Hurry" + str(i)
					screen.show( szButtonID )
					screen.enable( szButtonID, pHeadSelectedCity.canHurry(i, False) )

				# Conscript Button Show
				screen.show( "Conscript" )
				if (pHeadSelectedCity.canConscript()):
					screen.enable( "Conscript", True )
				else:
					screen.enable( "Conscript", False )

				# Liberate Button Show
				#screen.show( "Liberate" )
				#if (-1 != pHeadSelectedCity.getLiberationPlayer()):
				#	screen.enable( "Liberate", True )
				#else:
				#	screen.enable( "Liberate", False )

				iCount = 0
				iRow = 0
				bFound = False

				# Units to construct
				for i in range ( g_NumUnitClassInfos ):
					eLoopUnit = gc.getCivilizationInfo(pHeadSelectedCity.getCivilizationType()).getCivilizationUnits(i)

					if (pHeadSelectedCity.canTrain(eLoopUnit, False, True)):
						szButton = gc.getPlayer(pHeadSelectedCity.getOwner()).getUnitButton(eLoopUnit)
						screen.appendMultiListButton( "BottomButtonContainer", szButton, iRow, WidgetTypes.WIDGET_TRAIN, i, -1, False )
						screen.show( "BottomButtonContainer" )
						
						if ( not pHeadSelectedCity.canTrain(eLoopUnit, False, False) ):
							screen.disableMultiListButton( "BottomButtonContainer", iRow, iCount, szButton)
						
						iCount = iCount + 1
						bFound = True

				iCount = 0
				if (bFound):
					iRow = iRow + 1
				bFound = False

				# Buildings to construct
				for i in range ( g_NumBuildingClassInfos ):
					if (not isLimitedWonderClass(i)):
						eLoopBuilding = gc.getCivilizationInfo(pHeadSelectedCity.getCivilizationType()).getCivilizationBuildings(i)

						if (pHeadSelectedCity.canConstruct(eLoopBuilding, False, True, False)):
							screen.appendMultiListButton( "BottomButtonContainer", gc.getBuildingInfo(eLoopBuilding).getButton(), iRow, WidgetTypes.WIDGET_CONSTRUCT, i, -1, False )
							screen.show( "BottomButtonContainer" )
							
							if ( not pHeadSelectedCity.canConstruct(eLoopBuilding, False, False, False) ):
								screen.disableMultiListButton( "BottomButtonContainer", iRow, iCount, gc.getBuildingInfo(eLoopBuilding).getButton() )

							iCount = iCount + 1
							bFound = True

				iCount = 0
				if (bFound):
					iRow = iRow + 1
				bFound = False

				# Wonders to construct
				i = 0
				for i in range( g_NumBuildingClassInfos ):
					if (isLimitedWonderClass(i)):
						eLoopBuilding = gc.getCivilizationInfo(pHeadSelectedCity.getCivilizationType()).getCivilizationBuildings(i)

						if (pHeadSelectedCity.canConstruct(eLoopBuilding, False, True, False)):
							[COLOR="Red"]screen.appendMultiListButton( "BottomButtonContainer", gc.getBuildingInfo(eLoopBuilding).getButton(), iRow, WidgetTypes.WIDGET_CONSTRUCT, i, -1, False )[/COLOR]
							screen.show( "BottomButtonContainer" )
							
							if ( not pHeadSelectedCity.canConstruct(eLoopBuilding, False, False, False) ):
								screen.disableMultiListButton( "BottomButtonContainer", iRow, iCount, gc.getBuildingInfo(eLoopBuilding).getButton() )

							iCount = iCount + 1
							bFound = True

				iCount = 0
				if (bFound):
					iRow = iRow + 1
				bFound = False

				# Projects
				i = 0
				for i in range( g_NumProjectInfos ):
					if (pHeadSelectedCity.canCreate(i, False, True)):
						screen.appendMultiListButton( "BottomButtonContainer", gc.getProjectInfo(i).getButton(), iRow, WidgetTypes.WIDGET_CREATE, i, -1, False )
						screen.show( "BottomButtonContainer" )
						
						if ( not pHeadSelectedCity.canCreate(i, False, False) ):
							screen.disableMultiListButton( "BottomButtonContainer", iRow, iCount, gc.getProjectInfo(i).getButton() )
						
						iCount = iCount + 1
						bFound = True

				# Processes
				i = 0
				for i in range( g_NumProcessInfos ):
					if (pHeadSelectedCity.canMaintain(i, False)):
						screen.appendMultiListButton( "BottomButtonContainer", gc.getProcessInfo(i).getButton(), iRow, WidgetTypes.WIDGET_MAINTAIN, i, -1, False )
						screen.show( "BottomButtonContainer" )
						
						iCount = iCount + 1
						bFound = True

				screen.selectMultiList( "BottomButtonContainer", CyInterface().getCityTabSelectionRow() )
							
		elif (not CyEngine().isGlobeviewUp() and pHeadSelectedUnit and CyInterface().getShowInterface() != InterfaceVisibility.INTERFACE_HIDE_ALL and CyInterface().getShowInterface() != InterfaceVisibility.INTERFACE_MINIMAP_ONLY):

			self.setMinimapButtonVisibility(True)

			if (CyInterface().getInterfaceMode() == InterfaceModeTypes.INTERFACEMODE_SELECTION):
			
				if ( pHeadSelectedUnit.getOwner() == gc.getGame().getActivePlayer() and g_pSelectedUnit != pHeadSelectedUnit ):
				
					g_pSelectedUnit = pHeadSelectedUnit
					
					iCount = 0

					actions = CyInterface().getActionsToShow()
					for i in actions:
						screen.appendMultiListButton( "BottomButtonContainer", gc.getActionInfo(i).getButton(), 0, WidgetTypes.WIDGET_ACTION, i, -1, False )
						screen.show( "BottomButtonContainer" )
				
						if ( not CyInterface().canHandleAction(i, False) ):
							screen.disableMultiListButton( "BottomButtonContainer", 0, iCount, gc.getActionInfo(i).getButton() )
							
						if ( pHeadSelectedUnit.isActionRecommended(i) ):#or gc.getActionInfo(i).getCommandType() == CommandTypes.COMMAND_PROMOTION ):
							screen.enableMultiListPulse( "BottomButtonContainer", True, 0, iCount )
						else:
							screen.enableMultiListPulse( "BottomButtonContainer", False, 0, iCount )

						iCount = iCount + 1

					if (CyInterface().canCreateGroup()):
						screen.appendMultiListButton( "BottomButtonContainer", ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_CREATEGROUP").getPath(), 0, WidgetTypes.WIDGET_CREATE_GROUP, -1, -1, False )
						screen.show( "BottomButtonContainer" )
						
						iCount = iCount + 1

					if (CyInterface().canDeleteGroup()):
						screen.appendMultiListButton( "BottomButtonContainer", ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_SPLITGROUP").getPath(), 0, WidgetTypes.WIDGET_DELETE_GROUP, -1, -1, False )
						screen.show( "BottomButtonContainer" )
						
						iCount = iCount + 1

# Immigration Mod
					# ##### Join City Button ######
					iUnitType = g_pSelectedUnit.getUnitType()
					iUnitOwner = g_pSelectedUnit.getOwner( )
					pUnitOwner = gc.getPlayer(iUnitOwner)
					
					if pUnitOwner.isTurnActive( ):
						if gc.getMap().plot(g_pSelectedUnit.getX(), g_pSelectedUnit.getY() ).isCity():
							# Immigration Mod
							if iUnitType == gc.getInfoTypeForString("UNIT_IMMIGRANT"):
								if Immigration.showJoinCityButton(g_pSelectedUnit):
									screen.appendMultiListButton( "BottomButtonContainer", ArtFileMgr.getInterfaceArtInfo("INTERFACE_JOIN_CITY").getPath(), 0, WidgetTypes.WIDGET_GENERAL, 680, 680, False )
									screen.show("BottomButtonContainer")
									iCount = iCount + 1
									return
# End Immigration Mod

		elif (CyInterface().getShowInterface() != InterfaceVisibility.INTERFACE_HIDE_ALL and CyInterface().getShowInterface() != InterfaceVisibility.INTERFACE_MINIMAP_ONLY):
		
			self.setMinimapButtonVisibility(True)

		return 0
		
	# Will update the research buttons
 

Attachments

  • FehlermeldungFrank5.jpg
    FehlermeldungFrank5.jpg
    137.5 KB · Views: 82
Hmm. I´ve gone back to my last change I´ve made and undid it. After that I made the change again and now it seems to work... Thank you for your help. I hope the errors will not show up again.
 
Ok good..

Just a guess on the cause but I'd just offer to be careful with python, spaces and tabs aren't the same thing to it and sometimes the spacing looks the good but it's not. If indentation is not perfect (again rememeber spaces and tabs aren't the same) you'll get odd errors.

Recommend notepad++ and winmerge as good tools
 
It´s me again with another python error.:blush:

When I start a custom game, sometimes the error in the attached screenshot shows up (you can ignore the comments in the white boxes) and sometimes not. Even when I start a new game with just one Civ sometimes everything is ok, the other time with the same civ the error is there.

I´ve looked at the lines which where pointed out and it seems to have something to do with the PromotionGrouping.

Here are the referred files with the lines which were pointed out in red.

BugInit line 93:
Code:
def callInits():
	"""Calls all of the stored init functions in the order they were added."""
	BugUtil.debug("BugInit - calling init functions...")
	while g_initQueue:
		name, func = g_initQueue.pop(0)
		try:
			[COLOR="Red"]func()[/COLOR]
		except:
			BugUtil.trace("BugInit - init '%s' failed" % name)

CvScreensInterface line 1185:
Code:
# BUG - Options - start
def init():
	createDomesticAdvisor()
	createFinanceAdvisor()
	[COLOR="Red"]createMilitaryAdvisor()[/COLOR]
	createCivilopedia()
	createTechSplash()
# BUG - Options - end

CvScreensInterface line 160:
Code:
# BUG - Military Advisor - start
militaryAdvisor = None
def createMilitaryAdvisor():
	"""Creates the correct Military Advisor based on an option."""
	global militaryAdvisor
	if militaryAdvisor is None:
		if (AdvisorOpt.isBUG_MA()):
			import CvBUGMilitaryAdvisor
			[COLOR="Red"]militaryAdvisor = CvBUGMilitaryAdvisor.CvMilitaryAdvisor(MILITARY_ADVISOR)[/COLOR]
		else:
			import CvMilitaryAdvisor
			militaryAdvisor = CvMilitaryAdvisor.CvMilitaryAdvisor(MILITARY_ADVISOR)
		HandleInputMap[MILITARY_ADVISOR] = militaryAdvisor

CvBUGMilitaryAdvisor line 87:
Code:
	def __init__(self, screenId):
		self.screenId = screenId
		self.SCREEN_NAME = "MilitaryScreen-BUG"

		self.UNIT_LOC_TAB_ID = "MilitaryUnitLocTabWidget-BUG"
		self.SIT_REP_TAB_ID = "MilitarySitRepTabWidget-BUG"
		self.STRAT_ADV_TAB_ID = "MilitaryStratAdvTabWidget-BUG"

		self.X_GROUP_LIST = 20
		self.Y_GROUP_LIST = 190
		self.W_GROUP_LIST = 280
		
		self.X_MAP = 20
		self.Y_MAP = 220      # 190
		self.W_MAP = 580
		self.H_MAP_MAX = 470  # 500
		self.MAP_MARGIN = 20

		self.X_TEXT = 625
		self.Y_TEXT = 190
		self.W_TEXT = 380
		self.H_TEXT = 500
						
		self.X_LEADERS = 20
		self.Y_LEADERS = 80
		self.W_LEADERS = 985
		self.H_LEADERS = 90
		self.LEADER_BUTTON_SIZE = 64
		self.LEADER_MARGIN = 12

		self.LEADER_COLUMNS = int(self.W_LEADERS / (self.LEADER_BUTTON_SIZE + self.LEADER_MARGIN))

		[COLOR="Red"]self.grouper = UnitGrouper.StandardGrouper()[/COLOR]
		self.selectedLeaders = set()
		self.selectedGroups = set()
		self.selectedUnits = set()
		self.groupingKeys = ["loc", "type"]

UnitGrouper line 299:
Code:
class StandardGrouper(Grouper):
	def __init__(self):
		Grouper.__init__(self)
		
		self._addGrouping(UnitTypeGrouping())
		self._addGrouping(UnitCombatGrouping())
		self._addGrouping(LevelGrouping())
		[COLOR="Red"]self._addGrouping(PromotionGrouping())[/COLOR]
		self._addGrouping(LocationGrouping())
		self._addGrouping(OrderGrouping())

UnitGrouper line 166:
Code:
class PromotionGrouping(Grouping):
	"""
	Groups units by their promotions.
	Ex: Combat 1, Cover, Tactics
	"""
	def __init__(self):
		Grouping.__init__(self, "promo", "TXT_KEY_UNIT_GROUPER_PROMOTION_GROUPING")
		
		self.NONE = 0
		self.NO_PROMOS = (0,)
		self._addGroup(Group(self, self.NONE, "TXT_KEY_UNIT_GROUPER_PROMOTION_GROUP_NONE"))
		for i in range(gc.getNumPromotionInfos()):
			info = gc.getPromotionInfo(i)
			if info:
				[COLOR="Red"]self._addGroup(Group(self, i + 1, '<img=%s size=16></img> %s' % [/COLOR]
							          [COLOR="Orange"](info.getButton(), info.getDescription())))[/COLOR]

I´ve no idea where the failure is and how I could fix it. The only thing that looks strange for me is that "(info.getButton(), info.getDescription())))" in the last code (I made it orange) is so far left although it seems the last bracket closes the one behind "self._addGroup" in the line above (line 166). Could that be the problem?
http://forums.civfanatics.com/attachment.php?attachmentid=331394&d=1347920548
 
I´ve one Promotion which is a little bit unusual in the german text, but it works in the game and you get the promotion only after building a national wonder:

Code:
<Tag>TXT_KEY_PROMOTION_ATHENA_BLESSING</Tag>
		<English>Athena's Blessing</English>
		<French></French>
		[COLOR="Red"]<German>[OUR_NAME]´s Segen</German>[/COLOR]
		</TEXT>

The error shows up right after starting or loading a game, when the national wonder isn´t built.

I´ve corrected another error in the CvEventManager.py. After that, the error didn´t show up until now but I´ve only started five games. Could it be, that this error shows up because of another incorrect part of the CvEventManager.py without naming the line?
 
No codes under onGameStart or onGameLoad related to that wonder.
But I can tell you it is not going to work well for a National Wonder if you are using the same exact codes as its original version.
 
I´ve another error I can´t solve. Could anyone explain me please what could be wrong there? The files the error is related to are the original files of BtS (CvWBDesc.py and CvWBInterface.py).

The error is shown in the screenshot. These are the lines it refers to (in red):

CvWBInterface.py line 18
def writeDesc(argsList):
"Save out a high-level desc of the world, for WorldBuilder"
fileName = argsList[0]
global lastFileRead
lastFileRead=None
return WBDesc.write(fileName)

CvWBDesc.py line 1552
Code:
	def write(self, fileName):
		"Save out a high-level desc of the world, and height/terrainmaps"		
		fileName = os.path.normpath(fileName)
		fileName,ext = os.path.splitext(fileName)
		CvUtil.pyPrint( 'saveDesc:%s, curDir:%s' %(fileName,os.getcwd()) )

		f = file(self.getDescFileName(fileName), "w")		# open text file		
		f.write("Version=%d\n" %(self.getVersion(),))		
		self.gameDesc.write(f)	# write game info

		for i in range(gc.getMAX_CIV_TEAMS()):	
			CvTeamDesc().write(f, i)		# write team info

		for i in range(gc.getMAX_CIV_PLAYERS()):	
			CvPlayerDesc().write(f, i)		# write player info
			
		self.mapDesc.write(f)	# write map info
		
		f.write("\n### Plot Info ###\n")		
		iGridW = CyMap().getGridWidth()
		iGridH = CyMap().getGridHeight()
		for iX in range(iGridW):
			for iY in range(iGridH):
				plot = CyMap().plot(iX, iY)
				pDesc = CvPlotDesc()
				if pDesc.needToWritePlot(plot): 
					pDesc.write(f, plot)
					
		f.write("\n### Sign Info ###\n")
		iNumSigns = CyEngine().getNumSigns()
		for i in range(iNumSigns):
			sign = CyEngine().getSignByIndex(i)
			pDesc = CvSignDesc()
			[COLOR="Red"]pDesc.write(f, sign)[/COLOR]

		f.close()
		
		print("WBSave done\n")
		return 0	# success


CvWBDesc.py line 1462
Code:
	def write(self, f, sign):
		"write sign data"
		f.write("BeginSign\n")
		f.write("\tplotX=%d\n" %(sign.getPlot().getX(),))
		f.write("\tplotY=%d\n" %(sign.getPlot().getY(),))
		f.write("\tplayerType=%d\n" %(sign.getPlayerType(),))
		[COLOR="Red"]f.write("\tcaption=%s\n" %(sign.getCaption(),))[/COLOR]
		f.write("EndSign\n")

Thank you for your help.

Alrik
 

Attachments

  • 27 - Ladefehler Ramses 3.JPG
    27 - Ladefehler Ramses 3.JPG
    261 KB · Views: 57
Any idea where or how I could find the file with the umlaut to correct it? I believe it will be a xml-file. Correct?

Are umlaute ok in the translations of the gametext.xml?
 
In this case it's some special character in a sign on the map, not in the XML files.
Else yes, it would be in the XML, and you can put umlauts and other characters from extended sets directly into the XML files, but that will cause problems on Macs.
 
Text in Civ4's Python tends to try to be ASCII, which is only a 7-bit encoding (and probably a mistake, given the international nature of Civ4 sales). You can see in the CvWBDesc.py file up near the top there is a variable called fileencoding that gets set to "latin_1", which is an 8-bit encoding that covers western European languages (it includes letters with umlauts and other accents). For some read and write function calls you can see how this is already used. What you do is set up the problematic write, and the corresponding read, to use the fileencoding the same way as the others. The existence of this code in there shows that the developers had this problem too, but didn't fix it by making the Python interpreter default to latin_1 for this sort of thing (or even utf-8) instead of ASCII; they just did the encode/decode on whichever text items were having the problem in here.

Line 1462 then becomes:
Code:
		f.write("\tcaption=%s\n" %(sign.getCaption()[B][I].encode(fileencoding)[/I][/B],))
In the read function shortly after that you should make it symmetric by doing a decode on the caption when loaded, so the code several lines later would look like:
Code:
			v = parser.findTokenValue(toks, "caption")
			if v!=-1:
				self.szCaption = v[B][I].decode(fileencoding)[/I][/B]
				continue

With a little luck, that will solve the problem with saving/loading that "ü" character (that's what the u'\xfc' refers to, hexadecimal character fc = decimal character 252 which is a lowercase u with an umlaut).

In the XML they have all the text that is non-ASCII characters encoded using the XML encodings (which really should not be necessary as the headers in the XML files specify encoding="ISO-8859-1", which is another name for the latin_1 character set). But once this data is read into memory it is just the unicode character, not encoded. When it goes to write it out to the worldbuilder save, the Python then has issues like this due to the default conversion being set to be ASCII even though the file it is writing to is apparently opened as a latin_1 file (not being unicode, it forces a conversion but it defaults to the wrong conversion). Oops.
 
But I can tell you it is not going to work well for a National Wonder if you are using the same exact codes as its original version.

Could you tell me which part of the code must be changed when I want to use Erechtheion as a National Wonder?

This is the code how it´s now:
Code:
	def onBuildingBuilt(self, argsList):
		'Building Completed'
		pCity, iBuildingType = argsList
		game = gc.getGame()

		iPlayer = pCity.getOwner()
		pPlayer = gc.getPlayer(iPlayer)
		iTeam = pPlayer.getTeam()
		pTeam = gc.getTeam(iTeam)
## Erechtheion Start ##
		if iBuildingType == gc.getInfoTypeForString("BUILDING_ERECHTHEION"):
			Fearsome = [-1, -1]
			(loopUnit, iter) = pPlayer.firstUnit(false)
			while(loopUnit):
				if loopUnit.getExperience() > Fearsome[0]:
					Fearsome = [loopUnit.getExperience(), loopUnit]
				(loopUnit, iter) = pPlayer.nextUnit(iter, false)
			Athena = gc.getInfoTypeForString("PROMOTION_ATHENA_BLESSING")
			Fearsome[1].setHasPromotion(Athena, true)
			CyInterface().addMessage(iPlayer,true,15,CyTranslator().getText("TXT_ATHENA_BLESSING",(Fearsome[1].getName(),)),'',0,gc.getPromotionInfo(Athena).getButton(),ColorTypes(11),Fearsome[1].getX(),Fearsome[1].getY(),true,true)
## Platyping Wonders End ##
		if ((not gc.getGame().isNetworkMultiPlayer()) and (pCity.getOwner() == gc.getGame().getActivePlayer()) and isWorldWonderClass(gc.getBuildingInfo(iBuildingType).getBuildingClassType())):
			# If this is a wonder...
			popupInfo = CyPopupInfo()
			popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON_SCREEN)
			popupInfo.setData1(iBuildingType)
			popupInfo.setData2(pCity.getID())
			popupInfo.setData3(0)
			popupInfo.setText(u"showWonderMovie")
			popupInfo.addPopup(pCity.getOwner())

		CvAdvisorUtils.buildingBuiltFeats(pCity, iBuildingType)

		if (not self.__LOG_BUILDING):
			return
		CvUtil.pyPrint('%s was finished by Player %d Civilization %s' 
			%(PyInfo.BuildingInfo(iBuildingType).getDescription(), pCity.getOwner(), gc.getPlayer(pCity.getOwner()).getCivilizationDescription(0)))

...

	def onUnitKilled(self, argsList):
		'Unit Killed'
		unit, iAttacker = argsList
		player = PyPlayer(unit.getOwner())
		attacker = PyPlayer(iAttacker)

		iPlayer = unit.getOwner()
		pPlayer = gc.getPlayer(iPlayer)
		pPlayer2 = gc.getPlayer(iAttacker)
## Erechtheion Start ##
		Athena = gc.getInfoTypeForString("PROMOTION_ATHENA_BLESSING")
		if unit.isHasPromotion(Athena):
			unit.setHasPromotion(Athena, false)	## To be compatible with other wonders which "revive" units
			Fearsome = [-1, -1]
			(loopUnit, iter) = pPlayer.firstUnit(false)
			while(loopUnit):
				if not loopUnit.isDead():
					if loopUnit.getExperience() > Fearsome[0]:
						Fearsome = [loopUnit.getExperience(), loopUnit]
				(loopUnit, iter) = pPlayer.nextUnit(iter, false)
			Fearsome[1].setHasPromotion(Athena, true)
			CyInterface().addMessage(iPlayer,true,15,CyTranslator().getText("TXT_ATHENA_BLESSING",(Fearsome[1].getName(),)),'',0,gc.getPromotionInfo(Athena).getButton(),ColorTypes(11),Fearsome[1].getX(),Fearsome[1].getY(),true,true)
## Platyping Wonders End ##

		if (not self.__LOG_UNITKILLED):
			return
		CvUtil.pyPrint('Player %d Civilization %s Unit %s was killed by Player %d' 
			%(player.getID(), player.getCivilizationName(), PyInfo.UnitInfo(unit.getUnitType()).getDescription(), attacker.getID()))

Thank you.
 
The main reason is because National Wonders can be destroyed via alot of means, yet there is no python way of detecting that. There isn't any "onBuildingDestoyed" kind of thing.

This wonder is meant to work such that when it is built, only one unit in the world is blessed with that OP promotion. And if the unit died, the promotion is passed on to another unit.
I believe there should be codes when the city changes hands as well, so that the promotion is removed from old owner and granted to new owner.

As a world wonder, it is ok, because world wonder can only be destroyed when the city itself is razed, so there is a way to detect that.
As a national wonder, there isn't any method. So you may end up with multiple units with that promotion if you build it multiple times, although you can add an additional check for it.
But the other problem is when the NW is destoryed, the unit with the promotion is still hanging around. If you are fine with that, then an additional check has to be added so that when this leftover unit is dead, you do not pass the promotion to a new unit since you no longer own the wonder.

In short, there will be situations where you still have unit(s) with the promotion when you no longer own the wonder.
 
Hmmm...ok I see the problem. But isn´t the tag "iConquestProb" in the Civ4BuildingInfos good for that? There you can define the percentage chance that a building will survive if the city is captured. In this case it would be 100 (like it´s set now), so the Erechteion will only be destroyed if the city itself will be destroyed. So it´s the same like a world wonder.

But I have to check what happens if a Civ with Erechteion already built capture a city with Erechtheion in it. I hope it will be the same like the wall street or other national wonders.
 
It will be kept I believe and you end up with 2 National Wonders, so additional codes have to be added to destroy it manually.
However, it can still be destroyed by Nukes and if you want to set it as Nuke Immune as well, doesn't it look too special compared to the other NWs?

In short, you need many additional codes here and there
 
Top Bottom