Requesting following features

I'll get to it momentarily. :D I just finished G&G and am awaiting comments from seasnake - so I need something to fill in the time.

Have you changed anything in Rebellion or can I just work with my copy? If I'm gonna add stuff to your copy I obviously need to have it first.

edit: Do you want debug messages in the log only, or in the game interface also? (I actually think there is a useful thing for this in the CvUtil module we can use.)
 
did we ever set it so that if the rebels destroy a civ then the corresponding rebels become the civ again?
 
I will give you the rebels module in this posts edit
Spoiler :

Code:
### Rebellion mod component written for Jamie's Rome Mod, by Baldyr

from Helpers import *
from eNums import *

# constants

iRequiredRebellionCitySize = 3
iRebelReinforcementPercentage = 90
iNumRebelReinforcements = 1
iCulturalRebellionPercentage = 75
iResistancePercentage = 100
iResistanceDomesticPercentage = 50
iResistanceDomesticTurns = 2
iDomesticRebellionPercentage = 60
iCivilizedPercentageSubtract = 5
iCapitalHappinessPenalty = 2
iMinorRevoltPercentage = 8
iCivilWarPercentage = 5
iCivilWarUnhappyCitiesPercentage = 30
iRequiredNumCivilWarCities = 6
iRequiredNumCivilWarUnhappiness = 2
iCivilWarRebelArmySize = 6
iSlaveRevoltDenominator = 10
iNumSlaveUnitsPerCitizen = 3
tByzantion = (46, 23)
byzansCapital = "Constantinople"
iByzansRebelArmySize = iCivilWarRebelArmySize

eDefaultUnit = eWarrior

tRebelUnits = (
(eBronzeWorking, eAxeman),
(eIronWorking, eSwordsman),
(eAdvancedBronzeWorking, eAdvancedSpearman),
(eAdvanceIronWorking, eAdvancedSwordsman)
)

tCivilized = ( "Carthage", "Greece", "Rome", "Egypt" )

defaultRebellionMessage = "TXT_KEY_REBELLION_REBELLION"
defaultTerminationMessage = "TXT_KEY_REBELLION_TERMINATION"
defaultUnitSpawnMessage = "TXT_KEY_REBELLION_UNITSPAWN"
civilWarMessage = "TXT_KEY_REBELLION_CIVILWAR"
civilWarTerminationMessage = "TXT_KEY_REBELLION_CIVILWAR_TERMINATION"
civilWarUnitSpawnMessage = "TXT_KEY_REBELLION_CIVILWAR_UNITSPAWN"
slaveRevoltMessage = "TXT_KEY_REBELLION_SLAVEREVOLT" 
slaveRevoltTerminationMessage = "TXT_KEY_REBELLION_SLAVEREVOLT_TERMINATION"
byzantiumMessage = "TXT_KEY_REBELLION_ERE"

iRandomSeed = getRandNum(iNumMajorPlayers, "seed")
tRebellionClasses = (
    "CulturalInfiltration",
    "Resistance",
    "DomesticRebellion",
    "MinorRevolt",
    )

# main functions

def process(iGameTurn):
    for pCurrentRebellion in getRebellions():
        #print pCurrentRebellion
        if pCurrentRebellion.checkTermination(iGameTurn):
            removeRebellion(pCurrentRebellion)
            pCurrentRebellion.setDeactivate()
            pCurrentRebellion.addTerminationMessage()
        else:
            pCurrentRebellion.process(iGameTurn)
    checkRebellion(iGameTurn)

def checkRebellion(iGameTurn):
    pCivPlayer = instance((iGameTurn + iRandomSeed) % iNumMajorPlayers)
    if not pCivPlayer.isAlive(): return
    lCities = pCivPlayer.get(PyPlayer).getCityList()
    lCities.reverse()
    lDefectingCities = list()
    iNumCities = len(lCities)
    bCivilWarValid = iNumCities >= iRequiredNumCivilWarCities #isCivilWarValid(iNumCities)
    for pCity in (city.GetCy() for city in lCities):
        if not isRebellionValid(pCity): continue
        if checkClasses(pCity, pCivPlayer): return
        if ( bCivilWarValid
             and not CivilWar.isQuota(len(lDefectingCities), iNumCities)
             and CivilWar.checkUnhappiness(pCity) ):
            lDefectingCities.append(pCity)
    if ( bCivilWarValid
         and CivilWar.checkConditions(len(lDefectingCities), iNumCities) ):
        CivilWar.initCivilWar(pCivPlayer, lDefectingCities)

