Barbarian spawn event help

Joined
Nov 20, 2009
Messages
384
EDIT: SOLVED

I'm trying to put in an event that spawns barbarian units inside your borders by copypasting the Cylon event from Next War, and it's worked pretty well so far, except that it only fires for the AI, which apparently happens with the original event as well. I tried cross-referencing with the other barb-spawning events and I'm pretty sure I know where the problem is, but I'm not sure how to approach it. Anyone got any ideas?

Python for the Cylon event
Spoiler :

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

###    Pretty sure the problem is here...
#    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

# and plot.area().getCitiesPerPlayer(kTriggeredData.ePlayer) > 0

def getHelpNWTheCylons1(argsList):
    iEvent = argsList[0]
    kTriggeredData = argsList[1]
  
    szHelp = localText.getText("TXT_KEY_EVENT_NW_THE_CYLONS_HELP_1", ())

    return szHelp

###    ...And here?
# and plot.area().getCitiesPerPlayer(kTriggeredData.ePlayer) > 0
def applyNWTheCylons1(argsList):
    iEvent = argsList[0]
    kTriggeredData = argsList[1]
    pPlayer = gc.getPlayer(kTriggeredData.ePlayer)

    listPlots = []
    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):
            listPlots.append(i)

    if 0 == len(listPlots):
        return

    plot = map.plotByIndex(listPlots[gc.getGame().getSorenRandNum(len(listPlots), "Cylons event location")])
  
    if map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_DUEL'):
        iNumUnits  = 1
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_TINY'):
        iNumUnits  = 1
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_SMALL'):
        iNumUnits  = 2
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_STANDARD'):
        iNumUnits  = 3
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_LARGE'):
        iNumUnits  = 4
    else:
        iNumUnits  = 5
      
    iUnitType = CvUtil.findInfoTypeNum(gc.getUnitInfo, gc.getNumUnitInfos(), 'UNIT_AUTOMATONS')
    barbPlayer = gc.getPlayer(gc.getBARBARIAN_PLAYER())
    for i in range(iNumUnits):
        barbPlayer.initUnit(iUnitType, plot.getX(), plot.getY(), UnitAITypes.UNITAI_ATTACK_CITY_LEMMING, DirectionTypes.DIRECTION_SOUTH)


Python from the Vandal event for comparison
Spoiler :

Code:
def canTriggerTheVandals(argsList):

    kTriggeredData = argsList[0]
    player = gc.getPlayer(kTriggeredData.ePlayer)
  
#   If Barbarians are disabled in this game, this event will not occur.
    if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_NO_BARBARIANS):
        return false
          
#   At least one civ on the board must know Metal Casting.
    bFoundValid = false
    iTech = CvUtil.findInfoTypeNum(gc.getTechInfo, gc.getNumTechInfos(), 'TECH_METAL_CASTING')
    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 know Iron Working.
    bFoundValid = false
    iTech = CvUtil.findInfoTypeNum(gc.getTechInfo, gc.getNumTechInfos(), 'TECH_IRON_WORKING')
    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

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

    (loopCity, iter) = player.firstCity(false)
    bFound = false
    while(loopCity):
        if (loopCity.canTrain(iCounterUnit, false, false)):
            bFound = true
            break
              
        (loopCity, iter) = player.nextCity(iter, false)
      
    if not bFound:
        return false

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

    return false
                  

def getHelpTheVandals1(argsList):
    iEvent = argsList[0]
    kTriggeredData = argsList[1]
  
    szHelp = localText.getText("TXT_KEY_EVENT_THE_VANDALS_HELP_1", ()) 

    return szHelp


