Event firing without checking requirements

openyourmind

Chieftain
Joined
Feb 22, 2016
Messages
51
I have an event that is supposed to fire under certain conditions (tech cloning that is way into future, cloning factory, being able to build a counter unit) specified in python, but it seems to ignore them completely and fire anyway.

The event itself:

Code:
        <EventTriggerInfo>
            <Type>EVENTTRIGGER_NW_THE_CYLONS</Type>
            <WorldNewsTexts/>
            <TriggerTexts>
                <TriggerText>
                    <Text>TXT_KEY_EVENT_TRIGGER_NW_THE_CYLONS</Text>
                    <Era>NONE</Era>
                </TriggerText>
            </TriggerTexts>
            <bSinglePlayer>0</bSinglePlayer>
            <iPercentGamesActive>20</iPercentGamesActive>
            <iWeight>150</iWeight>
            <bProbabilityUnitMultiply>0</bProbabilityUnitMultiply>
            <bProbabilityBuildingMultiply>0</bProbabilityBuildingMultiply>
            <Civic>NONE</Civic>
            <iMinTreasury>0</iMinTreasury>
            <iMinPopulation>0</iMinPopulation>
            <iMaxPopulation>0</iMaxPopulation>
            <iMinMapLandmass>0</iMinMapLandmass>
            <iMinOurLandmass>0</iMinOurLandmass>
            <iMaxOurLandmass>-1</iMaxOurLandmass>
            <MinDifficulty>NONE</MinDifficulty>
            <iAngry>0</iAngry>
            <iUnhealthy>0</iUnhealthy>
            <UnitsRequired/>
            <iNumUnits>0</iNumUnits>
            <iNumUnitsGlobal>0</iNumUnitsGlobal>
            <iUnitDamagedWeight>0</iUnitDamagedWeight>
            <iUnitDistanceWeight>0</iUnitDistanceWeight>
            <iUnitExperienceWeight>0</iUnitExperienceWeight>
            <bUnitsOnPlot>0</bUnitsOnPlot>
            <BuildingsRequired/>
            <iNumBuildings>0</iNumBuildings>
            <iNumBuildingsGlobal>0</iNumBuildingsGlobal>
            <iNumPlotsRequired>0</iNumPlotsRequired>
            <bOwnPlot>0</bOwnPlot>
            <iPlotType>-1</iPlotType>
            <FeaturesRequired/>
            <TerrainsRequired/>
            <ImprovementsRequired/>
            <BonusesRequired/>
            <RoutesRequired/>
            <ReligionsRequired/>
            <iNumReligions>0</iNumReligions>
            <CorporationsRequired/>
            <iNumCorporations>0</iNumCorporations>
            <bPickReligion>0</bPickReligion>
            <bStateReligion>0</bStateReligion>
            <bHolyCity>0</bHolyCity>
            <bPickCorporation>0</bPickCorporation>
            <bHeadquarters>0</bHeadquarters>
            <Events>
                <Event>EVENT_NW_THE_CYLONS_1</Event>
            </Events>
            <PrereqEvents/>
            <bPrereqEventPlot>0</bPrereqEventPlot>
            <OrPreReqs/>
            <AndPreReqs/>
            <ObsoleteTechs/>
            <bRecurring>0</bRecurring>
            <bTeam>0</bTeam>
            <bGlobal>1</bGlobal>
            <bPickPlayer>0</bPickPlayer>
            <bOtherPlayerWar>0</bOtherPlayerWar>
            <bOtherPlayerHasReligion>0</bOtherPlayerHasReligion>
            <bOtherPlayerHasOtherReligion>0</bOtherPlayerHasOtherReligion>
            <bOtherPlayerAI>0</bOtherPlayerAI>
            <iOtherPlayerShareBorders>0</iOtherPlayerShareBorders>
            <OtherPlayerHasTech>NONE</OtherPlayerHasTech>
            <bPickCity>0</bPickCity>
            <bPickOtherPlayerCity>0</bPickOtherPlayerCity>
            <bShowPlot>0</bShowPlot>
            <iCityFoodWeight>0</iCityFoodWeight>
            <PythonCanDo>canTriggerNWTheCylons</PythonCanDo>
            <PythonCanDoCity/>
            <PythonCanDoUnit/>
            <PythonCallback/>
        </EventTriggerInfo>

And here are the triggers.

Code:
def canTriggerNWTheCylons(argsList):

    kTriggeredData = argsList[0]
    pPlayer = gc.getPlayer(kTriggeredData.ePlayer)
    pTeam = gc.getTeam(pPlayer.getTeam())
    