def checkClasses(pCity, pCivPlayer):
    for rebellionClass in tRebellionClasses:
        if eval(rebellionClass + ".checkConditions(pCivPlayer, pCity)"):
            appendRebellion(eval(rebellionClass + "(pCivPlayer, pCity)"))
            return True

# data storage

def setup():
    setGlobalData("lCurrentRebellions", list())

def getRebellions():
    return getGlobalData("lCurrentRebellions")

def appendRebellion(pCurrentRebellion):
    lCurrentRebellions = getRebellions()
    lCurrentRebellions.append(pCurrentRebellion)
    setGlobalData("lCurrentRebellions", lCurrentRebellions)

def removeRebellion(pCurrentRebellion):
    lCurrentRebellions = getRebellions()
    lCurrentRebellions.remove(pCurrentRebellion)
    setGlobalData("lCurrentRebellions", lCurrentRebellions)

# class definitions

class Rebellion:

    @classmethod
    def checkConditions(cls, pCivPlayer, pCity):
        return pCity.isDisorder()

    # initialization

    def __init__(self, pCivPlayer, pCity):
        self.iRebellionTurn = Game.getGameTurn()
        self.plotID = getPlotID(pCity.plot())
        self.eCityOwner = pCivPlayer.get(playerID)
        self.setRebelPlayer(pCity)
        self.setUnitType(pCity)
        self.setNumUnits(pCity)
        self.setRebelUnitSettings(pCity)
        self.setMessages(pCity)
        self.setActivate()
        self.fire()
        #print self

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = eBarbarian

    def setUnitType(self, pCity):
        self.eUnitType = getTechUnitType(self.getCityOwner().get(CyTeam))

    def setNumUnits(self, pCity):
        iNatives = pCity.getCulturePercentAnger() / 100
        iPopulation = pCity.getPopulation()
        self.iNumUnits = max(1, min(iNatives, iPopulation))

    def setRebelUnitSettings(self, pCity):
        self.iUnitAI = int(eAttackCity)
        self.ePromotion = None
        self.unitFlag = "rebel"

    def setMessages(self, pCity):
        self.rebellionMessage = defaultRebellionMessage
        self.terminationMessage = defaultTerminationMessage
        self.unitSpawnMessage = defaultUnitSpawnMessage

    # class instance interface

    def isRebellionTurn(self):
        return Game.getGameTurn() == self.iRebellionTurn

    def getRebellionTurn(self):
        return self.iRebellionTurn

    def getCityOwner(self):
        return instance(self.eCityOwner)

    def getRebelCiv(self):
        if self.eRebelPlayer == eBarbarian:
            return pBarbarianCiv
        else:
            return instance(self.eRebelPlayer)

    def getRebelPlayer(self):
        return self.eCityOwner + iNumMajorPlayers + 2

    def getUnitType(self):
        return self.eUnitType

    def getPlotID(self):
        return self.plotID

    def getCyPlot(self):
        return Map.plotByIndex(self.getPlotID())

    def getPlotCoords(self):
        return getCoords(self.getCyPlot())

    def getCyCity(self):
        return self.getCyPlot().getPlotCity()

    def getCityName(self):
        return self.getCyCity().getName()

    def getNumUnits(self):
        return self.iNumUnits

    def getUnitAI(self):
        return UnitAITypes(self.iUnitAI)

    def isPromotion(self):
        return self.ePromotion != None

    def getPromotion(self):
        return self.ePromotion

    def isUnitFlag(self):
        return self.unitFlag != ""

    def getUnitFlag(self):
        return self.unitFlag
    
    def setPromotion(self, pUnit):
        if self.isPromotion():
            pUnit.setHasPromotion(self.getPromotion())

    def setUnitFlag(self, pUnit):
        if self.isUnitFlag():
            pUnit.setScriptData(self.getUnitFlag())

    def setActivate(self):
        self.getCyCity().setScriptData("rebellion")

    def setDeactivate(self):
        self.getCyCity().setScriptData("")

    def isActive(self):
        return self.getCyCity().getScriptData() == "rebellion"

    # shared customizable functionality

    def fire(self):
        self.spawnRebelUnits()
        self.addRebellionMessage()
        
    def process(self, iGameTurn):
        if isChance(iRebelReinforcementPercentage):
            self.spawnRebelUnits(iNumRebelReinforcements)

    def checkTermination(self, iGameTurn):
        if self.getCyCity().isDisorder(): return False
        unitFlag = self.getUnitFlag()
        for pUnit in self.getRebelCiv().get(PyPlayer).getUnitList():
            if pUnit.getScriptData() == unitFlag:
                return False
        return True

    def killRebelUnits(self):
        flag = self.getUnitFlag()
        for pUnit in self.getRebelCiv().get(PyPlayer).getUnitList():
            if pUnit.getScriptData() == flag:
                pUnit.kill(True, self.getCityOwner().get(playerID))

    def addMessage(self, message, tColor):
        if not message: return
        if cityKnownByHuman(self.getCyCity()):
            addMessage(message, (self.getCityName(),), getColor(*tColor))

    def addTerminationMessage(self, bRed=False, bWhite=True):
        bGreen = self.getCityOwner() == pHumanCiv
        self.addMessage(self.terminationMessage, (bGreen, bRed, bWhite))

    def addRebellionMessage(self, bGreen=False, bWhite=True):
        bRed = self.getCityOwner() == pHumanCiv
        self.addMessage(self.rebellionMessage, (bGreen, bRed, bWhite))

    def addUnitSpawnMessage(self, bGreen=False):
        if self.isRebellionTurn(): return
        bRed = self.getCityOwner() == pHumanCiv
        self.addMessage(self.unitSpawnMessage, (bGreen, bRed))

    def spawnRebelUnits(self, iNumUnits=0):
        if not iNumUnits:
            iNumUnits = self.getNumUnits()
        eUnitType, eUnitAI = self.getUnitType(), self.getUnitAI()
        lPlots = self.getPlotList()
        if len(lPlots) == 0: return
        while iNumUnits:
            iX, iY = getRandomCoords(lPlots)
            pUnit = self.getRebelCiv().get(CyPlayer).initUnit(eUnitType, iX, iY, UnitAITypes.UNITAI_ATTACK_CITY, DirectionTypes.NO_DIRECTION)
            self.setPromotion(pUnit)
            self.setUnitFlag(pUnit)
            iNumUnits -= 1
        self.addUnitSpawnMessage()

    def getPlotList(self):
        lPlots = list()
        iX, iY = self.getPlotCoords()
        for eDirection in range(DirectionTypes.NUM_DIRECTION_TYPES):
            pPlot = plotDirection(iX, iY, DirectionTypes(eDirection))
            if isSpawnValid(pPlot):
                lPlots.append(pPlot)
        return lPlots

    def updateRebelTechs(self):
        rebelCiv = self.getRebelCiv().get(PyPlayer)
        for eTech in self.getCityOwner().get(PyPlayer).getResearchedTechList():
            if rebelCiv.hasResearchedTech(eTech): continue
            rebelCiv.setHasTech(eTech)


