Requesting following features

number 2 should be in effect (I guess we could use "arrgg!" for now but find some way into using a new thingy)

War will not be a prerequisite.

I think the rebels should get updated by their counterpart when they respawn... but we could always change this after testing!
 
number 2 should be in effect (I guess we could use "arrgg!" for now but find some way into using a new thingy)
This is probably a DLL hack. Note that this is also true for the Britons unique power (conquered cities get unhappiness, right?).

War will not be a prerequisite.
In that case the rebellion event will surely force the players into a state of war? Because otherwise the units will just be removed - with nonsensical consequences.

I think the rebels should get updated by their counterpart when they respawn... but we could always change this after testing!
But will they always be updated?

In my view they should always have matching Techs to their major player counterparts, but that might not be the effect you're looking for?

edit: No war weariness at all, then? :eek2:
 
mmmmm @War we could have some sort of system where if the oppoent is alive war is a prereq and if they are dead it is not...For example

Rome declares war on gaul... during the war there are chances for the rebellions. Rome and gaul declare peace and the chance goes into domestic rebellions instead (say if some cities are still in revolt) gaul is then destroyed by Greece. Rome can once again receive Occupational revolts (bearing in mind the counter which stops chances for occupational rebellions in a city after 30 turns or something) which allows gaul to be resurected again.

What do you think?


yes this is also true for the britons power. will there be any problems with that?


Ok, I guess the rebels are constantly updated...
 
mmmmm @War we could have some sort of system where if the oppoent is alive war is a prereq and if they are dead it is not...For example

Rome declares war on gaul... during the war there are chances for the rebellions. Rome and gaul declare peace and the chance goes into domestic rebellions instead (say if some cities are still in revolt) gaul is then destroyed by Greece. Rome can once again receive Occupational revolts (bearing in mind the counter which stops chances for occupational rebellions in a city after 30 turns or something) which allows gaul to be resurected again.

What do you think?
Well, occupation rebellions only occur immediately after conquest. Because I don't think that the CyCity.isOccupation() method will return True otherwise. So then there is no reason to have a turn limit on occupation rebellions either.

yes this is also true for the britons power. will there be any problems with that?
Right now the cause of the unhappiness with the Briton power is also "arrggh!" and not "we yearn to join our motherhand" (or whatever). Not exactly what you specified... :p

I'm figuring out how to make the civil war thing work with a one city only rebellion setup. I think I can get it to work, but this is probably how far this particular setup can be stretched... :p (The event is basically triggered in another way and there is an index of all cities flipping to the rebels. The trick is not only to make several individual cities/rebellions work as one civil war, but also to have the whole thing end in a timely fashion once the rebels have been vanquished. Well, I do like me a challenge...)
 
I prefer the britons having Aaarrggg! it was a nice coincidence!
 
Thinking about it... Perhaps its not such a good idea to use a shoe-horn in order to make the civil wars feature fit the rebellion mold? Sure, there are bits and pieces that can be utilized in the rebellion class, but I inevitably end up writing a lot of additional code just to accommodate the civil wars - defined as "rebellions".

Didn't you wanna have some historical events also, like some civil war and the long awaited Byzantine spawn? Because we could probably just leave the civil wars for later. Otherwise we might end up with overlapping modules.

Please feel free to specify these other things once again - and don't feel restricted by the rebellions feature!
 
Ok, I'm done with the first draft for all the various classes of rebellions. :king:
Spoiler :
Code:
class CulturalRebellion(Rebellion):

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

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = getHighestCityCulturalRival(pCity)
        if self.eRebelPlayer == -1:
            self.eRebelPlayer = self.eCityOwner + iNumMajorPlayers

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


class Resistance(Rebellion):

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

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

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

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

    def process(self):
        if ( Game.getGameTurn() - self.getRebellionTurn() >= iResistanceDomesticTurns
             and isChance(iResistanceDomesticPercentage) ):
            self.killRebelUnits()
            removeRebellion(self)
            pDomesticRebellion = DomesticRebellion.initRebellion(self.getCityOwner(), self.getCyCity())
            appendRebellion(pDomesticRebellion)


class DomesticRebellion(Rebellion):

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

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = self.eCityOwner + iNumMajorPlayers
        self.updateRebelTechs()

    def setNumUnits(self, pCity):
        iUnhappyLevel = pCity.unhappyLevel(0)
        iPopulation = pCity.getPopulation()
        iDistance = getDistanceToCapital(pCity)
        self.iNumUnits = iPopulation / 2 * iUnhappyLevel + iDistance


class MinorRevolt(Rebellion):

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

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = self.eCityOwner + iNumMajorPlayers
        self.updateRebelTechs()

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


