AND2 and SVN Bug Reports - A New Dawn 2 ONLY

hey i posted here about an installation problem, not a word... strange i always have quick answers in CFC.

Before answer, mind: i'm a long time CIV player, i'm a good level player, i used to mod-mod this thing in the past, i know what a computer is :)
 
Not sure what Afforess changed in the codes, but I can tell you even in BTS, this code will fail.

Under normal circumstances, this code is fine. But when a middle city is captured, the ID is screwed up.

For instance, Cities A to E, where A will be ID 0, while E will be ID 4. When City C is captured, number of cities will fall to 4, but City D and E will remain as ID 3 and 4 respectively. Hence, you loop through a range of 4, City ID 2 which used to be City C will be null, while City E is missed.

When a new City F is built, it will take up the missing slot though, so usually nobody will notice.

The solution is to use a while loop, or the inefficient pyhelper method, which uses the while loop and a for loop.

I've tried

Code:
		lCities = PyHelpers.PyPlayer(iActivePlayer).getCityList()
		for iCity in range( len( lCities ) ):
			objCity = gc.getPlayer(iActivePlayer).getCity( lCities[ iCity ].getID( ) )

instead of

Code:
		for iCityID in range(gc.getPlayer(iActivePlayer).getNumCities()):
			objCity = gc.getPlayer(iActivePlayer).getCity(iCityID)

and same for units, but it looks like it's not working. Do you have any suggestion? Is there something wrong that you can spot? Thank you anyway for all your advices platyping!
 
45°38'N-13°47'E;13635607 said:
Code:
		lCities = PyHelpers.PyPlayer(iActivePlayer).getCityList()
		for iCity in range( len( lCities ) ):
			objCity = gc.getPlayer(iActivePlayer).getCity( lCities[ iCity ].getID( ) )

If you are using PyHelpers, the for loop can be simplified to :
Code:
 for objCity in lCities:

PyHelpers is an inefficient way of coding, but many coders are used to it, because previous coders code using them, so they just C&P without understanding how it works.

Most of the time, I use a while loop directly to get the same task done.
Code:
		pPlayer = gc.getPlayer(iActivePlayer)
		(loopCity, iter) = pPlayer.firstCity(False)
		while(loopCity):
			............
			(loopCity, iter) = pPlayer.nextCity(iter, False)

What actually happens in PyHelpers is that they use this while loop to loop through all cities and store them in a list.
After which, you use a for loop to loop through this saved list to do what you want.
Then you realise you could have done what you need via the while loop directly, why is there a need for a double loop...

Need more info on what is not working, such as python exceptions.
 
If you are using PyHelpers, the for loop can be simplified to :
Code:
 for objCity in lCities:

PyHelpers is an inefficient way of coding, but many coders are used to it, because previous coders code using them, so they just C&P without understanding how it works.

Most of the time, I use a while loop directly to get the same task done.
Code:
		pPlayer = gc.getPlayer(iActivePlayer)
		(loopCity, iter) = pPlayer.firstCity(False)
		while(loopCity):
			............
			(loopCity, iter) = pPlayer.nextCity(iter, False)

What actually happens in PyHelpers is that they use this while loop to loop through all cities and store them in a list.
After which, you use a for loop to loop through this saved list to do what you want.
Then you realise you could have done what you need via the while loop directly, why is there a need for a double loop...

Need more info on what is not working, such as python exceptions.

Well, I've tried the while loop; I actually need it only for the units part, because I've seen that cities problem was somewhere else and now it works.

So here's the code:

