from CvPythonExtensions import *
from CivPlayer import *
##Helpers##
def getIndex(category, entry):
"""
Returns the enumerated index value (integer) of the specified entry belonging to the
specified category, as specified by the XML.
"""
key = category.replace(" ", "") + "_" + entry.replace(" ", "_")
return gc.getInfoTypeForString(key.upper())
def initActiveRebellions():
setGlobalData("Active Rebellions", ([], 0))
def getActiveRebellions():
return getGlobalData("Active Rebellions")
def setActiveRebellions(pRebellion):
n = getActiveRebellions()[1] + 1
lRebellions = getActiveRebellions()[0]
lRebellions.append(pRebellion)
setGlobalData("Active Rebellions", (lRebellions, n))
def removeRebellion(pRebellion):
n = getActiveRebellions()[1] - 1
lRebellions = getActiveRebellions()[0]
lRebellions.remove(pRebellion)
setGlobalData("Active Rebellions", (lRebellions, n))
def createRebellion(pCity, pCivPlayer):
pRebellion = Rebellion(pCity, pCivPlayer)
setActiveRebellions(pRebellion)
if Game.getSorenRandNum(100, "Rebellion Chance") >= iFlipChance:
pRebellion.spawnRebels()
else:
pRebellion.flipCity()
pRebellion.spawnGarrison()
def isRebellionActive(pRebellion):
sUnitData = "RebelUnit City:%s" % pRebellion.pCity.getName()
for pUnit in (eRebelCiv.get(CyPlayer).getUnit(iNum) for iNum in xrange(eRebelCiv.get(CyPlayer).getNumUnits())):
if pUnit.getScriptData() == sUnitData:
return True
for pCity in (eRebelCiv.get(CyPlayer).getCity(iNum) for iNum in xrange(eRebelCiv.get(CyPlayer).getNumCities())):
if pCity.getName() == pRebellion.pCity.getName():
return True
return False
##Constants##
bActive = True #set to False to turn rebels off
gc = CyGlobalContext()
Game = CyGame()
#eRebelCiv = pointer("Rome", playerID) #edit if you want a rebel player, use short desc of civ
eRebelCiv = instance(gc.getBARBARIAN_PLAYER())
tGarrisonUnits = (getIndex("Unit", "Archer"), getIndex("Unit", "Archer"))
tRebelUnits = (getIndex("Unit", "Swordsman"), getIndex("Unit", "Swordsman"))
eTransitionTech1 = getIndex("Tech", "Archery")
eTransitionTech2 = getIndex("Tech", "Iron Working")
iChance = 100
iMinUnhappy = 4
iMinUnhealthy = 6
iMinDistance = 15
iFlipChance = 25
maxRebellionsPerPlayer = 3
##Class code##
class Rebellion:
def __init__(self, pCity, pOwner):
self.pCity = pCity
self.pOwner = pOwner
@classmethod
def refreshRebels(cls):
for pRebellion in getActiveRebllions()[0]:
if not isRebellionActive(pRebellion): removeRebellion(pRebellion)
@classmethod
def runCheck(cls):
if not bActive: return
for pCivPlayer in CivPlayer.getPlayers():
pPlayer = CivPlayer.get(CyPlayer)
n = 0
for pRebellion in getActiveRebellions()[0]:
if pRebellion.pOwner == pCivPlayer: n+=1
if n > 3: continue
for i in range(pPlayer.getNumCities()):
pCity = pPlayer.getCity(i)
bInRebellion = False
for pRebellion in getActiveRebellions()[0]:
if pRebellion.pCity == pCity: bInRebellion = True
if bInRebellion: continue
if cls.calculateChance(pCity, pPlayer):
createRebellion(pCity, pCivPlayer)
@classmethod
def calculateChance(cls, pCity, pOwner):
pCapital = pOwner.get(CyPlayer).getCapitalCity()
iDistance = max((pCity.getX() - pCapital.getX()),(pCity.getY() - pCapital.getY()))
if iDistance >= iMinDistance and (pCity.angryPopulation(0) - (pCity.getWarWearinessPercentAnger()/100)) >= iMinUnhappy:
#y is directly proportional to ((x power 11) power 0.11111) * iChance/100 math FTW :p
iModifiedChance = (float(iChance)/100) * (float(iDistance) ** (11.0 / 9.0))
return (Game.getSorenRandNum(100, "Rebellion Chance") <= iModifiedChance)
else: return False
def spawnRebels(self):
if self.pOwner.get(CyTeam).isHasTech(eTransitionTech2):
eUnit = tRebelUnits[1]
lPlots = [self.pCity.getCityIndexPlot(iIndex) for iIndex in xrange(19) if not ( self.pCity.getCityIndexPlot(iIndex).isPeak() or
self.pCity.getCityIndexPlot(iIndex).isWater() or
self.pCity.getCityIndexPlot(iIndex).isCity() )]
pRandPlot = lPlots[Game.getSorenRandNum(len(lPlots), "Rand Plot")]
CivPlayer(eRebelCiv).get(PyPlayer).initUnit(pUnit.getUnitTpe(), pPlot.getX(), pPlot.getY(), 8)
else:
eUnit = tRebelUnits[0]
lPlots = [self.pCity.getCityIndexPlot(iIndex) for iIndex in xrange(19) if not ( self.pCity.getCityIndexPlot(iIndex).isPeak() or
self.pCity.getCityIndexPlot(iIndex).isWater() or
self.pCity.getCityIndexPlot(iIndex).isCity() )]
pRandPlot = lPlots[Game.getSorenRandNum(len(lPlots), "Rand Plot")]
CivPlayer(eRebelCiv).get(PyPlayer).initUnit(pUnit.getUnitTpe(), pPlot.getX(), pPlot.getY(), 8)
for pUnit in (pRandPlot.getUnit(iUnit) for iUnit in range(pRandPlot.getNumUnits())):
if pUnit.getOwner == eRebelCiv:
sUnitData = "RebelUnit City:%s" % self.pCity.getName()
pUnit.setScriptData(sUnitData)
def flipCity(self):
pPlot = self.pCity.plot()
lUnits = [pUnit for pUnit in (pPlot.getUnit(iUnit) for iUnit in range(pPlot.getNumUnits())) if pUnit.getOwner() == self.pCity.getOwner()]
lUnitsData = lUnits
for pUnit in lUnits:
pUnit.kill(False, self.pCity.getOwner())
CivPlayer(eRebelCiv).get(CyPlayer).acquireCity(self.pCity, True, False)
for pUnit in lUnitsData:
CivPlayer(eRebelCiv).get(PyPlayer).initUnit(pUnit.getUnitTpe(), self.pCity.getX(), self.pCity.getY(), 1)
def spawnGarrison(self):
if self.pOwner.get(CyTeam).isHasTech(eTransitionTech1):
eUnit = tGarrisonUnits[1]
CivPlayer(eRebelCiv).get(PyPlayer).initUnit(eUnit, self.pCity.getX(), self.pCity.getY(), 6)
else:
eUnit = tGarrisonUnits[0]
CivPlayer(eRebelCiv).get(PyPlayer).initUnit(eUnit, self.pCity.getX(), self.pCity.getY(), 6)