#   If Barbarians are disabled in this game, this event will not occur.
    if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_NO_BARBARIANS):
        return false

#   Let's be fair -- civ can't currently be at war.

    if pTeam.getAtWarCount(true) > 0:
        return False
            
#   At least one civ on the board must know TECH_CLONING.
    bFoundValid = false
    iTech = CvUtil.findInfoTypeNum(gc.getTechInfo, gc.getNumTechInfos(), 'TECH_CLONING')
    for iPlayer in range(gc.getMAX_CIV_PLAYERS()):           
        loopPlayer = gc.getPlayer(iPlayer)
        if loopPlayer.isAlive():
            if gc.getTeam(loopPlayer.getTeam()).isHasTech(iTech):
                bFoundValid = true
                break       
    if not bFoundValid:
        return false

#   At least one civ on the board must have constructed a CLONING_FACTORY.
    bFoundValid = false
    iCloning = CvUtil.findInfoTypeNum(gc.getBuildingInfo, gc.getNumBuildingInfos(), 'BUILDING_CLONING_FACTORY')
    for iPlayer in range(gc.getMAX_CIV_PLAYERS()):           
        loopPlayer = gc.getPlayer(iPlayer)
        if loopPlayer.isAlive():
            if gc.getTeam(loopPlayer.getTeam()).getBuildingClassCount(gc.getBuildingInfo(iCloning).getBuildingClassType()) > 0:
                bFoundValid = true
                break               
    if not bFoundValid:
        return false


#    Find an eligible plot
    map = gc.getMap()   
    for i in range(map.numPlots()):
        plot = map.plotByIndex(i)
        if (plot.getOwner() == kTriggeredData.ePlayer and not plot.isWater() and not plot.isImpassable() and not plot.isCity() and plot.getNumUnits() > 0 and plot.area().getCitiesPerPlayer(kTriggeredData.ePlayer) > 0):
            return true

    return false

    # Can we build the counter unit?       
    iCounterUnitClass = CvUtil.findInfoTypeNum(gc.getUnitClassInfo, gc.getNumUnitClassInfos(), 'UNITCLASS_INFANTRY')
    iCounterUnit = gc.getCivilizationInfo(player.getCivilizationType()).getCivilizationUnits(iCounterUnitClass)
    if iCounterUnit == -1:
        return False

    (loopCity, iter) = pPlayer.firstCity(false)
    bFound = false
    while(loopCity):
        if (loopCity.canTrain(iCounterUnit, false, false)):
            bFound = true
            break
                
        (loopCity, iter) = pPlayer.nextCity(iter, false)
        
    if not bFound:
        return False
 
You're returning true before the counter unit check here:
Code:
#    Find an eligible plot
    map = gc.getMap()
    for i in range(map.numPlots()):
        plot = map.plotByIndex(i)
        if (plot.getOwner() == kTriggeredData.ePlayer and not plot.isWater() and not plot.isImpassable() and not plot.isCity() and plot.getNumUnits() > 0 and plot.area().getCitiesPerPlayer(kTriggeredData.ePlayer) > 0):
            return true
It's likely that this search will find a viable plot. If that's the case, the checks further below will be redundant.
 
The python code looks fine to me. Do you have python exception enabled? Are you sure the canTrigger function is in the correct file? I think the game ignores python conditions it can't find. I would first insert a print statement at the start of the python function to verify it is actually called.

I think you're onto something here. I've set no barb game options and the event still firing when setting weight to -1, so it cannot see the python rules set. I've also tried other event which has only python rules defined and it's firing too.

The canTrigger is in CvRandomEventInterface.py, which is in Assets\Python\EntryPoints of the Better Bat AI.

Edit: tried other events that are governed by python only, none are reading it correctly even though python is good as you said (albeit with errors in logic as devolution stated)
 
Last edited:
Whelp, solved. turns out there were actually 2 EventInterface.py files, another one was in Assets\Python folder which actually didn't have the python lines.

You're returning true before the counter unit check here:
Code:
#    Find an eligible plot
    map = gc.getMap()
    for i in range(map.numPlots()):
        plot = map.plotByIndex(i)
        if (plot.getOwner() == kTriggeredData.ePlayer and not plot.isWater() and not plot.isImpassable() and not plot.isCity() and plot.getNumUnits() > 0 and plot.area().getCitiesPerPlayer(kTriggeredData.ePlayer) > 0):
            return true
It's likely that this search will find a viable plot. If that's the case, the checks further below will be redundant.

Thanks btw, put the plot check in the end as it should have been. Shame though game checks only for infantry and not mechanized too.
 
Top Bottom