Code:
	def drawOutgoingWarheadsContent(self, screen):
	
		self.H_MAP = (self.W_MAP * CyMap().getGridHeight()) / CyMap().getGridWidth()
		if (self.H_MAP > self.H_MAP_MAX):
			self.W_MAP = (self.H_MAP_MAX * CyMap().getGridWidth()) / CyMap().getGridHeight()
			self.H_MAP = self.H_MAP_MAX
			
		screen.addPanel(OUTGOING_WARHEADS_PANEL, u"", "", False, False, 24, 60, 350, 708-60, PanelStyles.PANEL_STYLE_MAIN)
		screen.addPanel(OUTGOING_WARHEADS_INNER_PANEL, u"", "", True, True, 34, 60+10+40, 330, 708-(70+15+35), PanelStyles.PANEL_STYLE_IN)
		screen.addPanel(OUTGOING_LABEL_PANEL, u"", "", False, False, 29, 60+10, 340, 35, PanelStyles.PANEL_STYLE_MAIN)
		screen.setText(self.OUTGOING_LABEL_ID, "Background", self.OUTGOING_LABEL_TEXT, CvUtil.FONT_CENTER_JUSTIFY, 24+(350/2), 60+10+7, self.Z_CONTROLS, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1 )
		screen.setHitTest(self.OUTGOING_LABEL_ID,HitTestTypes.HITTEST_NOHIT)
		
		screen.addPanel(OUTGOING_SUMMARY_PANEL, u"", "", False, False, 420, self.Y_MAP+self.H_MAP+5, 580, self.H_SCREEN-(self.Y_MAP+self.H_MAP+5)-60, PanelStyles.PANEL_STYLE_MAIN)
		screen.addPanel(OUTGOING_SUMMARY_INNER_PANEL, u"", "", True, False, 425+5, self.Y_MAP+self.H_MAP+15+40, 580-20, self.H_SCREEN-(self.Y_MAP+self.H_MAP+5)-(70+35+15), PanelStyles.PANEL_STYLE_IN)
		screen.addPanel(OUTGOING_SUMMARY_LABEL_PANEL, u"", "", False, False, 425, self.Y_MAP+self.H_MAP+15, 570, 35, PanelStyles.PANEL_STYLE_MAIN)
		screen.setText(self.OUTGOING_SUMMARY_LABEL_ID, "Background", self.OUTGOING_SUMMARY_LABEL_TEXT, CvUtil.FONT_CENTER_JUSTIFY, 425+(570/2), self.Y_MAP+self.H_MAP+15+7, self.Z_CONTROLS, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1 )
		screen.setHitTest(self.OUTGOING_SUMMARY_LABEL_ID,HitTestTypes.HITTEST_NOHIT)
		
		iCounter = 0
		iTotalNukeCount = 0
		
		pPlayer = gc.getPlayer(iActivePlayer)
		(objUnit, iter) = pPlayer.firstUnit(False)
		while(objUnit):		
			objUnit = gc.getPlayer(gc.getGame().getActivePlayer()).getUnit(iUnitID)
			
			self.selectedUnitHash[iUnitID] = False;

			if(objUnit.getUnitAIType() != UnitAITypes.UNITAI_ICBM):
				continue
							
			iTotalNukeCount += 1
			
			if(objUnit.getMADTargetPlot() == None):
				continue

			if(objUnit.getMADTargetPlot().isNone()):
				continue
			
			[COLOR="Red"]screen.attachPanel(OUTGOING_WARHEADS_INNER_PANEL, "UnitPanel%s" %(iUnitID), "", "", True, False, PanelStyles.PANEL_STYLE_OUT)[/COLOR]

			screen.attachPanel("UnitPanel%s" %(iUnitID), "UnitInnerPanel%s" %(iUnitID), "", "", True, False, PanelStyles.PANEL_STYLE_EMPTY)
			screen.attachLabel( "UnitInnerPanel%s" %(iUnitID), "UnitInnerPanel%sfill1" %(iUnitID), "            Located At: %s" %(objUnit.plot().getPlotCity().getName()))
			screen.attachLabel( "UnitInnerPanel%s" %(iUnitID), "UnitInnerPanel%sfill2" %(iUnitID), "            Targetting: %s" %(objUnit.getMADTargetPlot().getPlotCity().getName()))
			screen.attachLabel( "UnitInnerPanel%s" %(iUnitID), "UnitInnerPanel%sfill3" %(iUnitID), "            City Owned By: %s" %(gc.getPlayer(objUnit.getMADTargetPlot().getPlotCity().getOwner()).getName()))

