Problems with adding a button

LoneTraveller

Warlord
Joined
Apr 30, 2008
Messages
283
Location
Montreal, Quebec
I'm working on creating a widget

I finished my SDK part of the mod now I'm having problems with the button creation. Specifically when I start the mod up I always get this error message and I don't understand what the python is reading. I looked in the python API and in theory it should work.

Here is the error log :

Code:
Traceback (most recent call last):

  File "CvScreensInterface", line 705, in forceScreenRedraw

  File "CvMainInterface", line 727, in redraw

  File "CvMainInterface", line 1541, in updateSelectionButtons

ArgumentError: Python argument types in
    CyGInterfaceScreen.appendMultiListButton(CyGInterfaceScreen, str, str, int, CvPythonExtensions.WidgetTypes, CyPlayer, int, bool)
did not match C++ signature:
    appendMultiListButton(class CyGInterfaceScreen {lvalue}, char const *, char const *, int, enum WidgetTypes, int, int, bool)
ERR: Python function forceScreenRedraw failed, module CvScreensInterface

Here is the code relating to the error message :

Code:
# Lone's Tanker Addon Start

					# Section for the unloading of Oil to cities
		
					pUnit = g_pSelectedUnit
					iUnitType = pUnit.getUnitType()
					pPlot = CyInterface().getSelectionPlot()
					pUnitOwner = gc.getPlayer( pUnit.getOwner( ))
					if pUnitOwner.isTurnActive( ):
						if iUnitType == gc.getInfoTypeForString('UNIT_TANKER') and pPlot.isCity() and pUnit.isTankerFull():							
							screen.appendMultiListButton( "BottomButtonContainer", ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTON_OIL").getPath(), 0, WidgetTypes.WIDGET_TANKER_UNLOAD_OIL, pUnitOwner, pUnit.getID(), False )
							pPlot.addOilToPlotGroup(NB_TURNS_OIL, pUnitOwner)
							screen.show( "BottomButtonContainer" )
							iCount = iCount + 1
					
					# Section for the loading of oil from oil producing cities
					pUnit = g_pSelectedUnit
					if pUnitOwner.isTurnActive( ):
						if iUnitType == gc.getInfoTypeForString('UNIT_TANKER') and (pPlot.getPlotCity()).hasBonus(gc.getInfoTypeForString('BONUS_OIL')) and (pUnit.isTankerFull()!= 1):			
							screen.appendMultiListButton( "BottomButtonContainer", ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTON_OIL").getPath(), 0, WidgetTypes.WIDGET_TANKER_LOAD_OIL, pUnitOwner, pUnit.getID(), False )	
							screen.show( "BottomButtonContainer" )
							iCount = iCount + 1

					# Lone's Tanker Addon End

It seems to think that the 1st parameter for the widget is a CyPlayer although when I searched this API (http://civ4bug.sourceforge.net/PythonAPI/index.html) it leads to an integer.

Please help

PS : the error is for the second "appendMultiListButton" the first one seems to pass.
 
In both calls to appendMultiListButton() you want to use

pUnitOwner.getID()

instead of

pUnitOwner​

You can also simplify your code a bit, and I think there's a bug. First, the simpler code:

Code:
					# Lone's Tanker Addon Start

					pUnit = g_pSelectedUnit
					iUnitType = pUnit.getUnitType()
					pPlot = CyInterface().getSelectionPlot()
					pUnitOwner = gc.getPlayer( pUnit.getOwner( ))
					if pUnitOwner.isTurnActive( ):
						if iUnitType == gc.getInfoTypeForString('UNIT_TANKER'):
							# Section for the unloading of Oil to cities
							if pPlot.isCity() and pUnit.isTankerFull():
								screen.appendMultiListButton( "BottomButtonContainer", ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTON_OIL").getPath(), 0, WidgetTypes.WIDGET_TANKER_UNLOAD_OIL, pUnitOwner, pUnit.getID(), False )
								pPlot.addOilToPlotGroup(NB_TURNS_OIL, pUnitOwner)
								screen.show( "BottomButtonContainer" )
								iCount = iCount + 1
							# Section for the loading of oil from oil producing cities
							if (pPlot.getPlotCity()).hasBonus(gc.getInfoTypeForString('BONUS_OIL')) and (pUnit.isTankerFull()!= 1):			
								screen.appendMultiListButton( "BottomButtonContainer", ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTON_OIL").getPath(), 0, WidgetTypes.WIDGET_TANKER_LOAD_OIL, pUnitOwner, pUnit.getID(), False )	
								screen.show( "BottomButtonContainer" )
								iCount = iCount + 1

					# Lone's Tanker Addon End

What I've done is test for the owner being active and the type of unit being a Tanker only once. For the bug, I'm guessing that the second block (loading oil) should be done on either a plot that has oil or a city that has access to oil. Either way, you are assuming the plot has a valid city, but the SDK code makes it look like it can return None. To fix it, change the if() test to this:

Code:
							pPlotCity = pPlot.getPlotCity()
							if (pPlotCity and pPlotCity.hasBonus(gc.getInfoTypeForString('BONUS_OIL')) and (pUnit.isTankerFull()!= 1):
 
Thanks !

That works great !

But now I have another problem. I added a text "field" for a tanker unit that I'm working on and it states the cargo status : empty/full on the bottom left part of the screen. Now when I 'fill up' that tanker with the action button in the above post, I would like it to immediatly show the modified status...much like experience points that have been spent will show a different ratio right after you 'buy' a promotion.

I have another question. Do all units from the same CvUnit share the SAME and UNIQUE CvUnitInfo ?

I another further question. What is the procedure to add an accessible variable (an integer) whose value would decrease by 1 every turn ?
 
But now I have another problem. I added a text "field" for a tanker unit that I'm working on and it states the cargo status : empty/full on the bottom left part of the screen.

I have done something similar with limited fuel in Fury Road. I used promotions which look like a fuel gauge: a full gauge, partly full, and empty. The code can easily swap one promotion to another. This seems easier than creating a whole widget and text display.

I have another question. Do all units from the same CvUnit share the SAME CvUnitInfo ? Please tell me no :(

They share the same CvUnitInfo, but not the same CvUnit. A lot of information such as the unitcombat is guaranteed to be the same among all of those units, so this is stored on the CvUnitInfo. Other information such as the x,y position is obviously different for each unit, so this is stored on the CvUnit. Is there something in the CvUnitInfo which you think should be on the CvUnit instead?

I another further question. What is the procedure to add an accessible variable (an integer) whose value would decrease by 1 every turn ?

You should use the ScriptData on the unit. It sounds like you are describing exactly the fuel system which already exists in Fury Road; perhaps you can download that and read the documentation and python to see if it does what you want.
 
I added a text "field" for a tanker unit that I'm working on and it states the cargo status : empty/full on the bottom left part of the screen. Now when I 'fill up' that tanker with the action button in the above post, I would like it to immediatly show the modified status...much like experience points that have been spent will show a different ratio right after you 'buy' a promotion.

You want to set the InfoPane dirty bit in the CyInterface I believe. Or possibly it's the unit info. You can see in CvMainInterface() the function that draws your widget. Trace back to the place that calls that function and you'll see which dirty bit is being checked.

Code:
CyInterface().setDirty(InterfaceDirtyBits.InfoPane_DIRTY_BIT, True)
 
Is there something in the CvUnitInfo which you think should be on the CvUnit instead?

No...I just plugged the relevant custom variables and accessors in the wrong object. The effect is that when I "load up" a tanker...they ALL load up. When 1 unloads...they all unload :lol:

Thanks for the indications concerning your mod. I will look into it.

To : EmperorFool : I have coded what you suggested with the UnitInfo_dirty_bit and will test it tomorrow.

Goodnight

PS : Is there a way to modify the "nature" of the conditions of "open borders" diplomatic status ? Specificially i want to stop "my" internal trade going through another nation's landmass or sealanes to reach another territory of mine. But I still want to be able to move ships across other nation's waters. The end result would be that only the resources from each territory is available to themselves. (not sure that I'm clear here...)
 
Back
Top Bottom