class CulturalInfiltration(Rebellion):

    @classmethod
    def checkConditions(cls, pCivPlayer, pCity):
        return ( pCity.isDisorder()
                 and not pCity.isOccupation()
                 and not pCity.isNeverLost()
                 and isChance(iCulturalRebellionPercentage) )

    def __init__(self, pCivPlayer, pCity):
        Rebellion.__init__(self, pCivPlayer, pCity)

    def fire(self):
        self.setAtWar()
        self.spawnRebelUnits()
        self.addRebellionMessage()

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = getHighestCityCulturalRival(pCity)
        if self.eRebelPlayer == -1:
            self.eRebelPlayer = self.getRebelPlayer()
            self.updateRebelTechs()

    def setAtWar(self):
        setAtWar(self.getRebelCiv(), self.getCityOwner())


class Resistance(Rebellion):

    @classmethod
    def checkConditions(cls, pCivPlayer, pCity):
        return ( pCity.isDisorder()
                 and pCity.isOccupation()
                 and isChance(iResistancePercentage) )

    def __init__(self, pCivPlayer, pCity):
        Rebellion.__init__(self, pCivPlayer, pCity)

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = pCity.getPreviousOwner()

    def setUnitType(self, pCity):
        self.eUnitType = getTechUnitType(self.getRebelCiv().get(CyTeam))

    def process(self, iGameTurn):
        if ( iGameTurn - self.getRebellionTurn() >= iResistanceDomesticTurns
             and isChance(iResistanceDomesticPercentage) ):
            self.killRebelUnits()
            removeRebellion(self)
            appendRebellion(DomesticRebellion(self.getCityOwner(), self.getCyCity()))
        else:
            Rebellion.process(self, iGameTurn)