#			screen.attachLabel( "UnitPanel%s" %(iUnitID), "UnitPanel%sfill1" %(iUnitID), "            " )
			screen.addCheckBoxGFCAt( "UnitPanel%s" %(iUnitID), "UnitCheckbox%s" %(iUnitID)
							   , gc.getUnitInfo(objUnit.getUnitType()).getButton()
							   , ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath()
							   , 1, 2, 46, 46, WidgetTypes.WIDGET_GENERAL, iUnitID, iUnitID, ButtonStyles.BUTTON_STYLE_LABEL, False)
			iCounter +=1
			(objUnit, iter) = pPlayer.nextUnit(iter, False)	
			
		if(iCounter <= 10):
			iTempCounter = 10 - iCounter
			
			for iDummy in range(iTempCounter):
				screen.attachPanel(OUTGOING_WARHEADS_INNER_PANEL, "DummyPanel%s" %(iDummy), "", "", True, False, PanelStyles.PANEL_STYLE_EMPTY)
				screen.attachLabel( "DummyPanel%s" %(iDummy), "UnitPanel%sfill1" %(iDummy), "            " )
				screen.attachLabel( "DummyPanel%s" %(iDummy), "UnitPanel%sfill2" %(iDummy), "            " )
				screen.attachLabel( "DummyPanel%s" %(iDummy), "UnitPanel%sfill3" %(iDummy), "            " )
		
		screen.attachLabel( OUTGOING_SUMMARY_INNER_PANEL, "TotalNukes", u"%c<FONT=3b>%s Total Nuclear Warheads</FONT>" %(CyGame().getSymbolID(FontSymbols.BULLET_CHAR), iTotalNukeCount) )
		screen.attachLabel( OUTGOING_SUMMARY_INNER_PANEL, "TotalOutgoingNukes", u"%c<FONT=3b>%s Outgoing Nuclear Warheads</FONT>" %(CyGame().getSymbolID(FontSymbols.BULLET_CHAR), iCounter) )
		screen.attachLabel( OUTGOING_SUMMARY_INNER_PANEL, "TotalNukesAvailable", u"%c<FONT=3b>%s Available Nuclear Warheads</FONT>" %(CyGame().getSymbolID(FontSymbols.BULLET_CHAR), iTotalNukeCount-iCounter) )

I get no errors but no panel or label is displayed after that red line. If I use the old "for" code, all panels are displayed correctly but iTotalNukeCount and iCounter are always 0.
 
I will be surprised to see no errors.
Where is iUnitID defined?

When you use the while loop method...
Code:
(objUnit, iter) = pPlayer.firstUnit(False)
while(objUnit):

objUnit is already the CyUnit object which you need where you can do commands like change level, add experience, kill etc.

Why do you still add this line.
objUnit = gc.getPlayer(gc.getGame().getActivePlayer()).getUnit(iUnitID)

A simple while loop example:
Code:
pPlayer = gc.getPlayer(iActivePlayer)
iStateReligion = pPlayer.getStateReligion()
(loopCity, iter) = pPlayer.firstCity(False)
while(loopCity):
	if loopCity.isHasReligion(iStateReligion):
		loopCity.changePopulation(1)
	(loopCity, iter) = pPlayer.nextCity(iter, False)

while most people are using the PyHelpers method:
Code:
lCities = PyHelpers.PyPlayer(iActivePlayer).getCityList()
iStateReligion = gc.getPlayer(iActivePlayer).getStateReligion()
for loopCity in lCities:
	if loopCity.isHasReligion(iStateReligion):
		loopCity.changePopulation(1)

Anyway, if the for loop method shows 0 for both values, the while loop method will still show 0 when working correctly, because the for loop is just an inefficient version of the while loop method. One drawback with the while loop however is you cannot use continue statements. If you try to continue on the last iteration, it will crash.
 
If you want to change the header, you look for the header section, which I believe BTS pedia use getDescription, while I use short desc instead. The adjective is just to illustrate.
Thanks to your help, i've managed to correctly use the python API. This is not really what i call a good documentation, but yet, it is usable.

