[Warlords] How to add a python option

Paolo80

Chieftain
Joined
Dec 20, 2019
Messages
85
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(self, argsList):
        '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 != 4 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:
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(self, argsList):

....

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(self, argsList):
        '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 != 4 and iTurn > 1 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?
 
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)
 
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(self, argsList):
        '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 != 4 and iTurn > 1 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?
 
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.
 
If I erase this line I have a python error "global name 'iMercenaries' is not defined"
 
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:
 
Top Bottom