class DomesticRebellion(Rebellion):

    @classmethod
    def checkConditions(cls, pCivPlayer, pCity):
        return ( pCity.isDisorder()
                 and isChance(iDomesticRebellionPercentage - isCivilized(pCivPlayer) * iCivilizedPercentageSubtract) )
    
    def __init__(self, pCivPlayer, pCity):
        Rebellion.__init__(self, pCivPlayer, pCity)

    def fire(self):
        self.spawnRebelUnits()
        self.addRebellionMessage()
        self.setCapital()
        self.changeCapitalHappinessPenalty(-iCapitalHappinessPenalty)

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = self.getRebelPlayer()
        self.updateRebelTechs()

    def setNumUnits(self, pCity):
        iUnhappyLevel = pCity.unhappyLevel(0)
        iDistance = getDistanceToCapital(pCity, self.getCityOwner().get(CyPlayer))
        self.iNumUnits = max(iUnhappyLevel, iDistance)

    def checkTermination(self, iGameTurn):
        if Rebellion.checkTermination(self, iGameTurn):
            self.changeCapitalHappinessPenalty(iCapitalHappinessPenalty)
            return True

    def changeCapitalHappinessPenalty(self, value):
        self.getCapital().changeExtraHappiness(value)

    def setCapital(self):
        self.iCapital = self.getCityOwner().get(CyPlayer).getCapitalCity().getID()

    def getCapital(self):
        return self.getCityOwner().get(CyPlayer).getCity(self.iCapital)
    

class MinorRevolt(Rebellion):

    @classmethod
    def checkConditions(cls, pCivPlayer, pCity):
        return ( pCity.angryPopulation(0)
                 and isChance(iMinorRevoltPercentage) )

    def __init__(self, pCivPlayer, pCity):
        Rebellion.__init__(self, pCivPlayer, pCity)

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = self.getRebelPlayer()
        self.updateRebelTechs()

    def setNumUnits(self, pCity):
        iUnhappyLevel = pCity.unhappyLevel(0)
        iAngryPopulation = pCity.angryPopulation(0)
        iPopulation = pCity.getPopulation()
        self.iNumUnits = max(1, min(iUnhappyLevel - iAngryPopulation, iPopulation))


class SlaveRevolt(Rebellion):
    
    @classmethod
    def checkConditions(cls, pCity):
        return isChance(pCity.getHurryAngerTimer() * iSlaveRevoltDenominator)

    def __init__(self, ePlayer, pCity):
        Rebellion.__init__(self, instance(ePlayer), pCity)
        appendRebellion(self)
        self.setActivate()

    def fire(self):
        self.spawnRebelUnits()
        self.changeCitySize(-self.getNumSlaveCitizens(self.getNumUnits()))
        self.addRebellionMessage()
        
    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = pointer("Slaves", playerID)
        
    def setNumUnits(self, pCity):
        self.iNumUnits = pCity.getPopulation()

    def setRebelUnitSettings(self, pCity):
        self.iUnitAI = int(eAttackCity)
        self.ePromotion = None
        self.unitFlag = str(pCity.getName())

    def setMessages(self, pCity):
        self.rebellionMessage = slaveRevoltMessage
        self.terminationMessage = slaveRevoltTerminationMessage
        self.unitSpawnMessage = defaultUnitSpawnMessage

    def addTerminationMessage(self):
        pass

    def addEmancipationMessage(self):
        bGreen = self.getCityOwner() == pHumanCiv
        addMessage(self.terminationMessage, (), getColor(bGreen, False, True))

    def checkTermination(self, iGameTurn):
        if self.getCityOwner().get(CyPlayer).getCivics(eLabor) != eSlavery:
            self.changeCitySize(self.getNumSlaveCitizens(self.countRebelUnits()))
            self.killRebelUnits()
            self.revertSlaveCities()
            self.addEmancipationMessage()
            return True
        return Rebellion.checkTermination(self, iGameTurn)

    def revertSlaveCities(self):
        for pCity in (city.GetCy() for city in self.getRebelCiv().get(PyPlayer).getCityList()):
            if ( pCity.getPreviousOwner() == self.getCityOwner().get(playerID)
                 and pCity.getOwner() == self.getRebelCiv().get(playerID) ):
                self.getCityOwner().get(CyPlayer).acquireCity(pCity, False, False)

    def process(self, iGameTurn):
        pass

    def countRebelUnits(self):
        flag = self.getUnitFlag()
        iNumUnits = 0
        for scriptData in (unit.getScriptData() for unit in self.getRebelCiv().get(PyPlayer).getUnitList()):
            if scriptData == flag:
                iNumUnits += 1
        return iNumUnits

    def getNumSlaveCitizens(self, iNumUnits):
        return iNumUnits / iNumSlaveUnitsPerCitizen

    def changeCitySize(self, iValue):
        self.getCyCity().changePopulation(iValue)