getCivilizationType will return an int. In this case, it is used as a civilization type. But it is simply just an int which can be used for other purposes. For instance, pPlayer.changeGold(pPlayer.getCivilizationType())
Will work perfectly, resulting in the player gold increased by his civ ID.
In fact, there are some parts of the documentation for which the underline represents the output type of the function and some parts where that means the input type. Of course, it's mentionned nowhere; that's why i was a bit lost ;)
 
I will be surprised to see no errors.
Where is iUnitID defined?

You were right of course, I've mistakenly de-activated python exceptions. I'll try again and I'll let you know, thanks again. :)
 
Thanks to your help, i've managed to correctly use the python API. This is not really what i call a good documentation, but yet, it is usable.


In fact, there are some parts of the documentation for which the underline represents the output type of the function and some parts where that means the input type. Of course, it's mentionned nowhere; that's why i was a bit lost ;)

There are some errors with the API which I stated here.
http://forums.civfanatics.com/showthread.php?t=478603

And of course some functions which are not even listed.
The API only lists out the commands, but does not explain what they do, so most of the time you need to trial and error.

Some functions are similar in nature but behave differently.
CyCity changeFreeBonus will add free bonus to a city, like what Hollywood does.
CyCity changeFreeSpecialist will add free specialist to a city.

Yet the former freebie is lost upon city acquisition, while the later will retain the freebie. Thus, do some experiments on your own.
 
I will be surprised to see no errors.
Where is iUnitID defined?

When you use the while loop method...
Code:
(objUnit, iter) = pPlayer.firstUnit(False)
while(objUnit):

objUnit is already the CyUnit object which you need where you can do commands like change level, add experience, kill etc.
[CUT]
Anyway, if the for loop method shows 0 for both values, the while loop method will still show 0 when working correctly, because the for loop is just an inefficient version of the while loop method. One drawback with the while loop however is you cannot use continue statements. If you try to continue on the last iteration, it will crash.

Ok, looks like I've mostly made it:

Code:
		iActivePlayer = gc.getGame().getActivePlayer()
		pPlayer = gc.getPlayer(iActivePlayer)
#		iUnitID = pPlayer.getUnit(iUnitID)
		(iUnitID, iter) = pPlayer.firstUnit(False)
		while(iUnitID):
	#		objUnit = gc.getPlayer(gc.getGame().getActivePlayer()).getUnit(iUnitID)
			self.selectedUnitHash[iUnitID] = False;

			if(iUnitID.getUnitAIType() == UnitAITypes.UNITAI_ICBM):
				pass
				iTotalNukeCount += 1
			
			if(iUnitID.getMADTargetPlot() != None) and not (iUnitID.getMADTargetPlot().isNone()):
				pass

	#		if(objUnit.getMADTargetPlot().isNone()):
	#			continue
				
				screen.attachPanel(OUTGOING_WARHEADS_INNER_PANEL, "UnitPanel%s" %(iUnitID), "", "", True, False, PanelStyles.PANEL_STYLE_OUT)

				screen.attachPanel("UnitPanel%s" %(iUnitID), "UnitInnerPanel%s" %(iUnitID), "", "", True, False, PanelStyles.PANEL_STYLE_EMPTY)
				screen.attachLabel( "UnitInnerPanel%s" %(iUnitID), "UnitInnerPanel%sfill1" %(iUnitID), "            Located At: %s" %(iUnitID.plot().getPlotCity().getName()))
				screen.attachLabel( "UnitInnerPanel%s" %(iUnitID), "UnitInnerPanel%sfill2" %(iUnitID), "            Targetting: %s" %(iUnitID.getMADTargetPlot().getPlotCity().getName()))
				screen.attachLabel( "UnitInnerPanel%s" %(iUnitID), "UnitInnerPanel%sfill3" %(iUnitID), "            City Owned By: %s" %(gc.getPlayer(iUnitID.getMADTargetPlot().getPlotCity().getOwner()).getName()))

