1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

[Warlords] How to add a python option

Discussion in 'Civ4 - Creation & Customization' started by Paolo80, Jan 11, 2020.

  1. Paolo80

    Paolo80 Chieftain

    Joined:
    Dec 20, 2019
    Messages:
    41
    Gender:
    Male
    Hi guys,

    is it possible adding a python option which a player can activate at the beginning of the scenario? I wrote a routine which adds some units if a player acquire a city (they represent mercenary enemies which change flag). I would want ask the player if he wants to activate "mercenary" option or not. If he activates this option, the below code would run (in CvEventManager.py):


    PHP:
    def onCityAcquired(selfargsList):
            
    'City Acquired'
            
    iPreviousOwner,iNewOwner,pCity,bConquest,bTrade argsList
            CvUtil
    .pyPrint('City Acquired Event: %s' %(pCity.getName()))

                    
    pPlayer gc.getPlayer(iNewOwner)

            
    iTurn CyGame().getGameTurn()
                 
            if 
    iNewOwner != and iTurn 1:
                if 
    iPreviousOwner == 4:
                           for 
    i in range(3):
    [
    INDENT]                    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_ARCHER'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                    
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_CATAPULT'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                    
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_SPEARMAN'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)[/INDENT]
                else:
                    for 
    i in range(2):
                        
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_ROME_PRAETORIAN'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                    
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_SPEARMAN'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
    Any ideas?

    Thank you all
     
    Last edited: Jan 11, 2020
  2. Paolo80

    Paolo80 Chieftain

    Joined:
    Dec 20, 2019
    Messages:
    41
    Gender:
    Male
    I've created a python function in the file CvScreensInterface.py below

    PHP:
    def mercenaries(argsList):
        
    iButtonId argsList[0]
        
    iData1 argsList[1]
        
    iData2 argsList[2]
        
        
    iMercenaries 0
        
    if iButtonId == 0:
            
    iMercenaries 1
        
    if iButtonId == 1:
            return
    Then I've written in the file CvEventManager the code below

    PHP:
    def onGameStart(selfargsList):

    ....

    for 
    iPlayer in range(gc.getMAX_PLAYERS()):
                
    player gc.getPlayer(iPlayer)
                if 
    player.isAlive():
                    if 
    player.isHuman():
                        
    popupInfo CyPopupInfo()
                        
    popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON)
                        
    popupInfo.setText(CyTranslator().getText("TXT_KEY_POPUP_SELECT_MERCENARIO",()))
                        
    popupInfo.setData1(iPlayer)
                        
    popupInfo.setOnClickedPythonCallback("mercenaries")
                        
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_SI", ()), "")
                        
    popupInfo.addPythonButton(CyTranslator().getText("TXT_KEY_NO", ()), "")
                        
    popupInfo.addPopup(iPlayer)

    ....

    def onCityAcquired(selfargsList):
            
    'City Acquired'
            
    iPreviousOwner,iNewOwner,pCity,bConquest,bTrade argsList
            CvUtil
    .pyPrint('City Acquired Event: %s' %(pCity.getName()))

                    
    pPlayer gc.getPlayer(iNewOwner)

            
    iTurn CyGame().getGameTurn()
            
    iMercenaries CvScreensInterface.mercenaries(argsList)
                  
            if 
    iNewOwner != and iTurn and iMercenaries == 1:
                if 
    iPreviousOwner == 4:
                            for 
    i in range(3):
                        
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_ARCHER'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                    
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_CATAPULT'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                    
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_SPEARMAN'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                else:
                    for 
    i in range(2):
                        
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_ROME_PRAETORIAN'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                    
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_SPEARMAN'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
    At the beginning of the game I click on yes button but iMercenaries doesn't get value 1. What's the mistake? How I can use iMercenaries value in the function onCityAcquired?
     
  3. Paolo80

    Paolo80 Chieftain

    Joined:
    Dec 20, 2019
    Messages:
    41
    Gender:
    Male
    nobody knows?
     
  4. f1rpo

    f1rpo plastics

    Joined:
    May 22, 2014
    Messages:
    735
    Location:
    Germany
    Your iMercenaries seems to be a local variable, i.e. it doesn't get stored in between calls to the 'mercenaries' function. Your function also doesn't return any value. A global variable should work – but would still be lost when the player reloads. I guess one could show the popup again after reloading. There is also a way to store data in savegames from Python, namely CyGame.setScriptData. I've never tried that though. The argument would be a string, so I guess sth. like
    gc.getGame().setScriptData(str(iMercenaries))
    to store the player's choice and
    iMercenaries = int(gc.getGame().getScriptData())
    to retrieve it. (The DLL should then take care of including the data in savegames.)

    The easier approach might be to use a game option that the player can select on the Custom Scenario screen. To my knowledge, it's not possible to add a new game option without changing the DLL, but it should be possible to repurpose existing game options. I don't think the "Random Personalities" option has any effect in a scenario with pre-assigned leaders. The name and description of the option can be changed through GameInfo\CIV4GameOptionInfos.xml, the value is checked with:
    gc.getGame().isOption(GameOptionTypes.GAMEOPTION_RANDOM_PERSONALITIES)
     
  5. Paolo80

    Paolo80 Chieftain

    Joined:
    Dec 20, 2019
    Messages:
    41
    Gender:
    Male
    How can I call the global variable iMercenaries?

    Here the new code in CvScreenInterface

    PHP:
    iMercenaries 0

    def mercenaries
    (argsList):
        
    iButtonId argsList[0]
        
    iData1 argsList[1]
        
    iData2 argsList[2]
        
            global 
    iMercenaries
        
            
    if iButtonId == 0:
                
    iMercenaries 1
            
    if iButtonId == 1:
                
    iMercenaries 0
    And here the new code in CvEventManager

    PHP:
    def onCityAcquired(selfargsList):
            
    'City Acquired'
            
    iPreviousOwner,iNewOwner,pCity,bConquest,bTrade argsList
            CvUtil
    .pyPrint('City Acquired Event: %s' %(pCity.getName()))

                    
    pPlayer gc.getPlayer(iNewOwner)
             
    iTurn CyGame().getGameTurn()
            global 
    iMercenaries
                iMercenaries 
    CvScreensInterface.mercenaries(argsList)
                  
                    if 
    iNewOwner != and iTurn and iMercenaries == 1:
                if 
    iPreviousOwner == 4:
                            for 
    i in range(3):
                        
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_ARCHER'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                    
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_CATAPULT'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                    
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_SPEARMAN'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                else:
                    for 
    i in range(2):
                        
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_ROME_PRAETORIAN'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
                    
    pPlayer.initUnit(gc.getInfoTypeForString('UNIT_SPEARMAN'), pCity.getX(), pCity.getY(), UnitAITypes.NO_UNITAI)
    But iMercenaries value is always "none" (I print it in the python debug). What's the error?
     
  6. f1rpo

    f1rpo plastics

    Joined:
    May 22, 2014
    Messages:
    735
    Location:
    Germany
    iMercenaries = CvScreensInterface.mercenaries(argsList)
    ^Does it work if you just remove this line? The mercenaries function doesn't return a value (that would explain the "none") and the call shouldn't be necessary.
     
  7. Paolo80

    Paolo80 Chieftain

    Joined:
    Dec 20, 2019
    Messages:
    41
    Gender:
    Male
    If I erase this line I have a python error "global name 'iMercenaries' is not defined"
     
  8. f1rpo

    f1rpo plastics

    Joined:
    May 22, 2014
    Messages:
    735
    Location:
    Germany
    Goes to show that I don't even know the basics when it comes to Python in general. Apparently, to access a global variable defined in a different module, the module name needs to be prepended, i.e.:
    if iNewOwner != 4 and iTurn > 1 and CvScreensInterface.iMercenaries == 1:
     
  9. Paolo80

    Paolo80 Chieftain

    Joined:
    Dec 20, 2019
    Messages:
    41
    Gender:
    Male
    Wonderful! Now it works! Thanks a lot!
     
    f1rpo likes this.

Share This Page