class CivilWar(Rebellion):

##    lCivilWarCities = list()
##
##    @classmethod
##    def isCivilWarActive(cls):
##        return len(cls.lCivilWarCities) > 0
##
##    @classmethod
##    def resetCivilWar(cls):
##        cls.lCivilWarCities = list()
##
##    @classmethod
##    def appendCivilWar(cls, pCivilWar):
##        cls.lCivilWarCities.append(pCivilWar)
##        appendRebellion(pCivilWar)
##        pCivilWar.setActivate()
##
##    @classmethod
##    def removeCivilWar(cls, pCivilWar):
##        removeRebellion(pCivilWar)
##        pCivilWar.setDeactivate()

    @classmethod        
    def checkUnhappiness(cls, pCity):
        iAngryCitizens = pCity.angryPopulation(0)
        iWarWeariness = pCity.getWarWearinessPercentAnger() / 100
        return iAngryCitizens - iWarWeariness >= iRequiredNumCivilWarUnhappiness

    @classmethod
    def isQuota(cls, iNumRebelCities, iNumTotalCities):
        return iNumRebelCities > iNumTotalCities * iCivilWarUnhappyCitiesPercentage / 100
        
    @classmethod
    def checkConditions(cls, iNumDefectingCities, iNumTotalCities):
        return ( iNumDefectingCities >= iNumTotalCities * iCivilWarUnhappyCitiesPercentage / 100.0
                 and isChance(iCivilWarPercentage) )

    @classmethod
    def initCivilWar(cls, pCivPlayer, lDefectingCities):
        pRebelHQ = cls.initRebellions(pCivPlayer, lDefectingCities)
        if pRebelHQ:
            pRebelHQ.setRebelHQ()

    @classmethod
    def initRebellions(cls, pCivPlayer, lDefectingCities):
        tLargestCity = 0, None
        for pCity in lDefectingCities:
            pCivilWar = CivilWar(pCivPlayer, pCity)
            appendRebellion(pCivilWar)
            pCivilWar.setActivate()
            iPopulation = pCity.getPopulation()
            if iPopulation > tLargestCity[0]:
                tLargestCity = iPopulation, pCivilWar
        return tLargestCity[1]

    def setRebelHQ(self):
        setCapital(self.getCyCity())
        self.spawnRebelUnits()
        self.terminationMessage = civilWarTerminationMessage
        self.addRebellionMessage()

    def __init__(self, pCivPlayer, pCity):
        Rebellion.__init__(self, pCivPlayer, pCity)