#			screen.attachLabel( "UnitPanel%s" %(iUnitID), "UnitPanel%sfill1" %(iUnitID), "            " )
				screen.addCheckBoxGFCAt( "UnitPanel%s" %(iUnitID), "UnitCheckbox%s" %(iUnitID)
								[COLOR="Red"], gc.getUnitInfo(objUnit.getUnitType()).getButton()[/COLOR]
								, ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath()
								, 1, 2, 46, 46, WidgetTypes.WIDGET_GENERAL, iUnitID, iUnitID, ButtonStyles.BUTTON_STYLE_LABEL, False)
				iCounter +=1
			(iUnitID, iter) = pPlayer.nextUnit(iter, False)

There's just that red line giving me troubles. Of course that's the original line, I've changed objUnit with iUnitID but that doesn't work. I've tried many different form of the code but I always get some exception there. I need to get the button for that UnitID but there's always a conflict with C++ code so I think I'm using wrong syntax for getting that iUnitID's button.

Edit: nevermind, I've solved it changing

Code:
screen.addCheckBoxGFCAt( "UnitPanel%s" %(iUnitID), "UnitCheckbox%s" %(iUnitID)
								[COLOR="Red"], gc.getUnitInfo(objUnit.getUnitType()).getButton()[/COLOR]
								, ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath()
								, 1, 2, 46, 46, WidgetTypes.WIDGET_GENERAL, iUnitID, iUnitID, ButtonStyles.BUTTON_STYLE_LABEL, False)

to

Code:
				screen.addCheckBoxGFCAt( "UnitPanel%s" %(iUnitID), "UnitCheckbox%s" %(iUnitID)
								, gc.getUnitInfo(objUnit).getButton()
								, ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath()
								, 1, 2, 46, 46, WidgetTypes.WIDGET_GENERAL, objUnit, objUnit, ButtonStyles.BUTTON_STYLE_LABEL, False)

defining objUnit = iUnitID.getUnitType()

MAD Nukes Screen will be back into service in my next commit (still looking after a couple of bugs).

Thanks for all your advices platyping!! :)
 
Code:
		iActivePlayer = CyGame().getActivePlayer()
		pPlayer = gc.getPlayer(iActivePlayer)
		sBorder = ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath()

		(pUnit, iter) = pPlayer.firstUnit(False)
		while(pUnit):
			iUnitID = [COLOR="red"]pUnit.getID()[/COLOR]
			self.selectedUnitHash[iUnitID] = False

			if pUnit.getUnitAIType() == UnitAITypes.UNITAI_ICBM:
				iTotalNukeCount += 1
				pPlot = pUnit.plot()
				pTargetPlot = pUnit.getMADTargetPlot()	
				if pTargetPlot and pTargetPlot.isCity() and pPlot.isCity():
					pTargetCity = [COLOR="Red"]pTargetPlot.getPlotCity()[/COLOR]
					sMainPanel = "UnitPanel%s" %(iUnitID)
					sInnerPanel = "UnitInnerPanel%s" %(iUnitID)
					screen.attachPanel(OUTGOING_WARHEADS_INNER_PANEL, sMainPanel, "", "", True, False, PanelStyles.PANEL_STYLE_OUT)
					screen.attachPanel(sMainPanel, sInnerPanel, "", "", True, False, PanelStyles.PANEL_STYLE_EMPTY)

					sLocate = CyTranslator().getText("TXT_KEY_MAD_LOCATE", (pPlot.getPlotCity().getName(),))
					sTarget = CyTranslator().getText("TXT_KEY_MAD_TARGET", (pTargetCity.getName(),))
					sOwner = CyTranslator().getText("TXT_KEY_MAD_CITY_OWNER", (gc.getPlayer(pTargetCity.getOwner()).getName(),))

					screen.attachLabel(sInnerPanel, sInnerPanel + "fill1", sLocate)
					screen.attachLabel(sInnerPanel, sInnerPanel + "fill2", sTarget)
					screen.attachLabel(sInnerPanel, sInnerPanel + "fill3", sOwner)
					screen.addCheckBoxGFCAt(sMainPanel, "UnitCheckbox%s" %(iUnitID), pUnit.getButton(), sBorder
						, 1, 2, 46, 46, WidgetTypes.WIDGET_GENERAL, -1, -1, ButtonStyles.BUTTON_STYLE_LABEL, False)
					iCounter +=1
			(pUnit, iter) = pPlayer.nextUnit(iter, False)

