Quick Modding Questions Thread

I also have a question: I want to give city defenders the capability to withdraw to capital before they are killed. I have sucessfully implemented the effect itself, and combat ends with the defender being moved to the capital. However, during the entire combat animation the attacker faces toward the eventual location of the defender (i.e. the capital) instead of the previous one in the actual city being attacked. I checked but setFacingDirection() does not control this animation, so what does?

Edit: I worked around it.
 
Last edited:
Dang, I only found out that wasn't the case while looking through the mod files, I always just assumed it would be in both categories xD
 
Hi!

Can someone tell me where the size of tech icon is set for the Tech Tree screen?
I want to change this look in AND2
upload_2018-7-31_12-50-46-png.500614
into this look
upload_2018-7-31_12-51-46-png.500615


This is the CvTechChooser.py I want to edit:

Code:
## Sid Meier's Civilization 4
## Copyright Firaxis Games 2005
from CvPythonExtensions import *
import CvUtil
import ScreenInput
import CvScreenEnums
import CvScreensInterface

TEXTURE_SIZE = 24
X_START = 6
#X_INCREMENT = 27 # default BUG 27
X_INCREMENT = 24 # default BUG 27
Y_ROW = 32

CIV_HAS_TECH = 0
CIV_IS_RESEARCHING = 1
CIV_NO_RESEARCH = 2
CIV_TECH_AVAILABLE = 3

# globals
gc = CyGlobalContext()
ArtFileMgr = CyArtFileMgr()
localText = CyTranslator()

# BUG - GP Tech Prefs - start
import TechPrefs
import BugCore
BugOpt = BugCore.game.Advisors
ClockOpt = BugCore.game.NJAGC

import BugUtil

PREF_ICON_SIZE = 24
PREF_ICON_TOP = 168
PREF_ICON_LEFT = 10

FLAVORS = [ TechPrefs.FLAVOR_PRODUCTION, TechPrefs.FLAVOR_GOLD, TechPrefs.FLAVOR_SCIENCE,
            TechPrefs.FLAVOR_CULTURE, TechPrefs.FLAVOR_RELIGION, TechPrefs.FLAVOR_MILITARY,
            TechPrefs.FLAVOR_ESPIONAGE]
UNIT_CLASSES = [ "UNITCLASS_ENGINEER", "UNITCLASS_MERCHANT", "UNITCLASS_SCIENTIST",
                 "UNITCLASS_ARTIST", "UNITCLASS_PROPHET", "UNITCLASS_GREAT_GENERAL",
                 "UNITCLASS_GREAT_SPY"]
# BUG - GP Tech Prefs - end

# BUG - 3.19 No Espionage - start
import GameUtil
# BUG - 3.19 No Espionage - end

# BUG - Mac Support - start
BugUtil.fixSets(globals())
# BUG - Mac Support - end

# Rise of Mankind 2.91 - tech tree colors - start
RoMOpt = BugCore.game.RoMSettings
# Rise of Mankind 2.91 - tech tree colors - end

# BUG - Tech Era Colors - start
def getEraDescription(eWidgetType, iData1, iData2, bOption):
    return gc.getEraInfo(iData1).getDescription()
# BUG - Tech Era Colors - end

# BUG - GP Tech Prefs - start
def resetTechPrefs(args=[]):
    CvScreensInterface.techChooser.resetTechPrefs()

def getAllTechPrefsHover(widgetType, iData1, iData2, bOption):
    return buildTechPrefsHover("TXT_KEY_BUG_TECH_PREFS_ALL", CvScreensInterface.techChooser.pPrefs.getAllFlavorTechs(iData1))

def getCurrentTechPrefsHover(widgetType, iData1, iData2, bOption):
    return buildTechPrefsHover("TXT_KEY_BUG_TECH_PREFS_CURRENT", CvScreensInterface.techChooser.pPrefs.getCurrentFlavorTechs(iData1))

def getFutureTechPrefsHover(widgetType, iData1, iData2, bOption):
    pPlayer = gc.getPlayer(CvScreensInterface.techChooser.iCivSelected)
    sTechs = set()
    for i in range(gc.getNumTechInfos()):
        if (pPlayer.isResearchingTech(i)):
            sTechs.add(CvScreensInterface.techChooser.pPrefs.getTech(i))
    return buildTechPrefsHover("TXT_KEY_BUG_TECH_PREFS_FUTURE", CvScreensInterface.techChooser.pPrefs.getCurrentWithFlavorTechs(iData1, sTechs))

def buildTechPrefsHover(key, lTechs):
    szText = BugUtil.getPlainText(key) + "\n"
    for pTech in lTechs:
        szText += "<img=%s size=24></img>" % pTech.getInfo().getButton().replace(" ", "_")
    return szText
# BUG - GP Tech Prefs - end

class CvTechChooser:
    "Tech Chooser Screen"

    def __init__(self):
        self.nWidgetCount = 0
        self.iCivSelected = 0
        self.aiCurrentState = []

        # Advanced Start
        self.m_iSelectedTech = -1
        self.m_bSelectedTechDirty = False
        self.m_bTechRecordsDirty = False

# BUG - GP Tech Prefs - start
        self.bPrefsShowing = False
        self.resetTechPrefs()
# BUG - GP Tech Prefs - end
# Rise of Mankind 2.7 - more techs vertically
#        self.PIXEL_INCREMENT = 7 # BUG default 7
        self.PIXEL_INCREMENT = 10 # BUG default 7
        self.BOX_INCREMENT_WIDTH = 24 # Used to be 33 #Should be a multiple of 3...

#        self.BOX_INCREMENT_HEIGHT = 9 #Should be a multiple of 3...
        self.BOX_INCREMENT_HEIGHT = 6 #Should be a multiple of 3...
#        self.BOX_INCREMENT_Y_SPACING = 6 #Should be a multiple of 3...
        self.BOX_INCREMENT_Y_SPACING = 3 #Should be a multiple of 3...
# Rise of Mankind 2.7 - more techs vertically
        self.BOX_INCREMENT_X_SPACING = 9 # default 9, Should be a multiple of 3...

    def getScreen(self):
        return CyGInterfaceScreen( "TechChooser", CvScreenEnums.TECH_CHOOSER )

    def hideScreen (self):
        # Get the screen
        screen = self.getScreen()

        # Hide the screen
        screen.hideScreen()

    # Screen construction function
    def interfaceScreen(self):
#        BugUtil.debug("CvTechChooser: interfacescreen")
#        self.timer = BugUtil.Timer("CvTechChooser")

        if ( CyGame().isPitbossHost() ):
            return

        # Create a new screen, called TechChooser, using the file CvTechChooser.py for input
        screen = self.getScreen()
        screen.setRenderInterfaceOnly(True)
        screen.showScreen(PopupStates.POPUPSTATE_IMMEDIATE, False)

        screen.hide("AddTechButton")
        screen.hide("ASPointsLabel")
        screen.hide("SelectedTechLabel")

# BUG - GP Tech Prefs - start
        self.NO_TECH_ART = ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_CANCEL").getPath()
# BUG - GP Tech Prefs - end
            
        if ( CyGame().cheatCodesEnabled() or gc.getTeam(gc.getGame().getActiveTeam()).getNumMembers() > 1):
            screen.addDropDownBoxGFC( "CivDropDown", 22, 12, 192, WidgetTypes.WIDGET_GENERAL, -1, -1, FontTypes.SMALL_FONT )
            screen.setActivation( "CivDropDown", ActivationTypes.ACTIVATE_MIMICPARENTFOCUS )
            for j in range(gc.getMAX_PLAYERS()):
                if (gc.getPlayer(j).isAlive()):
                    if (CyGame().cheatCodesEnabled() or gc.getPlayer(j).getTeam() == gc.getGame().getActiveTeam()):
                        screen.addPullDownString( "CivDropDown", gc.getPlayer(j).getName(), j, j, False )
        else:
            screen.hide( "CivDropDown" )

        if ( screen.isPersistent() and self.iCivSelected == gc.getGame().getActivePlayer()):
            self.updateTechRecords(False)
            return

        self.nWidgetCount = 0
        self.sWidgets = []

        self.iCivSelected = gc.getGame().getActivePlayer()
        self.aiCurrentState = []
        screen.setPersistent( True )

        # Advanced Start
        if (gc.getPlayer(self.iCivSelected).getAdvancedStartPoints() >= 0):

            self.m_bSelectedTechDirty = True

            self.X_ADD_TECH_BUTTON = 10
            self.Y_ADD_TECH_BUTTON = 731
            self.W_ADD_TECH_BUTTON = 150
            self.H_ADD_TECH_BUTTON = 30
            self.X_ADVANCED_START_TEXT = self.X_ADD_TECH_BUTTON + self.W_ADD_TECH_BUTTON + 20

            szText = localText.getText("TXT_KEY_WB_AS_ADD_TECH", ())
            screen.setButtonGFC( "AddTechButton", szText, "", self.X_ADD_TECH_BUTTON, self.Y_ADD_TECH_BUTTON, self.W_ADD_TECH_BUTTON, self.H_ADD_TECH_BUTTON, WidgetTypes.WIDGET_GENERAL, -1, -1, ButtonStyles.BUTTON_STYLE_STANDARD )
            screen.hide("AddTechButton")

# BUG - Tech Screen Resolution - start
        if (BugOpt.isWideTechScreen() and screen.getXResolution() > 1024):
            xPanelWidth = screen.getXResolution() - 60
        else:
            xPanelWidth = 1024
        yPanelHeight = 768

        screen.showWindowBackground( False )
        screen.setDimensions((screen.getXResolution() - xPanelWidth) / 2, screen.centerY(0), xPanelWidth, yPanelHeight)
# BUG - Tech Screen Resolution - end

        screen.addPanel( "TechTopPanel", u"", u"", True, False, 0, 0, xPanelWidth, 55, PanelStyles.PANEL_STYLE_TOPBAR )
        screen.addDDSGFC("TechBG", ArtFileMgr.getInterfaceArtInfo("SCREEN_BG_OPAQUE").getPath(), 0, 51, xPanelWidth, yPanelHeight - 96, WidgetTypes.WIDGET_GENERAL, -1, -1 )
        screen.addPanel( "TechBottomPanel", u"", u"", True, False, 0, yPanelHeight - 55, xPanelWidth, 55, PanelStyles.PANEL_STYLE_BOTTOMBAR )
        screen.setText( "TechChooserExit", "Background", u"<font=4>" + CyTranslator().getText("TXT_KEY_PEDIA_SCREEN_EXIT", ()).upper() + "</font>", CvUtil.FONT_RIGHT_JUSTIFY, xPanelWidth - 30, yPanelHeight - 42, 0, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_CLOSE_SCREEN, -1, -1 )
        screen.setActivation( "TechChooserExit", ActivationTypes.ACTIVATE_MIMICPARENTFOCUS )

        # Header...
        szText = u"<font=4>"
        szText = szText + localText.getText("TXT_KEY_TECH_CHOOSER_TITLE", ()).upper()
        szText = szText + u"</font>"
        screen.setLabel( "TechTitleHeader", "Background", szText, CvUtil.FONT_CENTER_JUSTIFY, xPanelWidth / 2, 8, 0, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1 )

        # Make the scrollable area for the city list...
        if BugOpt.isShowGPTechPrefs():
            iX = 80
            iW = xPanelWidth - 80
        else:
            iX = 0
            iW = xPanelWidth

        self.TabPanels = ["TechList", "TechTrade"]

        screen.addScrollPanel(self.TabPanels[0], u"", iX, 64, iW, yPanelHeight - 142, PanelStyles.PANEL_STYLE_EXTERNAL )
        screen.setActivation(self.TabPanels[0], ActivationTypes.ACTIVATE_NORMAL )

        screen.addScrollPanel(self.TabPanels[1], u"", 80, 64, xPanelWidth - 80, yPanelHeight - 142, PanelStyles.PANEL_STYLE_EXTERNAL )
        screen.setActivation(self.TabPanels[1], ActivationTypes.ACTIVATE_NORMAL )