##        CivilWar.appendCivilWar(self)
##        self.fire()

    def fire(self):
        self.flipCity()

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = self.getRebelPlayer()
        self.updateRebelTechs()

    def setNumUnits(self, pCity):
        self.iNumUnits = iCivilWarRebelArmySize

    def setMessages(self, pCity):
        self.rebellionMessage = civilWarMessage
        self.terminationMessage = ""
        self.unitSpawnMessage = civilWarUnitSpawnMessage

    def addMessage(self, message, tColor):
        addMessage(message, (self.getCityOwner().getName(),), getColor(*tColor))

    def addTerminationMessage(self):
        bGreen = self.getCityOwner() == pHumanCiv
        self.addMessage(self.terminationMessage, (bGreen, False, True))

    def addRebellionMessage(self):
        bRed = self.getCityOwner() == pHumanCiv
        self.addMessage(self.rebellionMessage, (False, bRed, True))

    def addUnitSpawnMessage(self):
        bRed = self.getCityOwner() == pHumanCiv
        Rebellion.addMessage(self, self.unitSpawnMessage, (False, bRed))

    def flipCity(self):
        pCity = self.getCyCity()
        iX, iY = self.getPlotCoords()
        pRebelCiv = self.getRebelCiv()
        lCityUnits = getCityUnits(pCity)
        pRebelCiv.get(CyPlayer).acquireCity(pCity, False, False)
        for pUnit in lCityUnits:
            pRebelUnit = pRebelCiv.get(PyPlayer).initUnit(pUnit.getUnitType(), iX, iY)
            pRebelUnit.convert(pUnit)
            self.setUnitFlag(pRebelUnit)

    def checkTermination(self, iGameTurn):
        if self.getRebelCiv().get(CyPlayer).getNumCities() == 0:
##            self.terminateCivilWar()
##            CivilWar.resetCivilWar()
            self.getRebelCiv().get(CyPlayer).killUnits()
            return True

##    def terminateCivilWar(self):
##        for pCivilWar in self.lCivilWarCities:
##            if pCivilWar == self: continue
##            self.removeCivilWar(pCivilWar)
##        CivilWar.resetCivilWar()

    def process(self, iGameTurn):
        pass


class EastRomanEmpire(CivilWar):

    @classmethod
    def initRebellions(cls, pCivPlayer, lDefectingCities):
        tLargestCity = 0, None
        for pCity in lDefectingCities:
            pERE = EastRomanEmpire(pCivPlayer, pCity)
            appendRebellion(pERE)
            pERE.setActivate()
            iPopulation = pCity.getPopulation()
            if getCoords(pCity) == tByzantion:
                iPopulation = 99
            if iPopulation > tLargestCity[0]:
                tLargestCity = iPopulation, pERE
        return tLargestCity[1]

    def setRebelHQ(self):
        setCapital(self.getCyCity())
        self.terminationMessage = civilWarTerminationMessage
        self.addRebellionMessage()
        self.getCyCity().setName(byzansCapital, True)
        self.spawnRebelUnits()

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = pointer("Byzantium", playerID)
        self.updateRebelTechs()

    def setNumUnits(self, pCity):
        self.iNumUnits = iByzansRebelArmySize

    def setMessages(self, pCity):
        self.rebellionMessage = byzantiumMessage
        self.terminationMessage = ""
        self.unitSpawnMessage = civilWarUnitSpawnMessage

    def addRebellionMessage(self):
        addMessage(self.rebellionMessage, (self.getCyCity().getName(), byzansCapital), getColor(False, True))

# helper functions

def getPlotID(pPlot):
    return Map.plotNum(pPlot.getX(), pPlot.getY())

def getCyPlot(iPlot):
    return Map.plotByIndex(iPlot)

def getTechUnitType(pTeam):
    for i in xrange(len(tRebelUnits) - 1, -1, -1):
        eTechType = tRebelUnits[i][0]
        if pTeam.isHasTech(eTechType):
            return tRebelUnits[i][1]
    return eDefaultUnit

def isRebellionValid(pCity):
    return ( not pCity.getScriptData()
             and pCity.getPopulation() >= iRequiredRebellionCitySize )

def isCivilized(pCivPlayer):
    return pCivPlayer.getName(False) in tCivilized

##def getPlotUnitStrength(pCity):
##    pPlot = pCity.plot()
##    iNumUnits = pPlot.getNumUnits()
##    iUnit = iStrength = 0
##    while iUnit < iNumUnits:
##        pUnit = pPlot.getUnit(iUnit)
##        iStrength += pUnit.baseCombatStr()
##        iUnit += 1
##    return iStrength

##def getNumStrenghtUnits(eUnitType, iStrength):
##    return max(1, iStrength / gc.getUnitInfo(eUnitType).getCombat())