class CivilWar(Rebellion):

    lCivilWarCities = list()

    @classmethod
    def isCivilWarActive(cls):
        return len(cls.lCivilWarCities) > 0

    @classmethod
    def checkConditions(cls, iNumDefectingCities, iNumTotalCities):
        return iNumDefectingCities >= iNumTotalCities * 0.3

    @classmethod
    def initCivilWar(cls, pCivPlayer, lDefectingCities):
        tBiggestCity = None, 0, None
        for pCity in lDefectingCities:
            pCivilWar = CivilWar(pCivPlayer, pCity)
            appendRebellion(pCivilWar)
            CivilWar.lCivilWarCities.append(self)
            pCivilWar.setActivate()
            pCivilWar.flipCity()
            iPopulation = pCity.getPopulation() 
            if iPopulation > tBiggestCity[1]:
                tBiggestCity = pCity, iPopulation, pCivilWar
        pRebelHive = tBiggestCity[2]
        pRebelHive.spawnRebelUnits()
        pRebelHive.terminationMessage = CivilWarTerminationMessage
        pRebelHive.addRebellionMessage()
        pRebelHive.getCityOwner().get(CyPlayer).getCapitalCity().changeExtraHappiness(-2)

    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = self.eCityOwner + iNumMajorPlayers
        self.updateRebelTechs()

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

    def setMessages(self, pCity):
        self.rebellionMessage = CivilWarMessage
        self.terminationMessage = ""
        self.unitSpawnMessage = CivilWarUnitSpawnMessage

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

    def checkTermination(self, iGameTurn):
        if not self.getRebelCiv().get(CyPlayer).isAlive():
            self.terminateCivilWar()
            return True

    def terminateCivilWar(self):
        for pCivilWar in getGlobalData("lCurrentRebellions"):
            if pCivilWar == self: continue
            removeRebellion(pCivilWar)
            pCivilWar.setDeactivate()
        self.getCityOwner().get(CyPlayer).getCapitalCity().changeExtraHappiness(2)


class SlaveRevolt(Rebellion):
    
    @classmethod
    def checkConditions(cls):
        return isChance(iSlaveRevoltPercentage)

    @classmethod
    def initSlaveRevolt(cls, pEventTriggeredData):
        pCivPlayer = instance(pEventTriggeredData.ePlayer)
        pCity = pCivPlayer.get(CyPlayer).getCity(pEventTriggeredData.iCityID)
        pSlaveRevolt = SlaveRevolt(pCivPlayer, pCity)
        appendRebellion(pSlaveRevolt)
        pSlaveRevolt.setActivate()
        pSlaveRevolt.spawnRebelUnits()
        pSlaveRevolt.addRebellionMessage()
        
    def setRebelPlayer(self, pCity):
        self.eRebelPlayer = eSlaves
        
    def setNumUnits(self, pCity):
        self.iNumUnits = pCity.getPopulation()

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

    def checkTermination(self, iGameTurn):
        if self.getCityOwner().get(CyPlayer).getCivics(eLabor) != eSlavery:
            self.revertSlaveCities()
            return True
        unitFlag = self.getUnitFlag()
        for pUnit in self.getRebelCiv().get(PyPlayer).getUnitList():
            if pUnit.getScriptData() == unitFlag:
                return False
        return True

    def revertSlaveCities(self):
        pPlayer = self.getCityOwner().get(CyPlayer)
        for pCity in (city.GetCy() for city in self.getRebelCiv().get(PyPlayer).getCityList()):
            pCityOwner.acquireCity(pCity, False, False)
The slave rebellion should by the way be triggered by adding this code into CvRandomEventInterface.py:
Spoiler :
Code:
### Jamie's Rome mod

def doSlaveRevolt(argsList):
	from Rebellion import SlaveRevolt
	kTriggeredData = argsList[1]
	ePlayer = kTriggeredData.ePlayer
	pPlayer = gc.getPlayer(ePlayer)
	pCity = pPlayer.getCity(kTriggeredData.iCityID)
	if SlaveRevolt.checkConditions(pCity):
		SlaveRevolt(ePlayer, pCity)