def applyTheVandals1(argsList):
    iEvent = argsList[0]
    kTriggeredData = argsList[1]
    player = gc.getPlayer(kTriggeredData.ePlayer)

    listPlots = []
    map = gc.getMap() 
    for i in range(map.numPlots()):
        plot = map.plotByIndex(i)
        if (plot.getOwner() == -1 and not plot.isWater() and not plot.isImpassable() and plot.area().getCitiesPerPlayer(kTriggeredData.ePlayer) > 0 and plot.isAdjacentPlayer(kTriggeredData.ePlayer, true)):
            listPlots.append(i)
  
    if 0 == len(listPlots):
        return
          
    plot = map.plotByIndex(listPlots[gc.getGame().getSorenRandNum(len(listPlots), "Vandal event location")])
  
    if map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_DUEL'):
        iNumUnits  = 1
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_TINY'):
        iNumUnits  = 2
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_SMALL'):
        iNumUnits  = 3
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_STANDARD'):
        iNumUnits  = 4
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_LARGE'):
        iNumUnits  = 5
    else:
        iNumUnits  = 6
      
    iUnitType = CvUtil.findInfoTypeNum(gc.getUnitInfo, gc.getNumUnitInfos(), 'UNIT_SWORDSMAN')

    barbPlayer = gc.getPlayer(gc.getBARBARIAN_PLAYER())
    for i in range(iNumUnits):
        barbPlayer.initUnit(iUnitType, plot.getX(), plot.getY(), UnitAITypes.UNITAI_ATTACK_CITY_LEMMING, DirectionTypes.DIRECTION_SOUTH)
 
Last edited:
I tried fiddling around with the Vandal event since I know it works for the human player, and found out there's a function in the plot-finding and spawning code which sets the spawn to happen adjacent to the civ's borders. I just removed it, and now the event works as intended.

The code if anyone's interested:
Spoiler :

Code:
def canTriggerTerrorism(argsList):

    kTriggeredData = argsList[0]
    player = gc.getPlayer(kTriggeredData.ePlayer)
    
#   If Barbarians are disabled in this game, this event will not occur.
    if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_NO_BARBARIANS):
        return false
                    
#   At least one civ on the board must know Iron Working.
    bFoundValid = false
    iTech = CvUtil.findInfoTypeNum(gc.getTechInfo, gc.getNumTechInfos(), 'TECH_RIFLING')
    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

    # 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) = player.firstCity(false)
    bFound = false
    while(loopCity):
        if (loopCity.canTrain(iCounterUnit, false, false)):
            bFound = true
            break
                
        (loopCity, iter) = player.nextCity(iter, false)
        
    if not bFound:
        return false

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

    return false
    
def getHelpTerrorism(argsList):
    iEvent = argsList[0]
    kTriggeredData = argsList[1]
    
    szHelp = localText.getText("TXT_KEY_EVENT_THE_VANDALS_HELP_1", ())   

    return szHelp


def applyTerrorism(argsList):
    iEvent = argsList[0]
    kTriggeredData = argsList[1]
    player = gc.getPlayer(kTriggeredData.ePlayer)

    listPlots = []
    map = gc.getMap()   
    for i in range(map.numPlots()):
        plot = map.plotByIndex(i)
        if (plot.getOwner() == 0 and not plot.isWater() and not plot.isImpassable() and plot.area().getCitiesPerPlayer(kTriggeredData.ePlayer) > 0):
            listPlots.append(i)
    
    if 0 == len(listPlots):
        return
            
    plot = map.plotByIndex(listPlots[gc.getGame().getSorenRandNum(len(listPlots), "Vandal event location")])
    
    if map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_DUEL'):
        iNumUnits  = 1
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_TINY'):
        iNumUnits  = 2
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_SMALL'):
        iNumUnits  = 3
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_STANDARD'):
        iNumUnits  = 4
    elif map.getWorldSize() == CvUtil.findInfoTypeNum(gc.getWorldInfo, gc.getNumWorldInfos(), 'WORLDSIZE_LARGE'):
        iNumUnits  = 5
    else:
        iNumUnits  = 6
        
    iUnitType = CvUtil.findInfoTypeNum(gc.getUnitInfo, gc.getNumUnitInfos(), 'UNIT_INFANTRY')

    barbPlayer = gc.getPlayer(gc.getBARBARIAN_PLAYER())
    for i in range(iNumUnits):
        barbPlayer.initUnit(iUnitType, plot.getX(), plot.getY(), UnitAITypes.UNITAI_ATTACK_CITY_LEMMING, DirectionTypes.DIRECTION_SOUTH)
 
Top Bottom