##def isCivilWarValid(iNumCities):
##    return ( not CivilWar.isCivilWarActive()
##             and iNumCities >= iRequiredNumCivilWarCities )
 
did we ever set it so that if the rebels destroy a civ then the corresponding rebels become the civ again?
Nope, but we could. Lets just debug what we have first, ok?

Also, don't miss my edit above.
 
um ok the interface thing sounds good... But I will have to be able to remove it when I am done...
 
Um, the basement got flooded so I didn't have any time to do the debug code after all. :p Now I'm backed up with other stuff that I need to take care of also, but I might still have some time left tonight. Unless I need to fix something with G&G of course. :eekdance:

But I will basically be adding a debug() function in Helpers that takes care of the messages themselves, and then call on that from a Rebellion.debug() method, which gets inherited to all of the other classes. And no debug messages will be assembled or printed out unless a global variable bDebugMode is set to True. So you will be able to shut all of it down easily without even touching the code. And you'll be able to add debug functionality to your own code moving forward with the new debug() utility.

This shouldn't take long to code, but I really should take some time to test it. Otherwise you'll end up debugging the debugger! :lol:
 
ok, I think that we have to make sure that if the rebel's corresponding "real" civ is killed that they should take it's place because the Nubian Rebels just COMPLETLY conquored eygpt... Also the amount of reinforcements is crazy... (especcially as playable civs get it too and jsut move them to the capital..) I think a maximum of 10 turns can pass before rienforcements stop trickling in (if it isn't too much trouble).

so to do list is:

above
reset diplomacy
above2

sorry about your basement...
edit: can you tell me what these actually do:

iResistancePercentage = 100
iResistanceDomesticPercentage = 50
iResistanceDomesticTurns = 2

I can't figure the difference out...
 
what is the rebellion that happens immediatly after a city comes out of resistance? because it just spawned 12 units outside nove carthago (size 5) with 3 swordsmen inside... It needs to be removed or something...
 
I don't know all the answers but I guess you'll have to do the testing and debugging. I'll try to get you that debugging feature later - then can you decide what you wanna do/change/add.

Right now you should probably try to lower the probabilities for those rebellions that are taking place too frequently, so revisit the settings. The settings you were wondering about are related to this, by the way:
Spoiler :
Type - Occupational Rebellion

Sample Conditions - Occupation (not too common)

Civ Claimant - Original owner

Number of Units - to be completed

Type - Original owner's tech level

Termination - None

Misc - Revival of civ, Chance of rebellion ends (therfore turning into domestic rebellions) after some turns after capture (not sure how many though...)

I'm not even sure if I understood what the marked passage meant, but the code reflects my interpretation of it anyway. Did I ever mention how critical it is that specifications can never ever be open for interpretation? :p
 
what that is is basically that after 5 turns of the city being owned by the new owner the chance for the city to have occupational rebellions end and instead the city will have domestic rebellions... so what does resistance domestic percentage refer to and what is resistance percentage? (Im guessing it is the chance of occupational happening and it's set at 100 :lol:)
 
These settings:
Code:
iResistancePercentage = 100
100% probability for a occupation revolt if a city is in occupation once the owners turn rolls in (every 8 turns, so it may still happen or not).
Code:
iResistanceDomesticPercentage = 50
50% probability of a occupation revolt ending and turning into a domestic one. (Each turn, I guess.)
Code:
iResistanceDomesticTurns = 2
The above probability only applies after 2 turns of occupation revolt.

You basically have to test different settings until you find something that works and is balanced. Also the number of rebel units could be adjusted, but for that you need to edit the corresponding method for the class in question. If you have questions you could simply post the code you're unsure of and I'll explain it. Then you can edit it or replace it with something else entirely.
 
what was the calculation we used for occupational?
 
what was the calculation we used for occupational?
You mean number of units? At this point you need to look these things up in the actual code. Since the Resistance class doesn't have a setNumUnits() method it means that it is inherited from the main Rebellion class:
Code:
    def setNumUnits(self, pCity):
        iNatives = pCity.getCulturePercentAnger() / 100
        iPopulation = pCity.getPopulation()
        [B]self.iNumUnits[/B] = [B]max[/B](1, [B]min[/B](iNatives, iPopulation))
iNatives is the number of foreign citizens in the city. iPopulation is the total number of citizens in the city.

The calculation itself consists of a max() function and a min() function. The first one makes sure that at least one unit is always created. The second one makes sure that the number of units never exceeds the city size, just as a safe guard.

If you wanna change this you need to add a Resistance.setNumUnits() method where you assign the number of units (integer value) to the attribute iNumUnits (with the self. bit of course). The method must take self and a CyCity instance (here pCity) as the parameter, but the rest of the method is up to you. You might look in the API for inspiration, or you could sneak-peak at other setNumUnit() methods in the module.
 
I have actually been changing some calculations:

1: in MinorRevolt the happy level doesn't make sense... SO I changed to angrycitizens + 2 instead :D

2: a couple of other changed too but cant remember which...
 
I have an exception coming from the catapult code....

Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 187, in handleEvent

File "CvEventManager", line 381, in onBeginGameTurn

File "CatapultConstruction", line 182, in process

File "CatapultConstruction", line 119, in checkUnits

RuntimeError: unidentifiable C++ exception
ERR: Python function onEvent failed, module CvEventInterface

any ideas asaf or baldyr?
 
Ok, something is up with the marked line:
Code:
        def checkUnits(self):
                for pUnit, pPlot in list((pUnit, pUnit.plot()) for pUnit in self.iterateUnits()):
[B]                        if pPlot.getFeatureType() == eForest:[/B]
                                if isEnemyTerritory(pUnit, pPlot, self.pCivPlayer.get(CyTeam)) or self.isUsed(pUnit): return
                                self.activateOverwatch(pUnit, pPlot)
                                break
Since the pPlot value is fetched from the pUnit value, something must have happened to that CyUnit instance. It might have died in mid construction, or something. Thus the CyPlot instance would be invalid, or something.

How is the constant eForest defined in eNums?

edit: No, I already weeded out invalid CyUnit instances in the iterateUnits() method:
Code:
        def iterateUnits(self):
                lUnitList = self.lUnits[:]
                for pUnit in lUnitList:
                       [B] if pUnit.isNone():[/B]
                                self.removeUnit(pUnit)
                                continue
                        yield pUnit
I have no clue as to what the exception is about. Can you recreate the error or do you perhaps have a autosave? (Enable autosaves on every turn while testing!)
 
Ok, I've attached the Rebellion module with debug features below. All you need to do to disable the debug messages is to set:
Code:
bDebug = False
(Later we can move some code to the Helpers module - if you wanna be able to use the debug() function in other modules also.)

Note that there is only one single line printed into the game interface. The other debug stuff only appears in the Python Debug Log. Examples:
Code:
 *** Rebellion Debug ***
Rebellion initialized: <Rebellion.Resistance instance at 0x2925D210>
Date/Turn: -3920/2
City: Syracuse (Rome)
Units:
Type	Num	AI	Prom	Flag
27	4	5	-1	rebel
 ***
Code:
 *** Rebellion Debug ***
Active on Game Turn 2:
<Rebellion.Resistance instance at 0x2925D210> (city: Syracuse, starting turn: 2)
 ***
The strange thing inside the tag is a reference is the actual class instance and the last bit is where it resides in the memory. This address is unique for every instance so it can be used as a identifier. Looking at the two examples above we can be certain that they refer to the same Resistance class instance.
 

Attachments

Since we're debugging CatapultConstruction, it would help if you could enable debugging in that module also, by uncommenting line 178.

I also noticed a forgotten print statement on line 129 that could be deleted. It prints out the coordinates of the construction unit, the coordinates of the construction plot (which should be the same) and the number of turns it will take (which should always be the same). This isn't really needed as I already solved whatever issue it was that I was trying to solve. But this is still an example of how you can add your own print/debug lines in any old code.
 
when will you be able to work on the 3 things mentioned earlier (stop sending reenforcements after 10 turns, reset diplomacy fix... and swapping the rebels into original civ when the original civ dies and the rebels are still alive...)

enabled debugging in catapult con and will merge my rebels with your one tommorrow morning... possibly...

will post save either in 5 mins or tommorrow morning...

eForest = getIndex("Feature", "Forest")
 
save (this is during the catapult failure so it should happen next turn...

be mindfull of changes to the python (and some xml) tell me if there are problems)

dont forget to read the edits on previous post...
 

Attachments

Back
Top Bottom