1) iUnitID in the original code stands for int Unit ID. Using it as the name of a CyUnit object will be misleading.

2) self.selectedUnitHash[iUnitID] is supposed to take in the Unit ID, but you pass in a CyUnit object.

3) "pass" keyword has no meaning in python. It is merely as a placeholder for future codes.
Whatever codes below will still be activated.

4) It is a pretty bad habit to hard code text which are to be displayed, such as " Located At: %s". When you code like this, there is no way to translate "Located At" to other languages. Use CyTranslater and type the corresponding text in Text XML files.

5) The texts are trying to display names for both the city the nuke is in, as well as the city the nuke is targeting. But there is no check for whether both cities exist in the first place. Tactical Nukes for instance, can be loaded in subs in BTS, though not sure if still do in AND. Hence, checks are added, but this will ignore nukes which are either not in cities, or not tageting cities.
 
Code:
iActivePlayer = CyGame().getActivePlayer()
pPlayer = gc.getPlayer(iActivePlayer)
sBorder = ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath()

(pUnit, iter) = pPlayer.firstUnit(False)
while(pUnit):
iUnitID = pUnit.getUnitID()
self.selectedUnitHash[iUnitID] = False

if pUnit.getUnitAIType() == UnitAITypes.UNITAI_ICBM:
iTotalNukeCount += 1
pPlot = pUnit.plot()
pTargetPlot = pUnit.getMADTargetPlot()
if pTargetPlot and pTargetPlot.isCity() and pPlot.isCity():
pTargetCity = pTargetPlot.getCity()
sMainPanel = "UnitPanel%s" %(iUnitID)
sInnerPanel = "UnitInnerPanel%s" %(iUnitID)
screen.attachPanel(OUTGOING_WARHEADS_INNER_PANEL, sMainPanel, "", "", True, False, PanelStyles.PANEL_STYLE_OUT)
screen.attachPanel(sMainPanel, sInnerPanel, "", "", True, False, PanelStyles.PANEL_STYLE_EMPTY)

sLocate = CyTranslator().getText("TXT_KEY_MAD_LOCATE", (pPlot.getPlotCity().getName(),))
sTarget = CyTranslator().getText("TXT_KEY_MAD_TARGET", (pTargetCity.getName(),))
sOwner = CyTranslator().getText("TXT_KEY_MAD_CITY_OWNER", (gc.getPlayer(pTargetCity.getOwner()).getName(),))

screen.attachLabel(sInnerPanel, sInnerPanel + "fill1", sLocate)
screen.attachLabel(sInnerPanel, sInnerPanel + "fill2", sTarget)
screen.attachLabel(sInnerPanel, sInnerPanel + "fill3", sOwner)
screen.addCheckBoxGFCAt(sMainPanel, "UnitCheckbox%s" %(iUnitID), pUnit.getButton(), sBorder
, 1, 2, 46, 46, WidgetTypes.WIDGET_GENERAL, -1, -1, ButtonStyles.BUTTON_STYLE_LABEL, False)
iCounter +=1
(pUnit, iter) = pPlayer.nextUnit(iter, False)

1) iUnitID in the original code stands for int Unit ID. Using it as the name of a CyUnit object will be misleading.

2) self.selectedUnitHash[iUnitID] is supposed to take in the Unit ID, but you pass in a CyUnit object.

3) "pass" keyword has no meaning in python. It is merely as a placeholder for future codes.
Whatever codes below will still be activated.

4) It is a pretty bad habit to hard code text which are to be displayed, such as " Located At: %s". When you code like this, there is no way to translate "Located At" to other languages. Use CyTranslater and type the corresponding text in Text XML files.

5) The texts are trying to display names for both the city the nuke is in, as well as the city the nuke is targeting. But there is no check for whether both cities exist in the first place. Tactical Nukes for instance, can be loaded in subs in BTS, though not sure if still do in AND. Hence, checks are added, but this will ignore nukes which are either not in cities, or not tageting cities.