The function name doSlaveRevolt of course gets added to the <PythonCallback> tag in CIV4EventInfos.xml in the appropriate places (I'm guessing all 3 varieties of slave revolt events).

This of course needs to be tested in practice. :rolleyes: And the same goes for the rest of it - I need the new rebel players in place for said testing...
 
the only historical civil war I want at the moment is the byzantium spawn... otherwise no others (for the moment, but I will need something to base this on :D), of course the civil war rebellion still stands

speeching of which, what shoehorns would you be talking about?

I get the slight feeling that we may need to update the popup text just a little from the standard rebels modcomp text! (could you make it into a KEY_TEXT_REBELS_POPUP tag for me? you be easier to translate which would be VERY nessicary seeing though how important this feature has become! And while I remember could you do something simmilar for the rebellions names? Probs along the lines of a KEY_TEXT_"insert rebellion here"_REBELLION)
 
the only historical civil war I want at the moment is the byzantium spawn... otherwise no others (for the moment, but I will need something to base this on :D), of course the civil war rebellion still stands

speeching of which, what shoehorns would you be talking about?
Oh, never mind. I believe I already did the code needed. :rolleyes: We'll see what we'll do about Byzantium, eventually.

I get the slight feeling that we may need to update the popup text just a little from the standard rebels modcomp text! (could you make it into a KEY_TEXT_REBELS_POPUP tag for me? you be easier to translate which would be VERY nessicary seeing though how important this feature has become! And while I remember could you do something simmilar for the rebellions names? Probs along the lines of a KEY_TEXT_"insert rebellion here"_REBELLION)
Everything related to messages is something that you will be able to edit yourself going forward. But I'll make sure to add functionality to the popup allowing for multiple languages.

I don't think I'm gonna bother with XML tags for all messages at this point - unless you get all the XML files with the translations done before I finish, that is. Because this is something you're well equipped to take care of yourself once I hand over the reigns.
 
One would think that its still a bit early to get all Santa on someone, not? ;) (Well, obviously not the CFC staff... :rolleyes:)

Oh, and I forgot to mention: As the civil war code (aka "The Shoe-Horn") stands now there can only be one civil war in effect in the game at any one point. Hopefully this doesn't break your design. :p (Its supposed to be a rare event anyway, right?)
 
yeah that should be fine! (when I see those little hats, that's when it's christmas for me :D)
 
Another thought: The civil war rebellion flips all cities with angry citizens, right? (I'm trying to also flip all units garrisoned in those cities.) And the largest flipped city gets 6 free rebel units - but shouldn't that city also become the rebel capital?

edit: And what about having whip anger as a condition for the slave revolt? Perhaps even increased probability with more whip anger!
 
yeah that sounds great! definatly whips should increase revolt chance. I guess the highest pop city sound become the capital
 
definatly whips should increase revolt chance.
What sort of calculation would you like, then? Something like iSlaveRevoltPercentage = iNumWhipAnger * iSlaveRevoltDenominator, where I just give iSlaveRevoltDenominator a default value of 100 and you can lower it to whatever you need later? This calculation also means that there can be no slave rebellion (the unit spawn event, not the regular random event) if there is no whip-anger. Or should there always be a base chance, say equal to iSlaveRevoltDenominator? (So the calculation would in fact be iSlaveRevoltPercentage = iNumWhipAnger * iSlaveRevoltDenominator + iSlaveRevoltDenominator.)
I guess the highest pop city sound become the capital
I'm adding the code right away.
 
About the cultural rebellions and diplomacy - it turned out very difficult to have war as a condition for the event (because I'm checking who the player receiving the units will be only when the event has already fired - so it would be hard to check that players diplomatic status before I know who it is!), so I reverted to declaring war once the event occurs instead. :p

I suggest you test this approach before I do a complete rewrite.
 
yes there should be a chance without whip anger!
 
Also, these are the rebellion messages I've added to the ModSettings module:
PHP:
defaultRebellionMessage = "A rebellion has broken out in the city of %s1!"
defaultTerminationMessage = "The rebellion in %s1 has ended!"
defaultUnitSpawnMessage = "Rebel units are forming around %s1!"
civilWarMessage = "The %s1 Empire is descending into Civil War!"
civilWarTerminationMessage = "The %s1 Civil War has come to an end!"
civilWarUnitSpawnMessage = "A Rebel Army is forming around the rebel city of %s1!"
slaveRevoltMessage = "Escaped slaves are forming military units in the countryside around %s1!" 
slaveRevoltTerminationMessage = "All slave units are laying down arms and re-entering the work-force as free men!"
The first 3 strings are used if no rebellion type specific message has been defined. The next 3 are only used for civil wars (making the default messages void) and the last 2 are the slave revolt messages. Note that there is no message for slave unit spawns - no rebellion type actually has any unit spawns post the actual event. (The civil war event uses a special unit spawn message anyway, as specified above.)

Unit spawns after the actual event is however something I would probably personally add to the design. (Perhaps especially for the slave revolt event.) Why would all units form on the first turn? I'd rather have units spawn continuously - and probably make the event terminate at some point - with or without disbanding the rebel units.

If you're gonna start editing and adding messages I suggest you do this in a XML file with defined tags. Then you simply add those tags (in quotations) to the code above, replacing my sample strings. Remember that there are potentially up to 3 different messages per rebellion type! But also that any one can be omitted - then the code simply uses the default message (which you should also define in the XML).
 
if the rebel units trickly in and don't arrive as one there is less chance of it becoming effective...
 
Yeah, sure, but there could still be reinforcements coming in every (other/random) turn. Like one or two units (or whatever - depending on what you want - it can also be entirely rebellion type dependent), making it a priority to stomp out all remaining units in a timely fashion. Because the longer the event lingers (rebel units alive) - the more there will be.

Your call. I have already built in functionality for this sort of thing.
 
Back
Top Bottom