# BUG - GP Tech Prefs - start
        if BugOpt.isShowGPTechPrefs():
            screen.addPanel("GPTechPref", u"", u"", True, False, 0, 51, 80, yPanelHeight - 95, PanelStyles.PANEL_STYLE_MAIN_WHITE )
# BUG - GP Tech Prefs - end

        # Add the Highlight
        #screen.addDDSGFC( "TechHighlight", ArtFileMgr.getInterfaceArtInfo("TECH_HIGHLIGHT").getPath(), 0, 0, self.getXStart() + 6, 12 + ( self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT ), WidgetTypes.WIDGET_GENERAL, -1, -1 )
        #screen.hide( "TechHighlight" )

        self.X_SELECT_TAB = 30
        self.X_TRADE_TAB = 165
        self.Y_TABS = 730

        self.sTechSelectTab = self.getNextWidgetName("TechSelectTab")
        self.sTechTradeTab = self.getNextWidgetName("TechTradeTab")
        self.sTechTabID = self.sTechSelectTab

        # reset widget array so that the above never get deleted
        self.nWidgetCount = 0
        self.sWidgets = []

        self.ConstructTabs()

        self.ShowTab()

        return

    def ConstructTabs(self):
#        BugUtil.debug("cvTechChooser: ConstructTabs")

        screen = self.getScreen()

# Rise of Mankind 2.7
#        self.BOX_INCREMENT_WIDTH = 33 # Used to be 33 #Should be a multiple of 3...
        self.BOX_INCREMENT_WIDTH = 24 # Used to be 33 #Should be a multiple of 3...
# Rise of Mankind 2.7
        self.DrawTechChooser(screen, self.TabPanels[0], True, True, True, True, True, True)




        self.BOX_INCREMENT_WIDTH = 12 # Used to be 33 #Should be a multiple of 3... BUG default 12
        self.DrawTechChooser(screen, self.TabPanels[1], True, False, True, False, False, True)
# Rise of Mankind 2.7       
#        self.BOX_INCREMENT_WIDTH = 33 # Used to be 33 #Should be a multiple of 3...
        self.BOX_INCREMENT_WIDTH = 24 # Used to be 33 #Should be a multiple of 3...
# Rise of Mankind 2.7
#    def DrawTechChooser(self, screen, sPanel, bTechPanel, bTechName, bTechIcon, bTechDetails, bANDPreReq, bORPreReq):



    def ShowTab(self):
#        BugUtil.debug("cvTechChooser: ShowTab")

        screen = self.getScreen()

        for tp in self.TabPanels:
            screen.hide(tp)

        # remove these 2 lines when we return to multi-tab screen and uncomment out the 10 below.
        screen.show(self.TabPanels[0])
        screen.setFocus(self.TabPanels[0])

#        if(self.sTechTabID == self.sTechSelectTab):
#            screen.setText(self.sTechSelectTab, "", "Tech Select", CvUtil.FONT_LEFT_JUSTIFY, self.X_SELECT_TAB, self.Y_TABS, 0, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)
#            screen.setText(self.sTechTradeTab, "", "Tech Trade - under development", CvUtil.FONT_LEFT_JUSTIFY, self.X_TRADE_TAB, self.Y_TABS, 0, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)
#            screen.show(self.TabPanels[0])
#            screen.setFocus(self.TabPanels[0])

#        elif(self.sTechTabID == self.sTechTradeTab):
#            screen.setText(self.sTechSelectTab, "", "Tech Select", CvUtil.FONT_LEFT_JUSTIFY, self.X_SELECT_TAB, self.Y_TABS, 0, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)
#            screen.setText(self.sTechTradeTab, "", "Tech Trade - under development", CvUtil.FONT_LEFT_JUSTIFY, self.X_TRADE_TAB, self.Y_TABS, 0, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)
#            screen.show(self.TabPanels[1])
#            screen.setFocus(self.TabPanels[1])


    def DrawTechChooser(self, screen, sPanel, bTechPanel, bTechName, bTechIcon, bTechDetails, bANDPreReq, bORPreReq):
#        BugUtil.debug("cvTechChooser: DrawTechChooser (%s)", sPanel)
#        self.timer.reset()
#        self.timer.start()

        # Place the tech blocks
        self.placeTechs(screen, sPanel, bTechPanel, bTechName, bTechIcon, bTechDetails)

        # Draw the arrows
        self.drawArrows(screen, sPanel, bANDPreReq, bORPreReq)

        self.updateTechPrefs()

        screen.moveToFront( "CivDropDown" )

        screen.moveToFront( "AddTechButton" )

#        self.timer.logSpan("total")

    def placeTechs(self, screen, sPanel, bTechPanel, bTechName, bTechIcon, bTechDetails):
#        BugUtil.debug("cvTechChooser: placeTechs")

        iMaxX = 0
        iMaxY = 0

        if sPanel == self.TabPanels[0]:
            sPanelWidget = ""
        else:
            sPanelWidget = sPanel

        # If we are the Pitboss, we don't want to put up an interface at all
        if ( CyGame().isPitbossHost() ):
            return

        # Cache some tech infos
        self.createTechInfoCache()

        # Go through all the techs
        for i in range(gc.getNumTechInfos()):

#Afforess Skip Mountaineering w/o Mountains Mod
            if (not gc.getPlayer(0).canEverResearch(i)) : continue
            # Create and place a tech in its proper location
            iX = 30 + ( (gc.getTechInfo(i).getGridX() - 1) * ( ( self.BOX_INCREMENT_X_SPACING + self.BOX_INCREMENT_WIDTH ) * self.PIXEL_INCREMENT ) )
# Rise of Mankind 2.7 - more techs vertically
#            iY = ( gc.getTechInfo(i).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT ) + 5
            iY = ( gc.getTechInfo(i).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT )
# Rise of Mankind 2.7 - more techs vertically
            szTechRecord = sPanelWidget + "TechRecord" + str(i)

            if ( iMaxX < iX + self.getXStart() ):
                iMaxX = iX + self.getXStart()
            if ( iMaxY < iY + ( self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT ) ):
                iMaxY = iY + ( self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT )

# BUG - Tech Era Colors - start
            szTechRecordShadow = sPanelWidget + "TechRecordShadow" + str(i)
            iShadowOffset = 9
            screen.attachPanelAt( sPanel, szTechRecordShadow, u"", u"", True, False, PanelStyles.PANEL_STYLE_TECH, iX - 6 + iShadowOffset, iY - 6 + iShadowOffset, self.getXStart() + 6, 12 + ( self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT ), WidgetTypes.WIDGET_TECH_CHOOSER_ERA, gc.getTechInfo(i).getEra(), -1 )
            self.setTechPanelShadowColor(screen, szTechRecordShadow, gc.getTechInfo(i).getEra())
            screen.hide( szTechRecordShadow )
# BUG - Tech Era Colors - end

            screen.attachPanelAt( sPanel, szTechRecord, u"", u"", True, False, PanelStyles.PANEL_STYLE_TECH, iX - 6, iY - 6, self.getXStart() + 6, 12 + ( self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT ), WidgetTypes.WIDGET_TECH_TREE, i, -1 )
            screen.setActivation( szTechRecord, ActivationTypes.ACTIVATE_MIMICPARENTFOCUS)
            screen.hide( szTechRecord )

            #reset so that it offsets from the tech record's panel
            iX = 6
            iY = 6

            if ( gc.getTeam(gc.getPlayer(self.iCivSelected).getTeam()).isHasTech(i) ):
                screen.setPanelColor(szTechRecord, 0, 0, 0)
                self.aiCurrentState.append(CIV_HAS_TECH)
            elif ( gc.getPlayer(self.iCivSelected).getCurrentResearch() == i ):
                screen.setPanelColor(szTechRecord, 0, 0, 200)
                self.aiCurrentState.append(CIV_IS_RESEARCHING)
            elif ( gc.getPlayer(self.iCivSelected).isResearchingTech(i) ):
                screen.setPanelColor(szTechRecord, 200, 0, 0)
                self.aiCurrentState.append(CIV_IS_RESEARCHING)
            elif ( gc.getPlayer(self.iCivSelected).canEverResearch(i) ):
# Rise of Mankind 2.91 - tech tree colors - start
                if (RoMOpt.isRoMTechTreeColors()):
                    # Ancient Era
                    if ( gc.getTechInfo(i).getEra() == 0 ):
                        screen.setPanelColor(szTechRecord, 160, 100, 160)
                    # Classical Era
                    elif ( gc.getTechInfo(i).getEra() == 1 ):
                        screen.setPanelColor(szTechRecord, 160, 100, 100)
                    # Medieval Era
                    elif ( gc.getTechInfo(i).getEra() == 2 ):
                        screen.setPanelColor(szTechRecord, 160, 160, 100)
                    # Renaissance Era
                    elif ( gc.getTechInfo(i).getEra() == 3 ):
                        screen.setPanelColor(szTechRecord, 160, 160, 50)
                    # Industrial Era
                    elif ( gc.getTechInfo(i).getEra() == 4 ):
                        screen.setPanelColor(szTechRecord, 60, 200, 60)
                    # Modern Era
                    elif ( gc.getTechInfo(i).getEra() == 5 ):
                        screen.setPanelColor(szTechRecord, 100, 104, 160)
                    # Future Era
                    else:
                        screen.setPanelColor(szTechRecord, 50, 160, 250)
                else:
                    screen.setPanelColor(szTechRecord, 100, 104, 160)