1-2-3 noted, 4 I know, it's been like that for ages but I plan to change it.
5. code was supposed to work only for ICBM or city based units. I've considered making it valid for other nukes as well, but temporarily discarded the idea as too complicated.
 
Code:
		iActivePlayer = CyGame().getActivePlayer()
		pPlayer = gc.getPlayer(iActivePlayer)
		sBorder = ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath()

		(pUnit, iter) = pPlayer.firstUnit(False)
		while(pUnit):
			iUnitID = pUnit.getUnitID()
			self.selectedUnitHash[iUnitID] = False

			if pUnit.getUnitAIType() == UnitAITypes.UNITAI_ICBM:
				iTotalNukeCount += 1
				pPlot = pUnit.plot()
				pTargetPlot = pUnit.getMADTargetPlot()	
				if pTargetPlot and pTargetPlot.isCity() and pPlot.isCity():
					pTargetCity = pTargetPlot.getCity()
					sMainPanel = "UnitPanel%s" %(iUnitID)
					sInnerPanel = "UnitInnerPanel%s" %(iUnitID)
					screen.attachPanel(OUTGOING_WARHEADS_INNER_PANEL, sMainPanel, "", "", True, False, PanelStyles.PANEL_STYLE_OUT)
					screen.attachPanel(sMainPanel, sInnerPanel, "", "", True, False, PanelStyles.PANEL_STYLE_EMPTY)

					sLocate = CyTranslator().getText("TXT_KEY_MAD_LOCATE", (pPlot.getPlotCity().getName(),))
					sTarget = CyTranslator().getText("TXT_KEY_MAD_TARGET", (pTargetCity.getName(),))
					sOwner = CyTranslator().getText("TXT_KEY_MAD_CITY_OWNER", (gc.getPlayer(pTargetCity.getOwner()).getName(),))

					screen.attachLabel(sInnerPanel, sInnerPanel + "fill1", sLocate)
					screen.attachLabel(sInnerPanel, sInnerPanel + "fill2", sTarget)
					screen.attachLabel(sInnerPanel, sInnerPanel + "fill3", sOwner)
					screen.addCheckBoxGFCAt(sMainPanel, "UnitCheckbox%s" %(iUnitID), pUnit.getButton(), sBorder
						, 1, 2, 46, 46, WidgetTypes.WIDGET_GENERAL, -1, -1, ButtonStyles.BUTTON_STYLE_LABEL, False)
					iCounter +=1
			(pUnit, iter) = pPlayer.nextUnit(iter, False)

1) iUnitID in the original code stands for int Unit ID. Using it as the name of a CyUnit object will be misleading.

2) self.selectedUnitHash[iUnitID] is supposed to take in the Unit ID, but you pass in a CyUnit object.

3) "pass" keyword has no meaning in python. It is merely as a placeholder for future codes.
Whatever codes below will still be activated.

4) It is a pretty bad habit to hard code text which are to be displayed, such as " Located At: %s". When you code like this, there is no way to translate "Located At" to other languages. Use CyTranslater and type the corresponding text in Text XML files.

5) The texts are trying to display names for both the city the nuke is in, as well as the city the nuke is targeting. But there is no check for whether both cities exist in the first place. Tactical Nukes for instance, can be loaded in subs in BTS, though not sure if still do in AND. Hence, checks are added, but this will ignore nukes which are either not in cities, or not tageting cities.

Sorry, I've read your message from my phone and didn't realize that you actually posted corrected code. Thanks for that, but I've tried and it doesn't work. I get the same python exception I was getting earlier with some code I've tried, i.e.

iUnitID = pUnit.getUnitID() --> "'CyUnit' object has no attribute getUnitID"

Edit: and 'CyPlot' object has no attribute getCity

Edit2: I suppose this means that dll work is required on CyUnit and CyPlot
 
Was coding from memory and cannot test, edited the above codes.
 
Talking about Civilization, Platyping is the Python advisor ;)
 
There was still some errors because actual units, cities, etc weren't displayed. Only text was. No problem, I've been able to fix it. Next problem is now that flashing dots aren't being displayed on minimap, but I haven't looked into it yet.
 
Back
Top Bottom