# Rise of Mankind 2.91 - tech tree colors - end
                self.aiCurrentState.append(CIV_NO_RESEARCH)
            else:
                screen.setPanelColor(szTechRecord, 206, 65, 69)
                self.aiCurrentState.append(CIV_TECH_AVAILABLE)

            if bTechName:
                szTechID = sPanelWidget + "TechID" + str(i)
                szTechString = "<font=1>"
                if ( gc.getPlayer(self.iCivSelected).isResearchingTech(i) ):
                    szTechString = szTechString + str(gc.getPlayer(self.iCivSelected).getQueuePosition(i)) + ". "
                szTechString += gc.getTechInfo(i).getDescription()
                szTechString = szTechString + "</font>"
                screen.setTextAt( szTechID, szTechRecord, szTechString, CvUtil.FONT_LEFT_JUSTIFY, iX + 6 + X_INCREMENT, iY + 6, -0.1, FontTypes.SMALL_FONT, WidgetTypes.WIDGET_TECH_TREE, i, -1 )
                screen.setActivation( szTechID, ActivationTypes.ACTIVATE_MIMICPARENTFOCUS )

            if bTechIcon:
                szTechButtonID = sPanelWidget + "TechButtonID" + str(i)
                screen.addDDSGFCAt( szTechButtonID, szTechRecord, gc.getTechInfo(i).getButton(), iX + 6, iY + 6, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_TECH_TREE, i, -1, False )

            if bTechDetails:
                self.addIconsToTechPanel(screen, i, X_START, iX, iY, szTechRecord)

            if bTechPanel:
                if BugOpt.isShowTechEra():
                    screen.show( szTechRecordShadow )
                else:
                    screen.hide( szTechRecordShadow )
                screen.show( szTechRecord )
            else:
                screen.hide( szTechRecordShadow )
                screen.hide( szTechRecord )

        # delete the tech info cache
        self.deleteTechInfoCache()
        
        screen.setViewMin( sPanel, iMaxX + 20, iMaxY + 20 )

        return

    
    def createTechInfoCache(self):
            
        self.UnitCache = dict()
            
        for j in range( gc.getNumUnitClassInfos() ):
            eLoopUnit = gc.getCivilizationInfo(gc.getGame().getActiveCivilizationType()).getCivilizationUnits(j)
            if (gc.getGame().canEverTrain(eLoopUnit)):
                ePrereq = gc.getUnitInfo(eLoopUnit).getPrereqAndTech()
                if (ePrereq != TechTypes.NO_TECH):
                    if (ePrereq not in self.UnitCache):
                        self.UnitCache[ePrereq] = list()
                    self.UnitCache[ePrereq].append(eLoopUnit)
                        
            
        self.BuildingCache = dict()
        self.BuildingObsoleteCache = dict()
        
        for j in range(gc.getNumBuildingClassInfos()):
            eLoopBuilding = gc.getCivilizationInfo(gc.getGame().getActiveCivilizationType()).getCivilizationBuildings(j)

            if (gc.getGame().canEverConstruct(eLoopBuilding)):
                ePrereq = gc.getBuildingInfo(eLoopBuilding).getPrereqAndTech()
                if (ePrereq != TechTypes.NO_TECH):
                    if (ePrereq not in self.BuildingCache):
                        self.BuildingCache[ePrereq] = list()
                    self.BuildingCache[ePrereq].append(eLoopBuilding)
                                            
                eObsolete = gc.getBuildingInfo(eLoopBuilding).getObsoleteTech()
                if (eObsolete != TechTypes.NO_TECH):
                    if (eObsolete not in self.BuildingObsoleteCache):
                        self.BuildingObsoleteCache[eObsolete] = list()
                    self.BuildingObsoleteCache[eObsolete].append(eLoopBuilding)
                                            
                
    def deleteTechInfoCache(self):
        del self.UnitCache
        del self.BuildingCache
        del self.BuildingObsoleteCache
            

    def addIconsToTechPanel(self, screen, i, fX, iX, iY, szTechRecord):
        BugUtil.debug("CvTechChooser: addIconsToTechPanel")

        j = 0
        k = 0
        iCount = 0
        if (not gc.getPlayer(0).canEverResearch(i)):
            return
        
        
        # Unlockable units...
        if (i in self.UnitCache):
            for eLoopUnit in self.UnitCache[i]:
                szUnitButton = self.getNextWidgetName("Unit")
                iCount += 1
                if (iCount < 10):
                    screen.addDDSGFCAt( szUnitButton, szTechRecord, gc.getPlayer(gc.getGame().getActivePlayer()).getUnitButton(eLoopUnit), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_PEDIA_JUMP_TO_UNIT, eLoopUnit, 1, True )
                    fX += X_INCREMENT
                        
        #for j in range( gc.getNumUnitClassInfos() ):
        #    eLoopUnit = gc.getCivilizationInfo(gc.getGame().getActiveCivilizationType()).getCivilizationUnits(j)
        #    if (gc.getGame().canEverTrain(eLoopUnit)):
        #        if (gc.getUnitInfo(eLoopUnit).getPrereqAndTech() == i):
        #            szUnitButton = self.getNextWidgetName("Unit")
        #            iCount += 1
        #            if (iCount < 10):
        #                screen.addDDSGFCAt( szUnitButton, szTechRecord, gc.getPlayer(gc.getGame().getActivePlayer()).getUnitButton(eLoopUnit), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_PEDIA_JUMP_TO_UNIT, eLoopUnit, 1, True )
        #                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 1")

        # Unlockable Buildings...
        if (i in self.BuildingCache):
            for eLoopBuilding in self.BuildingCache[i]:
                szBuildingButton = self.getNextWidgetName("Building")
                iCount += 1
                if (iCount < 10):
                    screen.addDDSGFCAt( szBuildingButton, szTechRecord, gc.getBuildingInfo(eLoopBuilding).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_PEDIA_JUMP_TO_BUILDING, eLoopBuilding, 1, True )
                    fX += X_INCREMENT
                    
        #for j in range(gc.getNumBuildingClassInfos()):
        #    bTechFound = 0
        #    eLoopBuilding = gc.getCivilizationInfo(gc.getGame().getActiveCivilizationType()).getCivilizationBuildings(j)

        #    if (gc.getGame().canEverConstruct(eLoopBuilding)):
        #        if (gc.getBuildingInfo(eLoopBuilding).getPrereqAndTech() == i):
        #            szBuildingButton = self.getNextWidgetName("Building")
        #            iCount += 1
        #            if (iCount < 10):
        #                screen.addDDSGFCAt( szBuildingButton, szTechRecord, gc.getBuildingInfo(eLoopBuilding).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_PEDIA_JUMP_TO_BUILDING, eLoopBuilding, 1, True )
        #                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 2")
        # Obsolete Buildings...
        if (i in self.BuildingObsoleteCache):
            for eLoopBuilding in self.BuildingObsoleteCache[i]:
                # Add obsolete picture here...
                szObsoleteButton = self.getNextWidgetName("Obsolete")
                szObsoleteX = self.getNextWidgetName("ObsoleteX")
                iCount += 1
                if (iCount < 10):
                    screen.addDDSGFCAt( szObsoleteButton, szTechRecord, gc.getBuildingInfo(eLoopBuilding).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_OBSOLETE, eLoopBuilding, -1, False )
                    screen.addDDSGFCAt( szObsoleteX, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_RED_X").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_OBSOLETE, eLoopBuilding, -1, False )
                    fX += X_INCREMENT
                    
        #for j in range(gc.getNumBuildingClassInfos()):
        #    eLoopBuilding = gc.getCivilizationInfo(gc.getPlayer(self.iCivSelected).getCivilizationType()).getCivilizationBuildings(j)

        #    if (gc.getGame().canEverConstruct(eLoopBuilding)):
        #        if (gc.getBuildingInfo(eLoopBuilding).getObsoleteTech() == i):
                    # Add obsolete picture here...
        #            szObsoleteButton = self.getNextWidgetName("Obsolete")
        #            szObsoleteX = self.getNextWidgetName("ObsoleteX")
        #            iCount += 1
        #            if (iCount < 10):
        #                screen.addDDSGFCAt( szObsoleteButton, szTechRecord, gc.getBuildingInfo(eLoopBuilding).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_OBSOLETE, eLoopBuilding, -1, False )
        #                screen.addDDSGFCAt( szObsoleteX, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_RED_X").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_OBSOLETE, eLoopBuilding, -1, False )
        #                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 3")
        # Obsolete Bonuses...
        for j in range(gc.getNumBonusInfos()):
            if (gc.getBonusInfo(j).getTechObsolete() == i):
                # Add obsolete picture here...
                szObsoleteButton = self.getNextWidgetName("ObsoleteBonus")
                szObsoleteX = self.getNextWidgetName("ObsoleteXBonus")
                iCount += 1
                if (iCount < 10):
                    screen.addDDSGFCAt( szObsoleteButton, szTechRecord, gc.getBonusInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_OBSOLETE_BONUS, j, -1, False )
                    screen.addDDSGFCAt( szObsoleteX, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_RED_X").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_OBSOLETE_BONUS, j, -1, False )
                    fX += X_INCREMENT
                    
        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 4")
        # Obsolete Monastaries...
        for j in range (gc.getNumSpecialBuildingInfos()):
            if (gc.getSpecialBuildingInfo(j).getObsoleteTech() == i):
                    # Add obsolete picture here...
                    szObsoleteSpecialButton = self.getNextWidgetName("ObsoleteSpecial")
                    szObsoleteSpecialX = self.getNextWidgetName("ObsoleteSpecialX")
                    iCount += 1
                    if (iCount < 10):
                        screen.addDDSGFCAt( szObsoleteSpecialButton, szTechRecord, gc.getSpecialBuildingInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_OBSOLETE_SPECIAL, j, -1, False )
                        screen.addDDSGFCAt( szObsoleteSpecialX, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_RED_X").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_OBSOLETE_SPECIAL, j, -1, False )
                        fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 5")
        # Route movement change
        for j in range(gc.getNumRouteInfos()):
            if ( gc.getRouteInfo(j).getTechMovementChange(i) != 0 ):
                szMoveButton = self.getNextWidgetName("Move")
                iCount += 1
                if (iCount < 10):
                    screen.addDDSGFCAt( szMoveButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_MOVE_BONUS").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_MOVE_BONUS, i, -1, False )
                    fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 6")
        # Promotion Info
        for j in range( gc.getNumPromotionInfos() ):
            if ( gc.getPromotionInfo(j).getTechPrereq() == i ):
                szPromotionButton = self.getNextWidgetName("Promotion")
                iCount += 1
                if (iCount < 10):
                    screen.addDDSGFCAt( szPromotionButton, szTechRecord, gc.getPromotionInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_PEDIA_JUMP_TO_PROMOTION, j, -1, False )
                    fX += X_INCREMENT
                    
            elif ( gc.getPromotionInfo(j).getObsoleteTech() == i ):
                szPromotionButton = self.getNextWidgetName("Promotion")
                szObsoleteX = self.getNextWidgetName("ObsoleteX")
                iCount += 1
                if (iCount < 10):
                    screen.addDDSGFCAt( szPromotionButton, szTechRecord, gc.getPromotionInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_OBSOLETE_PROMOTION, j, -1, False )
                    screen.addDDSGFCAt( szObsoleteX, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_RED_X").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_OBSOLETE_PROMOTION, j, -1, False )
                    fX += X_INCREMENT
        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 7")
        # Free unit
        if ( gc.getTechInfo(i).getFirstFreeUnitClass() != UnitClassTypes.NO_UNITCLASS ):
            szFreeUnitButton = self.getNextWidgetName("FreeUnit")
            eLoopUnit = gc.getCivilizationInfo(gc.getGame().getActiveCivilizationType()).getCivilizationUnits(gc.getTechInfo(i).getFirstFreeUnitClass())
            if (eLoopUnit != -1):
# BUG - 3.19 No Espionage - start
                # CvUnitInfo.getEspionagePoints() was added in 319
                if (GameUtil.getVersion() < 319 or gc.getUnitInfo(eLoopUnit).getEspionagePoints() == 0 or not gc.getGame().isOption(GameOptionTypes.GAMEOPTION_NO_ESPIONAGE)):               
# BUG - 3.19 No Espionage - end
                    iCount += 1
                    if (iCount < 10):
                        screen.addDDSGFCAt( szFreeUnitButton, szTechRecord, gc.getPlayer(gc.getGame().getActivePlayer()).getUnitButton(eLoopUnit), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_FREE_UNIT, eLoopUnit, i, False )
                        fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 8")
        # Feature production modifier
        if ( gc.getTechInfo(i).getFeatureProductionModifier() != 0 ):
            szFeatureProductionButton = self.getNextWidgetName("FeatureProduction")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szFeatureProductionButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_FEATURE_PRODUCTION").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_FEATURE_PRODUCTION, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 9")
        # Worker speed
        if ( gc.getTechInfo(i).getWorkerSpeedModifier() != 0 ):
            szWorkerModifierButton = self.getNextWidgetName("Worker")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szWorkerModifierButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_WORKER_SPEED").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_WORKER_RATE, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 10")
        # Trade Routes per City change
        if ( gc.getTechInfo(i).getTradeRoutes() != 0 ):
            szTradeRouteButton = self.getNextWidgetName("TradeRoutes")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szTradeRouteButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_TRADE_ROUTES").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_TRADE_ROUTES, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 11")
        # Health Rate bonus from this tech...
        if ( gc.getTechInfo(i).getHealth() != 0 ):
            szHealthRateButton = self.getNextWidgetName("HealthRate")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szHealthRateButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_HEALTH").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_HEALTH_RATE, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 12")
        # Happiness Rate bonus from this tech...
        if ( gc.getTechInfo(i).getHappiness() != 0 ):
            szHappinessRateButton = self.getNextWidgetName("HappinessRate")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szHappinessRateButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_HAPPINESS").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_HAPPINESS_RATE, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 13")
        # Free Techs
        if ( gc.getTechInfo(i).getFirstFreeTechs() > 0 ):
            szFreeTechButton = self.getNextWidgetName("FreeTech")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szFreeTechButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_FREETECH").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_FREE_TECH, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 14")
        # Line of Sight bonus...
        if ( gc.getTechInfo(i).isExtraWaterSeeFrom() ):
            szLOSButton = self.getNextWidgetName("LOS")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szLOSButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_LOS").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_LOS_BONUS, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 14")
        # Map Center Bonus...
        if ( gc.getTechInfo(i).isMapCentering() ):
            szMapCenterButton = self.getNextWidgetName("MapCenter")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szMapCenterButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_MAPCENTER").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_MAP_CENTER, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 15")
        # Map Reveal...
        if ( gc.getTechInfo(i).isMapVisible() ):
            szMapRevealButton = self.getNextWidgetName("MapReveal")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szMapRevealButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_MAPREVEAL").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_MAP_REVEAL, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 16")
        # Map Trading
        if ( gc.getTechInfo(i).isMapTrading() == True ):
            szMapTradeButton = self.getNextWidgetName("MapTrade")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szMapTradeButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_MAPTRADING").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_MAP_TRADE, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 17")
        # Tech Trading
        if ( gc.getTechInfo(i).isTechTrading() ):
            szTechTradeButton = self.getNextWidgetName("TechTrade")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szTechTradeButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_TECHTRADING").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_TECH_TRADE, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 18")
        # Gold Trading
        if ( gc.getTechInfo(i).isGoldTrading() ):
            szGoldTradeButton = self.getNextWidgetName("GoldTrade")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szGoldTradeButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_GOLDTRADING").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_GOLD_TRADE, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 19")
        # Open Borders
        if ( gc.getTechInfo(i).isOpenBordersTrading() ):
            szOpenBordersButton = self.getNextWidgetName("OpenBorders")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szOpenBordersButton , szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_OPENBORDERS").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_OPEN_BORDERS, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 20")
        # Defensive Pact
        if ( gc.getTechInfo(i).isDefensivePactTrading() ):
            szDefensivePactButton = self.getNextWidgetName("DefensivePact")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szDefensivePactButton , szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_DEFENSIVEPACT").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_DEFENSIVE_PACT, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 21")
        # Permanent Alliance
        if ( gc.getTechInfo(i).isPermanentAllianceTrading() ):
            szPermanentAllianceButton = self.getNextWidgetName("PermanentAlliance")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szPermanentAllianceButton , szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_PERMALLIANCE").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_PERMANENT_ALLIANCE, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 22")
        # Vassal States
        if ( gc.getTechInfo(i).isVassalStateTrading() ):
            szVassalStateButton = self.getNextWidgetName("VassalState")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szVassalStateButton , szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_VASSAL").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_VASSAL_STATE, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 23")
        # Bridge Building
        if ( gc.getTechInfo(i).isBridgeBuilding() ):
            szBuildBridgeButton = self.getNextWidgetName("BuildBridge")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szBuildBridgeButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_BRIDGEBUILDING").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_BUILD_BRIDGE, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 24")
        # Irrigation unlocked...
        if ( gc.getTechInfo(i).isIrrigation() ):
            szIrrigationButton = self.getNextWidgetName("Irrigation")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szIrrigationButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_IRRIGATION").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_IRRIGATION, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 25")
        # Ignore Irrigation unlocked...
        if ( gc.getTechInfo(i).isIgnoreIrrigation() ):
            szIgnoreIrrigationButton = self.getNextWidgetName("IgnoreIrrigation")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szIgnoreIrrigationButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_NOIRRIGATION").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_IGNORE_IRRIGATION, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 26")
        # Coastal Work unlocked...
        if ( gc.getTechInfo(i).isWaterWork() ):
            szWaterWorkButton = self.getNextWidgetName("WaterWork")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szWaterWorkButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_WATERWORK").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_WATER_WORK, i, -1, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 27")
        # Improvements
        for j in range(gc.getNumBuildInfos()):
            bTechFound = False;

            if (gc.getBuildInfo(j).getTechPrereq() == -1):
                bTechFound = False
                for k in range(gc.getNumFeatureInfos()):
                    if (gc.getBuildInfo(j).getFeatureTech(k) == i):
                        bTechFound = True
            else:
                if (gc.getBuildInfo(j).getTechPrereq() == i):
                    bTechFound = True

            if (bTechFound):
                iCount += 1
                if (iCount < 10):
                    szImprovementButton = self.getNextWidgetName("Improvement")
                    screen.addDDSGFCAt( szImprovementButton, szTechRecord, gc.getBuildInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_IMPROVEMENT, i, j, False )
                    fX += X_INCREMENT
                    
                    
        j = 0
        k = 0

        BugUtil.debug("CvTechChooser: Marker 28")       
        # Improvements Can Upgrade
        for j in range(gc.getNumImprovementInfos()):
            if (gc.getImprovementInfo(j).getPrereqTech() == i):
                if (gc.getImprovementInfo(j).getImprovementPillage() != -1):
                    iCount += 1
                    if (iCount < 10):
                        szImprovementButton = self.getNextWidgetName("Improvement")
                        screen.addDDSGFCAt( szImprovementButton, szTechRecord, gc.getImprovementInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_IMPROVEMENT_CAN_UPGRADE, j, j, False )
                        fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 29")
        # Domain Extra Moves
        for j in range( DomainTypes.NUM_DOMAIN_TYPES ):
            if (gc.getTechInfo(i).getDomainExtraMoves(j) != 0):
                iCount += 1
                if (iCount < 10):
                    szDomainExtraMovesButton = self.getNextWidgetName("DomainExtraMoves")
                    screen.addDDSGFCAt( szDomainExtraMovesButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_WATERMOVES").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_DOMAIN_EXTRA_MOVES, i, j, False )
                    fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 30")
        # Adjustments
        for j in range( CommerceTypes.NUM_COMMERCE_TYPES ):
            if (gc.getTechInfo(i).isCommerceFlexible(j) and not (gc.getTeam(gc.getPlayer(self.iCivSelected).getTeam()).isCommerceFlexible(j))):
                szAdjustButton = self.getNextWidgetName("AdjustButton")
                if ( j == CommerceTypes.COMMERCE_CULTURE ):
                    szFileName = ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_CULTURE").getPath()
                elif ( j == CommerceTypes.COMMERCE_ESPIONAGE ):
                    szFileName = ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_ESPIONAGE").getPath()
                else:
                    szFileName = ArtFileMgr.getInterfaceArtInfo("INTERFACE_GENERAL_QUESTIONMARK").getPath()
                iCount += 1
                if (iCount < 10):
                    screen.addDDSGFCAt( szAdjustButton, szTechRecord, szFileName, iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_ADJUST, i, j, False )
                    fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 31")
        # Terrain opens up as a trade route
        for j in range( gc.getNumTerrainInfos() ):
            if (gc.getTechInfo(i).isTerrainTrade(j) and not (gc.getTeam(gc.getPlayer(self.iCivSelected).getTeam()).isTerrainTrade(j))):
                iCount += 1
                if (iCount < 10):
                    szTerrainTradeButton = self.getNextWidgetName("TerrainTradeButton")
                    screen.addDDSGFCAt( szTerrainTradeButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_WATERTRADE").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_TERRAIN_TRADE, i, j, False )
                    fX += X_INCREMENT

        j = gc.getNumTerrainInfos()   
        if (gc.getTechInfo(i).isRiverTrade() and not (gc.getTeam(gc.getPlayer(self.iCivSelected).getTeam()).isRiverTrade())):
            szTerrainTradeButton = self.getNextWidgetName("TerrainTradeButton")
            iCount += 1
            if (iCount < 10):
                screen.addDDSGFCAt( szTerrainTradeButton, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_TECH_RIVERTRADE").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_TERRAIN_TRADE, i, j, False )
                fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 32")
        # Special buildings like monestaries...
        for j in range( gc.getNumSpecialBuildingInfos() ):
            if (gc.getSpecialBuildingInfo(j).getTechPrereq() == i):
                iCount += 1
                if (iCount < 10):
                    szSpecialBuilding = self.getNextWidgetName("SpecialBuildingButton")
                    screen.addDDSGFCAt( szSpecialBuilding, szTechRecord, gc.getSpecialBuildingInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_SPECIAL_BUILDING, i, j, False )
                    fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 33")
        # Yield change
        for j in range( gc.getNumImprovementInfos() ):
            bFound = False
            for k in range( YieldTypes.NUM_YIELD_TYPES ):
                if (gc.getImprovementInfo(j).getTechYieldChanges(i, k)):
                    if ( bFound == False ):
                        iCount += 1
                        if (iCount < 10):
                            szYieldChange = self.getNextWidgetName("YieldChangeButton")
                            screen.addDDSGFCAt( szYieldChange, szTechRecord, gc.getImprovementInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_YIELD_CHANGE, i, j, False )
                            fX += X_INCREMENT
                            bFound = True

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 34")
        # Bonuses revealed
        for j in range( gc.getNumBonusInfos() ):
            if (gc.getBonusInfo(j).getTechReveal() == i):
                iCount += 1
                if (iCount < 10):
                    szBonusReveal = self.getNextWidgetName("BonusRevealButton")
                    screen.addDDSGFCAt( szBonusReveal, szTechRecord, gc.getBonusInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_BONUS_REVEAL, i, j, False )
                    fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 35")
        # Civic options
        for j in range( gc.getNumCivicInfos() ):
            if (gc.getCivicInfo(j).getTechPrereq() == i):
                iCount += 1
                if (iCount < 10):
                    szCivicReveal = self.getNextWidgetName("CivicRevealButton")
                    screen.addDDSGFCAt( szCivicReveal, szTechRecord, gc.getCivicInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_CIVIC_REVEAL, i, j, False )
                    fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 36")
        # Projects possible
        for j in range( gc.getNumProjectInfos() ):
            if (gc.getProjectInfo(j).getTechPrereq() == i):
                iCount += 1
                if (iCount < 10):
                    szProjectInfo = self.getNextWidgetName("ProjectInfoButton")
                    screen.addDDSGFCAt( szProjectInfo, szTechRecord, gc.getProjectInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_PEDIA_JUMP_TO_PROJECT, j, 1, False )
                    fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 37")
        # Processes possible
        for j in range( gc.getNumProcessInfos() ):
            if (gc.getProcessInfo(j).getTechPrereq() == i):
                iCount += 1
                if (iCount < 10):
                    szProcessInfo = self.getNextWidgetName("ProcessInfoButton")
                    screen.addDDSGFCAt( szProcessInfo, szTechRecord, gc.getProcessInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_PROCESS_INFO, i, j, False )
                    fX += X_INCREMENT

        j = 0
        k = 0
        BugUtil.debug("CvTechChooser: Marker 38")
        # Religions unlocked
        for j in range( gc.getNumReligionInfos() ):
            if ( gc.getReligionInfo(j).getTechPrereq() == i ):
                szFoundReligion = self.getNextWidgetName("FoundReligionButton")
                if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_PICK_RELIGION):
                    szButton = ArtFileMgr.getInterfaceArtInfo("INTERFACE_POPUPBUTTON_RELIGION").getPath()
                else:
                    szButton = gc.getReligionInfo(j).getButton()
                iCount += 1
                if (iCount < 10):
                    screen.addDDSGFCAt( szFoundReligion, szTechRecord, szButton, iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_FOUND_RELIGION, i, j, False )
                    fX += X_INCREMENT
        BugUtil.debug("CvTechChooser: Marker 39")
        #Corporations Unlocked
        for j in range( gc.getNumCorporationInfos() ):
            if (gc.getGame().canEverSpread(j) ):
                if ( gc.getCorporationInfo(j).getTechPrereq() == i ):
                    iCount += 1
                    if (iCount < 10):
                        szFoundCorporation = self.getNextWidgetName("FoundCorporationButton")
                        screen.addDDSGFCAt( szFoundCorporation, szTechRecord, gc.getCorporationInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_FOUND_CORPORATION, i, j, False )
                        fX += X_INCREMENT
                elif (gc.getCorporationInfo(j).getObsoleteTech() == i):
                    iCount += 1
                    if (iCount < 10):
                        szCorporation = self.getNextWidgetName("FoundCorporationButton")
                        szObsoleteX = self.getNextWidgetName("ObsoleteX")
                        screen.addDDSGFCAt( szCorporation, szTechRecord, gc.getCorporationInfo(j).getButton(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_OBSOLETE_CORPORATION, i, j, False )
                        screen.addDDSGFCAt( szObsoleteX, szTechRecord, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_RED_X").getPath(), iX + fX, iY + Y_ROW, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_OBSOLETE_CORPORATION, j, -1, False )
            

    # Will update the tech records based on color, researching, researched, queued, etc.
    def updateTechRecords (self, bForce):
#        BugUtil.debug("cvTechChooser: updateTechRecords")

        # If we are the Pitboss, we don't want to put up an interface at all
        if ( CyGame().isPitbossHost() ):
            return

        if (self.sTechTabID == self.sTechSelectTab):
            bTechName = True
            sPanel = self.TabPanels[0]
# Rise of Mankind 2.7
            self.BOX_INCREMENT_WIDTH = 24 # Used to be 33 #Should be a multiple of 3...
# Rise of Mankind 2.7
        else:
            bTechName = False
            sPanel = self.TabPanels[1]
            self.BOX_INCREMENT_WIDTH = 12 # Used to be 33 #Should be a multiple of 3...

        # Get the screen
        screen = self.getScreen()

        abChanged = []
        bAnyChanged = 0

        # Go through all the techs
        for i in range(gc.getNumTechInfos()):

            abChanged.append(0)
            
            if (not gc.getPlayer(0).canEverResearch(i)): continue

            if ( gc.getTeam(gc.getPlayer(self.iCivSelected).getTeam()).isHasTech(i) ):
                if ( self.aiCurrentState[i] != CIV_HAS_TECH ):
                    self.aiCurrentState[i] = CIV_HAS_TECH
                    abChanged[i] = 1
                    bAnyChanged = 1
            elif ( gc.getPlayer(self.iCivSelected).getCurrentResearch() == i ):
                if ( self.aiCurrentState[i] != CIV_IS_RESEARCHING ):
                    self.aiCurrentState[i] = CIV_IS_RESEARCHING
                    abChanged[i] = 1
                    bAnyChanged = 1
            elif ( gc.getPlayer(self.iCivSelected).isResearchingTech(i) ):
                if ( self.aiCurrentState[i] != CIV_IS_RESEARCHING ):
                    self.aiCurrentState[i] = CIV_IS_RESEARCHING
                    abChanged[i] = 1
                    bAnyChanged = 1
            elif ( gc.getPlayer(self.iCivSelected).canEverResearch(i) ):
                if ( self.aiCurrentState[i] != CIV_NO_RESEARCH ):
                    self.aiCurrentState[i] = CIV_NO_RESEARCH
                    abChanged[i] = 1
                    bAnyChanged = 1
            else:
                if ( self.aiCurrentState[i] != CIV_TECH_AVAILABLE ):
                    self.aiCurrentState[i] = CIV_TECH_AVAILABLE
                    abChanged[i] = 1
                    bAnyChanged = 1

        for i in range(gc.getNumTechInfos()):
            if (abChanged[i] or bForce or (bAnyChanged and gc.getPlayer(self.iCivSelected).isResearchingTech(i))):
                # Create and place a tech in its proper location
                szTechRecord = "TechRecord" + str(i)
                szTechID = "TechID" + str(i)
                szTechString = "<font=1>"

                if ( gc.getPlayer(self.iCivSelected).isResearchingTech(i) ):
                    szTechString = szTechString + unicode(gc.getPlayer(self.iCivSelected).getQueuePosition(i)) + ". "

                iX = 30 + ( (gc.getTechInfo(i).getGridX() - 1) * ( ( self.BOX_INCREMENT_X_SPACING + self.BOX_INCREMENT_WIDTH ) * self.PIXEL_INCREMENT ) )
# Rise of Mankind 2.7 - more techs vertically
                iY = ( gc.getTechInfo(i).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT )
# Rise of Mankind 2.7 - more techs vertically
                if bTechName:
                    szTechString += gc.getTechInfo(i).getDescription()
                    if ( gc.getPlayer(self.iCivSelected).isResearchingTech(i) ):
                        szTechString += " ("
                        szTechString += str(gc.getPlayer(self.iCivSelected).getResearchTurnsLeft(i, ( gc.getPlayer(self.iCivSelected).getCurrentResearch() == i )))
                        szTechString += ")"
                    szTechString = szTechString + "</font>"
                    screen.setTextAt( szTechID, sPanel, szTechString, CvUtil.FONT_LEFT_JUSTIFY, iX + 6 + X_INCREMENT, iY + 6, -0.1, FontTypes.SMALL_FONT, WidgetTypes.WIDGET_TECH_TREE, i, -1 )
                    screen.setActivation( szTechID, ActivationTypes.ACTIVATE_MIMICPARENTFOCUS )

                if ( gc.getTeam(gc.getPlayer(self.iCivSelected).getTeam()).isHasTech(i) ):
                    screen.setPanelColor(szTechRecord, 0, 0, 0)
                elif ( gc.getPlayer(self.iCivSelected).getCurrentResearch() == i ):
                    screen.setPanelColor(szTechRecord, 0, 0, 200)
                elif ( gc.getPlayer(self.iCivSelected).isResearchingTech(i) ):
                    screen.setPanelColor(szTechRecord, 200, 0, 0)
                elif ( gc.getPlayer(self.iCivSelected).canEverResearch(i) ):
# Rise of Mankind 2.91 - tech tree colors - start
                    if (RoMOpt.isRoMTechTreeColors()):
                        # Ancient Era
                        if ( gc.getTechInfo(i).getEra() == 0 ):
                            screen.setPanelColor(szTechRecord, 160, 100, 160)
                        # Classical Era
                        elif ( gc.getTechInfo(i).getEra() == 1 ):
                            screen.setPanelColor(szTechRecord, 160, 100, 100)
                        # Medieval Era
                        elif ( gc.getTechInfo(i).getEra() == 2 ):
                            screen.setPanelColor(szTechRecord, 160, 160, 100)
                        # Renaissance Era
                        elif ( gc.getTechInfo(i).getEra() == 3 ):
                            screen.setPanelColor(szTechRecord, 160, 160, 50)
                        # Industrial Era
                        elif ( gc.getTechInfo(i).getEra() == 4 ):
                            screen.setPanelColor(szTechRecord, 60, 200, 60)
                        # Modern Era
                        elif ( gc.getTechInfo(i).getEra() == 5 ):
                            screen.setPanelColor(szTechRecord, 100, 104, 160)
                        # Future Era
                        else:
                            screen.setPanelColor(szTechRecord, 50, 160, 250)
                            #screen.setPanelColor(szTechRecord, 0, 160, 160)
                    else:
                        screen.setPanelColor(szTechRecord, 100, 104, 160)
# Rise of Mankind 2.91 - tech tree colors - end
                else:
                    screen.setPanelColor(szTechRecord, 206, 65, 69)

# BUG - GP Tech Prefs - start
        self.updateTechPrefs()
# BUG - GP Tech Prefs - end

# BUG - Tech Era Colors - start
    def setTechPanelShadowColor(self, screen, sPanel, iEra):
        szEra = gc.getEraInfo(iEra).getType()
        iColor = ClockOpt.getEraColor(szEra)
        if iColor != -1:
            color = gc.getColorInfo(iColor)
            if color:
                rgb = color.getColor() # NiColorA object
                if rgb:
                    screen.setPanelColor(sPanel, int(100 * rgb.r), int(100 * rgb.g), int(100 * rgb.b))
# BUG - Tech Era Colors - end

    # Will draw the arrows
    def drawArrows(self, screen, sPanel, bANDPreReq, bORPreReq):
#        BugUtil.debug("cvTechChooser: drawArrows")

        iLoop = 0

        ARROW_X = ArtFileMgr.getInterfaceArtInfo("ARROW_X").getPath()
        ARROW_Y = ArtFileMgr.getInterfaceArtInfo("ARROW_Y").getPath()
        ARROW_MXMY = ArtFileMgr.getInterfaceArtInfo("ARROW_MXMY").getPath()
        ARROW_XY = ArtFileMgr.getInterfaceArtInfo("ARROW_XY").getPath()
        ARROW_MXY = ArtFileMgr.getInterfaceArtInfo("ARROW_MXY").getPath()
        ARROW_XMY = ArtFileMgr.getInterfaceArtInfo("ARROW_XMY").getPath()
        ARROW_HEAD = ArtFileMgr.getInterfaceArtInfo("ARROW_HEAD").getPath()

        for i in range(gc.getNumTechInfos()):
            bFirst = 1
            fX = (self.BOX_INCREMENT_WIDTH * self.PIXEL_INCREMENT) - 8
            if (not gc.getPlayer(0).canEverResearch(i)) : continue
            if bANDPreReq:
                numTechOverrides = gc.getTechInfo(i).getNumTechArrowOverrides()
                for j in range( gc.getNUM_AND_TECH_PREREQS() ):
                    eTech = gc.getTechInfo(i).getPrereqAndTechs(j)
                    if (numTechOverrides > 0):
                        for k in range (numTechOverrides):
                            fTech = gc.getTechInfo(i).getTechArrowOverride(k)
                            if ( eTech > -1 and eTech != fTech):
                                fX = fX - X_INCREMENT
                                iX = 30 + ( (gc.getTechInfo(i).getGridX() - 1) * ( ( self.BOX_INCREMENT_X_SPACING + self.BOX_INCREMENT_WIDTH ) * self.PIXEL_INCREMENT ) )
# Rise of Mankind 2.7 - more techs vertically
#                                iY = ( gc.getTechInfo(i).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT ) + 5
                                iY = ( gc.getTechInfo(i).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT )
# Rise of Mankind 2.7 - more techs vertically
                                szTechPrereqID = "TechPrereqID" + str((i * 1000) + j)
                                screen.addDDSGFCAt( szTechPrereqID, sPanel, gc.getTechInfo(eTech).getButton(), iX + fX, iY + 6, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_TECH_PREPREQ, eTech, -1, False )
                                #szTechPrereqBorderID = "TechPrereqBorderID" + str((i * 1000) + j)
                                #screen.addDDSGFCAt( szTechPrereqBorderID, sPanel, ArtFileMgr.getInterfaceArtInfo("TECH_TREE_BUTTON_BORDER").getPath(), iX + fX + 4, iY + 22, 32, 32, WidgetTypes.WIDGET_HELP_TECH_PREPREQ, eTech, -1, False )
                    else:
                        if ( eTech > -1):
                            fX = fX - X_INCREMENT
                            iX = 30 + ( (gc.getTechInfo(i).getGridX() - 1) * ( ( self.BOX_INCREMENT_X_SPACING + self.BOX_INCREMENT_WIDTH ) * self.PIXEL_INCREMENT ) )
# Rise of Mankind 2.7 - more techs vertically
#                            iY = ( gc.getTechInfo(i).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT ) + 5
                            iY = ( gc.getTechInfo(i).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT )
# Rise of Mankind 2.7 - more techs vertically
                            szTechPrereqID = "TechPrereqID" + str((i * 1000) + j)
                            screen.addDDSGFCAt( szTechPrereqID, sPanel, gc.getTechInfo(eTech).getButton(), iX + fX, iY + 6, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_HELP_TECH_PREPREQ, eTech, -1, False )
                            #szTechPrereqBorderID = "TechPrereqBorderID" + str((i * 1000) + j)
                            #screen.addDDSGFCAt( szTechPrereqBorderID, sPanel, ArtFileMgr.getInterfaceArtInfo("TECH_TREE_BUTTON_BORDER").getPath(), iX + fX + 4, iY + 22, 32, 32, WidgetTypes.WIDGET_HELP_TECH_PREPREQ, eTech, -1, False )


            j = 0

            if bORPreReq:
                numTechOverrides = gc.getTechInfo(i).getNumTechArrowOverrides()
                BugUtil.info("CvTechChooser: Num Tech Overrides for " + gc.getTechInfo(i).getDescription() + " is " + str(numTechOverrides))
                for j in range( max(gc.getNUM_OR_TECH_PREREQS(), numTechOverrides) ):
                    if (numTechOverrides > 0):
                        if (j >= numTechOverrides):
                            eTech = -1
                        else:
                            eTech = gc.getTechInfo(i).getTechArrowOverride(j)
                            BugUtil.info("CvTechChooser: Tech Overrides for " + gc.getTechInfo(i).getDescription() + " is " + gc.getTechInfo(eTech).getDescription())
                    else:
                        eTech = gc.getTechInfo(i).getPrereqOrTechs(j)
                        
                    if ( eTech > -1 ):
                        iX = 24 + ( (gc.getTechInfo(eTech).getGridX() - 1) * ( ( self.BOX_INCREMENT_X_SPACING + self.BOX_INCREMENT_WIDTH ) * self.PIXEL_INCREMENT ) )
                        iY = ( gc.getTechInfo(eTech).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT ) + 5

                        # j is the pre-req, i is the tech...
                        xDiff = gc.getTechInfo(i).getGridX() - gc.getTechInfo(eTech).getGridX()
                        yDiff = gc.getTechInfo(i).getGridY() - gc.getTechInfo(eTech).getGridY()

# Rise of Mankind - more techs vertically
                        if (yDiff == 0):
                            screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + self.getXStart(), iY + self.getYStart(3) + 1, self.getWidth(xDiff), 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                            screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_HEAD, iX + self.getXStart() + self.getWidth(xDiff), iY + self.getYStart(3) + 1, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                        elif (yDiff < 0):
                            if ( yDiff == -6 ):
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + self.getXStart(), iY + self.getYStart(1) + 10, self.getWidth(xDiff) / 2, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_XY, iX + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + self.getYStart(1) + 10, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_Y, iX + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + self.getYStart(1) + 8 - self.getHeight(yDiff, 0) + 125, 8, self.getHeight(yDiff, 0) - 8 - 115, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_XMY, iX + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + self.getYStart(1) - self.getHeight(yDiff, 0) + 125, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + 8 + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + self.getYStart(1) - self.getHeight(yDiff, 0) + 125, ( self.getWidth(xDiff) / 2 ) - 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_HEAD, iX + self.getXStart() + self.getWidth(xDiff), iY + self.getYStart(1) - self.getHeight(yDiff, 0) + 125, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                            elif ( yDiff == -2 and xDiff == 2 ):
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + self.getXStart(), iY + self.getYStart(2) + 10, self.getWidth(xDiff) * 5 / 6, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_XY, iX + self.getXStart() + ( self.getWidth(xDiff) * 5 / 6 ), iY + self.getYStart(2) + 10, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_Y, iX + self.getXStart() + ( self.getWidth(xDiff) * 5 / 6 ), iY + self.getYStart(2) + 8 - ( self.getHeight(yDiff, 3) / 2 ) + 15, 8, ( self.getHeight(yDiff, 3) / 2 ) - 8 - 5, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_XMY, iX + self.getXStart() + ( self.getWidth(xDiff) * 5 / 6 ), iY + self.getYStart(2) - ( self.getHeight(yDiff, 3) / 2 ) + 15, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + 8 + self.getXStart() + ( self.getWidth(xDiff) * 5 / 6 ), iY + self.getYStart(2) - ( self.getHeight(yDiff, 3) / 2 ) + 15, ( self.getWidth(xDiff) / 6 ) - 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_HEAD, iX + self.getXStart() + self.getWidth(xDiff), iY + self.getYStart(2) - ( self.getHeight(yDiff, 3) / 2 ) + 15, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                            else:
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + self.getXStart(), iY + self.getYStart(2) - 5, self.getWidth(xDiff) / 2, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_XY, iX + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + self.getYStart(2) - 5, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_Y, iX + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + ( self.getYStart(2) / 2 ) + 8 - ( self.getHeight(yDiff, 3) / 2 ) + 10, 8, ( self.getHeight(yDiff, 3) / 2 ) - 8 - 10, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_XMY, iX + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + ( self.getYStart(2) / 2 ) - ( self.getHeight(yDiff, 3) / 2 ) + 10, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + 8 + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + ( self.getYStart(2) / 2 ) - ( self.getHeight(yDiff, 3) / 2 ) + 10, ( self.getWidth(xDiff) / 2 ) - 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_HEAD, iX + self.getXStart() + self.getWidth(xDiff), iY + ( self.getYStart(2) / 2 ) - ( self.getHeight(yDiff, 3) / 2 ) + 10, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                        elif (yDiff > 0):
                            if ( yDiff == 2 and xDiff == 2):
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + self.getXStart(), iY + self.getYStart(4) * 2 - 15, self.getWidth(xDiff) / 6, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_MXMY, iX + self.getXStart() + ( self.getWidth(xDiff) / 6 ), iY + self.getYStart(4) * 2 - 15, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_Y, iX + self.getXStart() + ( self.getWidth(xDiff) / 6 ), iY + self.getYStart(4) * 2 + 8 - 15, 8, ( self.getHeight(yDiff, 3) / 2 ) - 8 - 30, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_MXY, iX + self.getXStart() + ( self.getWidth(xDiff) / 6 ), iY + self.getYStart(4) / 2 + ( self.getHeight(yDiff, 3) / 2 ), 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + 8 + self.getXStart() + ( self.getWidth(xDiff) / 6 ), iY + self.getYStart(4) / 2 + ( self.getHeight(yDiff, 3) / 2 ), ( self.getWidth(xDiff) * 5 / 6 ) - 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_HEAD, iX + self.getXStart() + self.getWidth(xDiff), iY + self.getYStart(4) / 2 + ( self.getHeight(yDiff, 3) / 2 ), 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                            elif ( yDiff == 4 and xDiff == 1):
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + self.getXStart(), iY + self.getYStart(5), self.getWidth(xDiff) / 3, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_MXMY, iX + self.getXStart() + ( self.getWidth(xDiff) / 3 ), iY + self.getYStart(5), 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_Y, iX + self.getXStart() + ( self.getWidth(xDiff) / 3 ), iY + self.getYStart(5) + 8, 8, self.getHeight(yDiff, 0) - 8 - 95, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_MXY, iX + self.getXStart() + ( self.getWidth(xDiff) / 3 ), iY + self.getYStart(5) + self.getHeight(yDiff, 0) - 100, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + 8 + self.getXStart() + ( self.getWidth(xDiff) / 3 ), iY + self.getYStart(5) + self.getHeight(yDiff, 0) - 100, ( self.getWidth(xDiff) * 2 / 3 ) - 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_HEAD, iX + self.getXStart() + self.getWidth(xDiff), iY + self.getYStart(5) + self.getHeight(yDiff, 0) - 100, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                            else:
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + self.getXStart(), iY + self.getYStart(4) + 5, self.getWidth(xDiff) / 2, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_MXMY, iX + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + self.getYStart(4) + 5, 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_Y, iX + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + self.getYStart(4) + 8 + 5, 8, ( self.getHeight(yDiff, 3) / 2 ) - 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_MXY, iX + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + self.getYStart(4) + (self.getHeight(yDiff, 3) / 2 ), 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_X, iX + 8 + self.getXStart() + ( self.getWidth(xDiff) / 2 ), iY + self.getYStart(4) + (self.getHeight(yDiff, 3) / 2 ), ( self.getWidth(xDiff) / 2 ) - 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )
                                screen.addDDSGFCAt( self.getNextWidgetName("TechArrow"), sPanel, ARROW_HEAD, iX + self.getXStart() + self.getWidth(xDiff), iY + self.getYStart(4) + (self.getHeight(yDiff, 3) / 2 ), 8, 8, WidgetTypes.WIDGET_GENERAL, -1, -1, False )

# Rise of Mankind 2.7 - more techs vertically

        return

# BUG - GP Tech Prefs - start
    def resetTechPrefs (self):
        self.pPrefs = TechPrefs.TechPrefs()
    
    def updateTechPrefs (self):
#        BugUtil.debug("cvTechChooser: updateTechPrefs")

        # If we are the Pitboss, we don't want to put up an interface at all
        if ( CyGame().isPitbossHost() ):
            return

        # These don't seem to be setup when screen is first opened
        if (gc.getNumTechInfos() <= 0 or gc.getNumFlavorTypes() <= 0):
            return

        # Get the screen and player
        screen = self.getScreen()
        pPlayer = gc.getPlayer(self.iCivSelected)

        # Don't show tech prefs during advanced start setup
        if (pPlayer.getAdvancedStartPoints() >= 0):
            return

        # Check to see if option is disabled
        if (not BugOpt.isShowGPTechPrefs()):
            if (self.bPrefsShowing):
                # ... and if so, remove icons if they are currently showing
                screen.hide( "GreatPersonHeading")
                for i, f in enumerate(FLAVORS):
                    screen.hide( "GreatPerson" + str(f) )
                    screen.hide( "GreatPersonTech" + str(f) )
                    screen.hide( "GreatPersonTechNext" + str(f) )
                self.bPrefsShowing = False
            return
        # Always redraw the GP icons because otherwise they are prone to disappearing
        # discover icon heading
        iIconSize = 48
        iX = PREF_ICON_LEFT + 5 * PREF_ICON_SIZE / 4 - iIconSize / 2
        iY = PREF_ICON_TOP - iIconSize - 40
        screen.addDDSGFC( "GreatPersonHeading", ArtFileMgr.getInterfaceArtInfo("DISCOVER_TECHNOLOGY_BUTTON").getPath(), iX, iY, iIconSize, iIconSize, WidgetTypes.WIDGET_GENERAL, -1, -1 )

        for i, f in enumerate(FLAVORS):
            # GP icon
            iUnitClass = gc.getInfoTypeForString(UNIT_CLASSES[i])
            iUnitType = gc.getUnitClassInfo(iUnitClass).getDefaultUnitIndex()
            pUnitInfo = gc.getUnitInfo(iUnitType)
            iX = PREF_ICON_LEFT
            iY = PREF_ICON_TOP + 4 * i * PREF_ICON_SIZE
            screen.addDDSGFC( "GreatPerson" + str(f), pUnitInfo.getButton(), iX, iY, PREF_ICON_SIZE, PREF_ICON_SIZE, WidgetTypes.WIDGET_TECH_PREFS_ALL, f, -1 )
        self.bPrefsShowing = True

        # Remove any techs researched since last call, creating tree if necessary
        if (not self.pPrefs):
            self.resetTechPrefs()
        self.pPrefs.removeKnownTechs()

        # Add all techs in research queue to set of soon-to-be-known techs
        sTechs = set()
        for i in range(gc.getNumTechInfos()):
            if (pPlayer.isResearchingTech(i)):
                sTechs.add(self.pPrefs.getTech(i))

        # Update the buttons to reflect the new tech prefs
        for i, f in enumerate(FLAVORS):
            # GP button
            screen.show( "GreatPerson" + str(f) )

            # Current tech GP will pop
            szButtonName = "GreatPersonTech" + str(f)
            pTech = self.pPrefs.getNextResearchableFlavorTech(f)
            iX = PREF_ICON_LEFT + 3 * PREF_ICON_SIZE / 2
            iY = PREF_ICON_TOP + 4 * i * PREF_ICON_SIZE
            if (pTech):
                screen.addDDSGFC( szButtonName, pTech.getInfo().getButton(), iX, iY, PREF_ICON_SIZE, PREF_ICON_SIZE, WidgetTypes.WIDGET_TECH_PREFS_CURRENT, f, -1 )
            else:
                screen.addDDSGFC( szButtonName, self.NO_TECH_ART, iX, iY, PREF_ICON_SIZE, PREF_ICON_SIZE, WidgetTypes.WIDGET_TECH_PREFS_CURRENT, f, -1 )
            screen.show( szButtonName )

            # Tech GP will pop once selected techs are researched
            szButtonName = "GreatPersonTechNext" + str(f)
            pTech = self.pPrefs.getNextResearchableWithFlavorTech(f, sTechs)
            iX = PREF_ICON_LEFT + 3 * PREF_ICON_SIZE / 2
            iY = PREF_ICON_TOP + 4 * i * PREF_ICON_SIZE + 3 * PREF_ICON_SIZE / 2
            if (pTech):
                screen.addDDSGFC( szButtonName, pTech.getInfo().getButton(), iX, iY, PREF_ICON_SIZE, PREF_ICON_SIZE, WidgetTypes.WIDGET_TECH_PREFS_FUTURE, f, -1 )
            else:
                screen.addDDSGFC( szButtonName, self.NO_TECH_ART, iX, iY, PREF_ICON_SIZE, PREF_ICON_SIZE, WidgetTypes.WIDGET_TECH_PREFS_FUTURE, f, -1 )
            screen.show( szButtonName )
# BUG - GP Tech Prefs - end

    def TechRecord (self, inputClass):
        return 0

    # Clicked the parent?
    def ParentClick (self, inputClass):
        return 0

    def CivDropDown( self, inputClass ):
        if ( inputClass.getNotifyCode() == NotifyCode.NOTIFY_LISTBOX_ITEM_SELECTED ):
            screen = self.getScreen()
            iIndex = screen.getSelectedPullDownID("CivDropDown")
            self.iCivSelected = screen.getPullDownData("CivDropDown", iIndex)
            self.updateTechRecords(False)

    # Will handle the input for this screen...
    def handleInput (self, inputClass):
#        BugUtil.debug("cvTechChooser: handleInput")
#        BugUtil.debugInput(inputClass)

        # Get the screen
        screen = self.getScreen()

        szWidgetName = inputClass.getFunctionName() + str(inputClass.getID())

        # Advanced Start Stuff
        pPlayer = gc.getPlayer(self.iCivSelected)
        if (pPlayer.getAdvancedStartPoints() >= 0):
#            BugUtil.debug("cvTechChooser: handleInput - advancedstart")
            # Add tech button
            if (inputClass.getFunctionName() == "AddTechButton"):
                if (pPlayer.getAdvancedStartTechCost(self.m_iSelectedTech, True) != -1):
                    CyMessageControl().sendAdvancedStartAction(AdvancedStartActionTypes.ADVANCEDSTARTACTION_TECH, self.iCivSelected, -1, -1, self.m_iSelectedTech, True)    #Action, Player, X, Y, Data, bAdd
                    self.m_bTechRecordsDirty = True
                    self.m_bSelectedTechDirty = True

            # Tech clicked on
            elif (inputClass.getNotifyCode() == NotifyCode.NOTIFY_CLICKED):
                if (inputClass.getButtonType() == WidgetTypes.WIDGET_TECH_TREE):
                    self.m_iSelectedTech = inputClass.getData1()
                    self.updateSelectedTech()

        ' Calls function mapped in TechChooserInputMap'
        # only get from the map if it has the key
        if ( inputClass.getNotifyCode() == NotifyCode.NOTIFY_LISTBOX_ITEM_SELECTED ):
#            BugUtil.debug("cvTechChooser: handleInput - dropdown")
            self.CivDropDown( inputClass )
            return 1

        if (inputClass.getNotifyCode() == NotifyCode.NOTIFY_CLICKED):
            if szWidgetName == self.sTechSelectTab:
                self.sTechTabID = self.sTechSelectTab
                self.ShowTab()

            elif szWidgetName == self.sTechTradeTab:
                self.sTechTabID = self.sTechTradeTab
                self.ShowTab()



        return 0

    def getNextWidgetName(self, sName):
#        BugUtil.debug("cvTechChooser: getNextWidgetName %i %i", self.nWidgetCount, len(self.sWidgets))
        szName = sName + str(self.nWidgetCount)
        self.nWidgetCount += 1
        self.sWidgets.append(szName)
        return szName

    def deleteWidgets(self):
#        BugUtil.debug("cvTechChooser: deleteWidgets %i %i", self.nWidgetCount, len(self.sWidgets))
        screen = self.getScreen()
        for w in self.sWidgets:
#            BugUtil.debug("cvTechChooser: deleteWidgets '%s'", w)
            screen.deleteWidget(w)

        self.nWidgetCount = 0
        self.sWidgets = []
        return





    def getXStart(self):
        return ( self.BOX_INCREMENT_WIDTH * self.PIXEL_INCREMENT )

    def getXSpacing(self):
        return ( self.BOX_INCREMENT_X_SPACING * self.PIXEL_INCREMENT )

    def getYStart(self, iY):
        return int((((self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT ) / 6.0) * iY) - self.PIXEL_INCREMENT )

    def getWidth(self, xDiff):
        return ( ( xDiff * self.getXSpacing() ) + ( ( xDiff - 1 ) * self.getXStart() ) )

    def getHeight(self, yDiff, nFactor):
        return ( ( nFactor + ( ( abs( yDiff ) - 1 ) * 6 ) ) * self.PIXEL_INCREMENT )

    def update(self, fDelta):
        if (CyInterface().isDirty(InterfaceDirtyBits.Advanced_Start_DIRTY_BIT)):
            CyInterface().setDirty(InterfaceDirtyBits.Advanced_Start_DIRTY_BIT, False)

            if (self.m_bSelectedTechDirty):
                self.m_bSelectedTechDirty = False
                self.updateSelectedTech()

            if (self.m_bTechRecordsDirty):
                self.m_bTechRecordsDirty = False
                self.updateTechRecords(True)

            if (gc.getPlayer(self.iCivSelected).getAdvancedStartPoints() < 0):
                # hide the screen
                screen = self.getScreen()
                screen.hide("AddTechButton")
                screen.hide("ASPointsLabel")
                screen.hide("SelectedTechLabel")

        return

    def updateSelectedTech(self):
        pPlayer = gc.getPlayer(CyGame().getActivePlayer())

        # Get the screen
        screen = self.getScreen()

        szName = ""
        iCost = 0

        if (self.m_iSelectedTech != -1):
            szName = gc.getTechInfo(self.m_iSelectedTech).getDescription()
            iCost = gc.getPlayer(CyGame().getActivePlayer()).getAdvancedStartTechCost(self.m_iSelectedTech, True)

        if iCost > 0:
            szText = u"<font=4>" + localText.getText("TXT_KEY_WB_AS_SELECTED_TECH_COST", (iCost, pPlayer.getAdvancedStartPoints())) + u"</font>"
            screen.setLabel( "ASPointsLabel", "Background", szText, CvUtil.FONT_LEFT_JUSTIFY, self.X_ADVANCED_START_TEXT, self.Y_ADD_TECH_BUTTON + 3, 0, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1 )
        else:
            screen.hide("ASPointsLabel")

        szText = u"<font=4>"
        szText += localText.getText("TXT_KEY_WB_AS_SELECTED_TECH", (szName,))
        szText += u"</font>"
        screen.setLabel( "SelectedTechLabel", "Background", szText, CvUtil.FONT_LEFT_JUSTIFY, self.X_ADVANCED_START_TEXT + 250, self.Y_ADD_TECH_BUTTON + 3, 0, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1 )

        # Want to add
        if (pPlayer.getAdvancedStartTechCost(self.m_iSelectedTech, True) != -1):
            screen.show("AddTechButton")
        else:
            screen.hide("AddTechButton")

    def onClose(self):
        pPlayer = gc.getPlayer(self.iCivSelected)
        if (pPlayer.getAdvancedStartPoints() >= 0):
            CyInterface().setDirty(InterfaceDirtyBits.Advanced_Start_DIRTY_BIT, True)
        return 0

class TechChooserMaps:

    TechChooserInputMap = {
        'TechRecord'            : CvTechChooser().TechRecord,
        'TechID'                : CvTechChooser().ParentClick,
        'TechPane'                : CvTechChooser().ParentClick,
        'TechButtonID'            : CvTechChooser().ParentClick,
        'TechButtonBorder'        : CvTechChooser().ParentClick,
        'Unit'                    : CvTechChooser().ParentClick,
        'Building'                : CvTechChooser().ParentClick,
        'Obsolete'                : CvTechChooser().ParentClick,
        'ObsoleteX'                : CvTechChooser().ParentClick,
        'Move'                    : CvTechChooser().ParentClick,
        'FreeUnit'                : CvTechChooser().ParentClick,
        'FeatureProduction'            : CvTechChooser().ParentClick,
        'Worker'                : CvTechChooser().ParentClick,
        'TradeRoutes'            : CvTechChooser().ParentClick,
        'HealthRate'            : CvTechChooser().ParentClick,
        'HappinessRate'            : CvTechChooser().ParentClick,
        'FreeTech'                : CvTechChooser().ParentClick,
        'LOS'                    : CvTechChooser().ParentClick,
        'MapCenter'                : CvTechChooser().ParentClick,
        'MapReveal'                : CvTechChooser().ParentClick,
        'MapTrade'                : CvTechChooser().ParentClick,
        'TechTrade'                : CvTechChooser().ParentClick,
        'OpenBorders'        : CvTechChooser().ParentClick,
        'BuildBridge'            : CvTechChooser().ParentClick,
        'Irrigation'            : CvTechChooser().ParentClick,
        'Improvement'            : CvTechChooser().ParentClick,
        'DomainExtraMoves'            : CvTechChooser().ParentClick,
        'AdjustButton'            : CvTechChooser().ParentClick,
        'TerrainTradeButton'    : CvTechChooser().ParentClick,
        'SpecialBuildingButton'    : CvTechChooser().ParentClick,
        'YieldChangeButton'        : CvTechChooser().ParentClick,
        'BonusRevealButton'        : CvTechChooser().ParentClick,
        'CivicRevealButton'        : CvTechChooser().ParentClick,
        'ProjectInfoButton'        : CvTechChooser().ParentClick,
        'ProcessInfoButton'        : CvTechChooser().ParentClick,
        'FoundReligionButton'    : CvTechChooser().ParentClick,
        'CivDropDown'            : CvTechChooser().CivDropDown,
        }
 
My guess is TEXTURE_SIZE but I have not had my coffee yet and it was a late night ;). but it the same variable is used to draw all those icons so you will need two one for the tech icon and one for the units and buildings etc.

edit I suppose you could say TEXTURE_SIZE * 2 in the code that draws the tech icon.

The very last line in this code block (I could not highlight it in any way so just cut the code off.
Code:
    def placeTechs(self, screen, sPanel, bTechPanel, bTechName, bTechIcon, bTechDetails):
#        BugUtil.debug("cvTechChooser: placeTechs")

        iMaxX = 0
        iMaxY = 0

        if sPanel == self.TabPanels[0]:
            sPanelWidget = ""
        else:
            sPanelWidget = sPanel

        # If we are the Pitboss, we don't want to put up an interface at all
        if ( CyGame().isPitbossHost() ):
            return

        # Cache some tech infos
        self.createTechInfoCache()

        # Go through all the techs
        for i in range(gc.getNumTechInfos()):

#Afforess Skip Mountaineering w/o Mountains Mod
            if (not gc.getPlayer(0).canEverResearch(i)) : continue
            # Create and place a tech in its proper location
            iX = 30 + ( (gc.getTechInfo(i).getGridX() - 1) * ( ( self.BOX_INCREMENT_X_SPACING + self.BOX_INCREMENT_WIDTH ) * self.PIXEL_INCREMENT ) )
# Rise of Mankind 2.7 - more techs vertically
#            iY = ( gc.getTechInfo(i).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT ) + 5
            iY = ( gc.getTechInfo(i).getGridY() - 1 ) * ( self.BOX_INCREMENT_Y_SPACING * self.PIXEL_INCREMENT )
# Rise of Mankind 2.7 - more techs vertically
            szTechRecord = sPanelWidget + "TechRecord" + str(i)

            if ( iMaxX < iX + self.getXStart() ):
                iMaxX = iX + self.getXStart()
            if ( iMaxY < iY + ( self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT ) ):
                iMaxY = iY + ( self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT )

# BUG - Tech Era Colors - start
            szTechRecordShadow = sPanelWidget + "TechRecordShadow" + str(i)
            iShadowOffset = 9
            screen.attachPanelAt( sPanel, szTechRecordShadow, u"", u"", True, False, PanelStyles.PANEL_STYLE_TECH, iX - 6 + iShadowOffset, iY - 6 + iShadowOffset, self.getXStart() + 6, 12 + ( self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT ), WidgetTypes.WIDGET_TECH_CHOOSER_ERA, gc.getTechInfo(i).getEra(), -1 )
            self.setTechPanelShadowColor(screen, szTechRecordShadow, gc.getTechInfo(i).getEra())
            screen.hide( szTechRecordShadow )
# BUG - Tech Era Colors - end

            screen.attachPanelAt( sPanel, szTechRecord, u"", u"", True, False, PanelStyles.PANEL_STYLE_TECH, iX - 6, iY - 6, self.getXStart() + 6, 12 + ( self.BOX_INCREMENT_HEIGHT * self.PIXEL_INCREMENT ), WidgetTypes.WIDGET_TECH_TREE, i, -1 )
            screen.setActivation( szTechRecord, ActivationTypes.ACTIVATE_MIMICPARENTFOCUS)
            screen.hide( szTechRecord )

            #reset so that it offsets from the tech record's panel
            iX = 6
            iY = 6

            if ( gc.getTeam(gc.getPlayer(self.iCivSelected).getTeam()).isHasTech(i) ):
                screen.setPanelColor(szTechRecord, 0, 0, 0)
                self.aiCurrentState.append(CIV_HAS_TECH)
            elif ( gc.getPlayer(self.iCivSelected).getCurrentResearch() == i ):
                screen.setPanelColor(szTechRecord, 0, 0, 200)
                self.aiCurrentState.append(CIV_IS_RESEARCHING)
            elif ( gc.getPlayer(self.iCivSelected).isResearchingTech(i) ):
                screen.setPanelColor(szTechRecord, 200, 0, 0)
                self.aiCurrentState.append(CIV_IS_RESEARCHING)
            elif ( gc.getPlayer(self.iCivSelected).canEverResearch(i) ):
# Rise of Mankind 2.91 - tech tree colors - start
                if (RoMOpt.isRoMTechTreeColors()):
                    # Ancient Era
                    if ( gc.getTechInfo(i).getEra() == 0 ):
                        screen.setPanelColor(szTechRecord, 160, 100, 160)
                    # Classical Era
                    elif ( gc.getTechInfo(i).getEra() == 1 ):
                        screen.setPanelColor(szTechRecord, 160, 100, 100)
                    # Medieval Era
                    elif ( gc.getTechInfo(i).getEra() == 2 ):
                        screen.setPanelColor(szTechRecord, 160, 160, 100)
                    # Renaissance Era
                    elif ( gc.getTechInfo(i).getEra() == 3 ):
                        screen.setPanelColor(szTechRecord, 160, 160, 50)
                    # Industrial Era
                    elif ( gc.getTechInfo(i).getEra() == 4 ):
                        screen.setPanelColor(szTechRecord, 60, 200, 60)
                    # Modern Era
                    elif ( gc.getTechInfo(i).getEra() == 5 ):
                        screen.setPanelColor(szTechRecord, 100, 104, 160)
                    # Future Era
                    else:
                        screen.setPanelColor(szTechRecord, 50, 160, 250)
                else:
                    screen.setPanelColor(szTechRecord, 100, 104, 160)
# Rise of Mankind 2.91 - tech tree colors - end
                self.aiCurrentState.append(CIV_NO_RESEARCH)
            else:
                screen.setPanelColor(szTechRecord, 206, 65, 69)
                self.aiCurrentState.append(CIV_TECH_AVAILABLE)

            if bTechName:
                szTechID = sPanelWidget + "TechID" + str(i)
                szTechString = "<font=1>"
                if ( gc.getPlayer(self.iCivSelected).isResearchingTech(i) ):
                    szTechString = szTechString + str(gc.getPlayer(self.iCivSelected).getQueuePosition(i)) + ". "
                szTechString += gc.getTechInfo(i).getDescription()
                szTechString = szTechString + "</font>"
                screen.setTextAt( szTechID, szTechRecord, szTechString, CvUtil.FONT_LEFT_JUSTIFY, iX + 6 + X_INCREMENT, iY + 6, -0.1, FontTypes.SMALL_FONT, WidgetTypes.WIDGET_TECH_TREE, i, -1 )
                screen.setActivation( szTechID, ActivationTypes.ACTIVATE_MIMICPARENTFOCUS )

            if bTechIcon:
                szTechButtonID = sPanelWidget + "TechButtonID" + str(i)
                screen.addDDSGFCAt( szTechButtonID, szTechRecord, gc.getTechInfo(i).getButton(), iX + 6, iY + 6, TEXTURE_SIZE, TEXTURE_SIZE, WidgetTypes.WIDGET_TECH_TREE, i, -1, False )
 
Last edited:
So I'm currently using the Smartmap, and loving it, and since I have a PC with a lot of RAM I can map some pretty big maps, and I wanted to know what I would have to edit in the files to extend the Civilization Count to 34, both in general and in the Smartmap?
 
So I'm currently using the Smartmap, and loving it, and since I have a PC with a lot of RAM I can map some pretty big maps, and I wanted to know what I would have to edit in the files to extend the Civilization Count to 34, both in general and in the Smartmap?
First of all, Civilization 4 is a 32 bit game, meaning by default it will crash if you use more than 2 GB. You can extend this but regardless of what you do, 32 bit applications have an address space limitation of 4 GB of memory. It's one of the main reasons for moving to 64 bit. I highly recommend playing on 64 bit systems though because there are some memory related crashes in some mods, which only affect 32 bit systems.

As for adding more players, make a custom game and add more players. Alternatively edit Assets/XML/GameInfo/civ4worldinfos.xml. This file sets the map size as well as how many items the map should contain of various kinds. One of the options is the number of players.

There is a variable called MAX_PLAYERS, which is hardcoded in the DLL. If you want to have a lot of players, you might need to increase this and compile a new DLL.
 
First of all, Civilization 4 is a 32 bit game, meaning by default it will crash if you use more than 2 GB. You can extend this but regardless of what you do, 32 bit applications have an address space limitation of 4 GB of memory. It's one of the main reasons for moving to 64 bit. I highly recommend playing on 64 bit systems though because there are some memory related crashes in some mods, which only affect 32 bit systems.

As for adding more players, make a custom game and add more players. Alternatively edit Assets/XML/GameInfo/civ4worldinfos.xml. This file sets the map size as well as how many items the map should contain of various kinds. One of the options is the number of players.

There is a variable called MAX_PLAYERS, which is hardcoded in the DLL. If you want to have a lot of players, you might need to increase this and compile a new DLL.

Mine is the Steam Version, and all my Computers are 64-bit, but are you saying that the game will still play as 32-bit unless I jury rig it?
 
Mine is the Steam Version, and all my Computers are 64-bit, but are you saying that the game will still play as 32-bit unless I jury rig it?
The only way to convert a game from 32 bit to 64 bit is to get the source code and then compile with a 64 bit compiler. This means the game can only see 4 GB. However there is a default setting to only allow a 32 bit exe to use 2 GB to make sure there is room for windows. However this is now silly because 64 bit windows will not take up the other 2 GB, meaning you can get away with increasing the allowed memory (there are tools for that online), but the exe can still only see 4 GB.

However the game data will not make you go over the limit. The game doesn't use an insane amount of memory for the game data. Graphics on the other can could become an issue if you add a lot.
 
Alright, I downloaded the CvGameCoreDLL source from here ( https://github.com/dguenms/beyond-the-sword-sdk ) and was able to edit the CvDefines.h file with Microsoft Visual C++ 2010 Express to change the Max players to 34. From all the directions I've read I should then load the the prepacked Project file and with MVC, and then clean and rebuild; but, as I'm completely new to this, I'm sort of lost. When I load the project file in MVC nothing comes up on the MVC window. Am I going about this the wrong way?
Keep in mind I'm completely new to Microsoft Visual C++, and really just wanted to alter this one aspect of the game.
 
Keep in mind I'm completely new to Microsoft Visual C++, and really just wanted to alter this one aspect of the game.
You could try using @vincentz's 34 civ gamecore with extra map sizes instead of compiling your own DLL. Assuming that SmartMap.py is already in your PublicMaps folder, it should be enough to copy the 34 Civ Mapsizes folder into Beyond the Sword\Mods and then load the mod from the main menu (under "Advanced").
 
It sounds like you are following my guide and are currently at this step:
4) Launch your project in Visual Studio

Double click on the CvGameCoreDLL.sln file, it should open in Visual Studio with an already configured project.

To test if everything is working, run Build ... -> Rebuild Solution.
Did you actually open Visual Studio from the CvGameCoreDLL.sln file? Are you sure nothing is open? Visual Studio usually starts with no file open but the "project structure" panel to the left should display a list of files that are part of the source code. Does anything happen when you run Rebuild Solution and if applicable what is the error message?
 
Here are two Screen shots, showing the file I open and what Visual Studio looks like afterwards. I suspect I'm missing something simple, since this is my first time.
 

Attachments

  • VStudi01.jpg
    VStudi01.jpg
    1 MB · Views: 155
  • VStudi02.jpg
    VStudi02.jpg
    1.1 MB · Views: 148
Oh alright. Try the CvGameCoreDLL file with the type "Microsoft Visual Studio Solution".
 
I have a huge problem in regard to making unit models with damage textures. TLDR I make a new mesh, texure it and export that mesh from 3d max. Than I copy that over into an existing nif like say Trireme, copy all the materials and names and everything properly to the new mesh. And it should all work. But instead all I get is no damage texture AND the teamcolor bleeds through everything like crazy.

nifscope.png
This is how it looks in nifscope. That is how it should look.

game.png

But this is how it looks in the game.

I'll upload the whole unit. And if anyone here can help me fix what's wrong and explain what I am messing up I'd be grateful.
 

Attachments

I have a huge problem in regard to making unit models with damage textures. TLDR I make a new mesh, texure it and export that mesh from 3d max. Than I copy that over into an existing nif like say Trireme, copy all the materials and names and everything properly to the new mesh. And it should all work. But instead all I get is no damage texture AND the teamcolor bleeds through everything like crazy.

View attachment 502750
This is how it looks in nifscope. That is how it should look.

View attachment 502751

But this is how it looks in the game.

I'll upload the whole unit. And if anyone here can help me fix what's wrong and explain what I am messing up I'd be grateful.
It appears that even the non-shadered version of the Trireme is using a shader, and since you did not do the shader entries on your unit, you get the team-colour overlay it seems.

The entries are easy to make though. In the block details of each meshes node (NiTriShape/NiTriStrips) change the "Has Shader" to "yes", the "Shader Name" to "TCiv4MechNonShader" and the "Unknown Integer" to "-1". For me the unit looked okay then, but I did not test if the damage textures work.
 
Hello all,
I noticed so weird thing that have to ask if someone can explain this:eek:

If I close steam client I start to have memory problems and crashes. My civ4 installation is ancient, years older than steam..
What possible connection can steam have my civ4? I play ROM-AND..
 
It appears that even the non-shadered version of the Trireme is using a shader, and since you did not do the shader entries on your unit, you get the team-colour overlay it seems.

The entries are easy to make though. In the block details of each meshes node (NiTriShape/NiTriStrips) change the "Has Shader" to "yes", the "Shader Name" to "TCiv4MechNonShader" and the "Unknown Integer" to "-1". For me the unit looked okay then, but I did not test if the damage textures work.
Apparently no, the damage states don't work. At least not in my admittedly limited testing so far. But even without that you have been an incredible help for saving me from the dreaded color bleed. Now I can get back to making units.

This being said, how did you know to check this? Truth be told I understand very little about the .nif format and you seem to know everything. So if I may ask what's your secret?
 
Apparently no, the damage states don't work. At least not in my admittedly limited testing so far. But even without that you have been an incredible help for saving me from the dreaded color bleed. Now I can get back to making units.

This being said, how did you know to check this? Truth be told I understand very little about the .nif format and you seem to know everything. So if I may ask what's your secret?
Mainly experience from making so many units to be honest.

First I check if everything with the texture files is in order. Since the unit is a non-shader unit (no _fx), the lack of a TeamColor.bmp file made me suspicious. So I compared your file with the original Trireme.nif file. Since that one doesn't have a TeamColor.bmp file either, the shader settings were the next place to look for me. Testing your unit with the shader settings then seems to have fixed the team-colour problem.
 
What would I have to do to replace the graphics (and sound) an existing unit in the base?
For example, let us say I wish to chance the graphics for "Mechanized Infantry" that appears in the game from an APC into an actual group of infantry, like, for example, kine100's Modern Infantry. What would be the simplest method to achieve this, the unit graphics, icon, and sound? Further what would I have to do to change all in game name instances of "Mechanized Infantry" to "Modern Infantry"?
 
Back
Top Bottom