Zechnophobe
Strategy Lich
In an attempt to make new Scenario's easier to make, I have changed my local files to split apart the code for each, and I'd like you to use this implementation for the live version. The way I have it set up now works thusly:
A new scenario uses the name SCENARIO_NAME.py, and defines each of the functions currently in Scenario Functions. Whereas Scenario Functions now acts simply as a pass through that checks to see what scenario is active. For instance, this would use this function:
Which would be called like:
Generate a new SCENARIO.PY from a template (Which I have and can provide).
Lastly, I removed all 'extra' function from ScenarioFunctions, and placed them in CustomScenarioFunctions (Such as the getHeroXP) since these break the design paradigm (You should only have functions in the scope of loading or working with scenarios, not grab bag functions):
The benefits which this reap (considerable!) Are that all the effects of a scenario are now in their own area. For Example, the Splintered Court:
Assuming you agree this is a good idea, how would you like me to get my files to you? (You don't want to have to duplicate what I've done). Note that this is up through patch 'd', so you'd have to merge it with 'e' before working on 'f'. I have not created a SCENARIO file for Wages of Sin since it didn't look anywhere near completion.
Do you have a version-ing system I could just check these files into or something? Let me know.
A new scenario uses the name SCENARIO_NAME.py, and defines each of the functions currently in Scenario Functions. Whereas Scenario Functions now acts simply as a pass through that checks to see what scenario is active. For instance, this would use this function:
Code:
def getScenario(self):
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_AGAINST_THE_WALL):
return SCENARIO_AGAINST_THE_WALL.SCENARIO_AGAINST_THE_WALL()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_AGAINST_THE_GREY):
return SCENARIO_AGAINST_THE_GREY.SCENARIO_AGAINST_THE_GREY()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_INTO_THE_DESERT):
return SCENARIO_INTO_THE_DESERT.SCENARIO_INTO_THE_DESERT()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_FALL_OF_CUANTINE):
return SCENARIO_FALL_OF_CUANTINE.SCENARIO_FALL_OF_CUANTINE()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_GIFT_OF_KYLORIN):
return SCENARIO_GIFT_OF_KYLORIN.SCENARIO_GIFT_OF_KYLORIN()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_GRAND_MENAGERIE):
return SCENARIO_GRAND_MENAGERIE.SCENARIO_GRAND_MENAGERIE()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_THE_BLACK_TOWER):
return SCENARIO_THE_BLACK_TOWER.SCENARIO_THE_BLACK_TOWER()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_THE_RADIANT_GUARD):
return SCENARIO_THE_RADIANT_GUARD.SCENARIO_THE_RADIANT_GUARD()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_BARBARIAN_ASSAULT):
return SCENARIO_BARBARIAN_ASSAULT.SCENARIO_BARBARIAN_ASSAULT()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_BENEATH_THE_HEEL):
return SCENARIO_BENEATH_THE_HEEL.SCENARIO_BENEATH_THE_HEEL()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_BLOOD_OF_ANGELS):
return SCENARIO_BLOOD_OF_ANGELS.SCENARIO_BLOOD_OF_ANGELS()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_LORD_OF_THE_BALORS):
return SCENARIO_LORD_OF_THE_BALORS.SCENARIO_LORD_OF_THE_BALORS()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_MULCARN_REBORN):
return SCENARIO_MULCARN_REBORN.SCENARIO_MULCARN_REBORN()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_RETURN_OF_WINTER):
return SCENARIO_RETURN_OF_WINTER.SCENARIO_RETURN_OF_WINTER()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_THE_CULT):
return SCENARIO_THE_CULT.SCENARIO_THE_CULT()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_THE_MOMUS):
return SCENARIO_THE_MOMUS.SCENARIO_THE_MOMUS()
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_WB_THE_SPLINTERED_COURT):
return SCENARIO_THE_SPLINTERED_COURT.SCENARIO_THE_SPLINTERED_COURT()
Which would be called like:
Code:
def doTurn(self):
myScenario = self.getScenario()
myScenario.doTurn()
Generate a new SCENARIO.PY from a template (Which I have and can provide).
Lastly, I removed all 'extra' function from ScenarioFunctions, and placed them in CustomScenarioFunctions (Such as the getHeroXP) since these break the design paradigm (You should only have functions in the scope of loading or working with scenarios, not grab bag functions):
Code:
class CustomScenarioFunctions:
def addPopupWB(self, szText, sDDS):
szTitle = CyGameTextMgr().getTimeStr(CyGame().getGameTurn(), false)
screen = CyGInterfaceScreen( "MainInterface", CvScreenEnums.MAIN_INTERFACE )
xRes = screen.getXResolution()
yRes = screen.getYResolution()
popup = PyPopup.PyPopup(-1)
popup.addDDS(sDDS, 0, 0, 500, 800)
popup.addSeparator()
popup.setHeaderString(szTitle)
popup.setBodyString(szText)
popup.setPosition((xRes - 840) / 2,(yRes - 640) / 2)
popup.setSize(840, 640)
popup.launch(true, PopupStates.POPUPSTATE_IMMEDIATE)
def getHeroXP(self, iPlayer, iUnit):
"""returns the amount of XP that the given unit has, owned by a player. If iUnit is not unique
then it will return the xp of the last unit found. If no units are found, returns -1"""
apUnitList = PyPlayer(iPlayer).getUnitList()
iXP = -1
for pLoopUnit in apUnitList:
if pLoopUnit.getUnitType() == iUnit:
if pLoopUnit.getExperience() > iXP:
iXP = pLoopUnit.getExperience()
return iXP
def giftHeroXP(self, iPlayer, iUnit, iXP):
"""Finds all units of type 'iUnit' owned by iPlayer, and gives them 'iXP' experience."""
apUnitList = PyPlayer(iPlayer).getUnitList()
for pLoopUnit in apUnitList:
if pLoopUnit.getUnitType() == iUnit:
pLoopUnit.changeExperience(iXP, -1, False, False, False)
The benefits which this reap (considerable!) Are that all the effects of a scenario are now in their own area. For Example, the Splintered Court:
Spoiler :
Code:
class SCENARIO_THE_SPLINTERED_COURT:
def doTurn(self):
iPlayer = 0
pPlayer = gc.getPlayer(iPlayer)
if gc.getGame().getScenarioCounter() == 7:
gc.getGame().changeScenarioCounter(-7)
else:
gc.getGame().changeScenarioCounter(1)
iCalabim = gc.getInfoTypeForString('CIVILIZATION_CALABIM')
iDoviello = gc.getInfoTypeForString('CIVILIZATION_DOVIELLO')
iDuin = gc.getInfoTypeForString('UNIT_DUIN')
iImmigrants = gc.getInfoTypeForString('EVENTTRIGGER_IMMIGRANTS')
iLjosalfar = gc.getInfoTypeForString('CIVILIZATION_LJOSALFAR')
iStrong = gc.getInfoTypeForString('PROMOTION_STRONG')
iSvartalfar = gc.getInfoTypeForString('CIVILIZATION_SVARTALFAR')
iVampire = gc.getInfoTypeForString('PROMOTION_VAMPIRE')
iWerewolf = gc.getInfoTypeForString('UNIT_WEREWOLF')
for iPlayer in range(gc.getMAX_PLAYERS()):
pPlayer = gc.getPlayer(iPlayer)
if pPlayer.isAlive():
if pPlayer.getCivilizationType() == iCalabim:
if gc.getGame().getScenarioCounter() == 0 or gc.getGame().getScenarioCounter() == 4:
bState = False
if gc.getGame().getScenarioCounter() == 4:
bState = True
py = PyPlayer(iPlayer)
for pLoopUnit in py.getUnitList():
if pLoopUnit.isHasPromotion(iVampire):
pLoopUnit.setHasPromotion(iStrong, bState)
if pPlayer.getCivilizationType() == iDoviello:
if gc.getGame().getScenarioCounter() == 0:
py = PyPlayer(iPlayer)
lList = []
for pLoopUnit in py.getUnitList():
if pLoopUnit.getScenarioCounter() != -1:
lList.append(pLoopUnit)
for pLoopUnit in lList:
newUnit = pPlayer.initUnit(pLoopUnit.getScenarioCounter(), pLoopUnit.getX(), pLoopUnit.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
newUnit.convert(pLoopUnit)
newUnit.setScenarioCounter(-1)
if gc.getGame().getScenarioCounter() == 4:
py = PyPlayer(iPlayer)
lList = []
for pLoopUnit in py.getUnitList():
if not pLoopUnit.isOnlyDefensive():
if pLoopUnit.getUnitType() != iDuin:
if pLoopUnit.isAlive():
lList.append(pLoopUnit)
for pLoopUnit in lList:
iUnit = pLoopUnit.getUnitType()
newUnit = pPlayer.initUnit(iWerewolf, pLoopUnit.getX(), pLoopUnit.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
newUnit.convert(pLoopUnit)
newUnit.setScenarioCounter(iUnit)
if pPlayer.getCivilizationType() == iLjosalfar or pPlayer.getCivilizationType() == iSvartalfar:
if gc.getGame().getScenarioCounter() == 0:
if CyGame().getSorenRandNum(100, "Immigrants") < 10:
lList = []
for pyCity in PyPlayer(iPlayer).getCityList():
pCity = pyCity.GetCy()
lList.append(pCity)
if len(lList) > 0:
pCity = lList[CyGame().getSorenRandNum(len(lList), "Pick City")-1]
triggerData = pPlayer.initTriggeredData(iImmigrants, true, -1, pCity.getX(), pCity.getY(), iPlayer, pCity.getID(), -1, -1, -1, -1)
def gameStart(self):
gc.getGame().incrementUnitClassCreatedCount(gc.getInfoTypeForString('UNITCLASS_LUCIAN'))
gc.getGame().incrementUnitClassCreatedCount(gc.getInfoTypeForString('UNITCLASS_TROJAN_HORSE'))
gc.getTeam(0).setPermanentWarPeace(1, True)
gc.getTeam(1).setPermanentWarPeace(0, True)
def getIntro(self):
introText = "TXT_KEY_WB_THE_SPLINTERED_COURT_INTRO"
return CyTranslator().getText(introText,())
def getIntroArt(self):
return 'art/interface/popups/The Splintered Court.dds'
def cannotResearch(self, ePlayer, eTech, bTrade):
pPlayer = gc.getPlayer(ePlayer)
return false
def cannotTrain(self, pCity, eUnit, bContinue, bTestVisible, bIgnoreCost, bIgnoreUpgrades):
ePlayer = pCity.getOwner()
pPlayer = gc.getPlayer(ePlayer)
return false
def getGoalTag(self, pPlayer):
szBuffer = u"<font=2>"
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_LJOSALFAR'):
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_WB_THE_SPLINTERED_COURT_LJOSALFAR_GOAL", (), gc.getInfoTypeForString("COLOR_RED"))
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SVARTALFAR'):
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_WB_THE_SPLINTERED_COURT_SVARTALFAR_GOAL", (), gc.getInfoTypeForString("COLOR_RED"))
if gc.getGame().getScenarioCounter() == 0:
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_MESSAGE_DAY_CYCLE_DAWN", (), gc.getInfoTypeForString("COLOR_RED"))
if gc.getGame().getScenarioCounter() == 1:
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_MESSAGE_DAY_CYCLE_MORNING", (), gc.getInfoTypeForString("COLOR_RED"))
if gc.getGame().getScenarioCounter() == 2:
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_MESSAGE_DAY_CYCLE_NOON", (), gc.getInfoTypeForString("COLOR_RED"))
if gc.getGame().getScenarioCounter() == 3:
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_MESSAGE_DAY_CYCLE_AFTERNOON", (), gc.getInfoTypeForString("COLOR_RED"))
if gc.getGame().getScenarioCounter() == 4:
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_MESSAGE_DAY_CYCLE_DUSK", (), gc.getInfoTypeForString("COLOR_RED"))
if gc.getGame().getScenarioCounter() == 5:
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_MESSAGE_DAY_CYCLE_EARLY_NIGHT", (), gc.getInfoTypeForString("COLOR_RED"))
if gc.getGame().getScenarioCounter() == 6:
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_MESSAGE_DAY_CYCLE_MIDNIGHT", (), gc.getInfoTypeForString("COLOR_RED"))
if gc.getGame().getScenarioCounter() == 7:
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_MESSAGE_DAY_CYCLE_LATE_NIGHT", (), gc.getInfoTypeForString("COLOR_RED"))
return szBuffer
def onCityAcquired(self, iPreviousOwner, iNewOwner, pCity, bConquest, bTrade):
pPlayer = gc.getPlayer(iNewOwner)
def onCityBuilt(self, pCity):
iPlayer = pCity.getOwner()
pPlayer = gc.getPlayer(iPlayer)
def onCityRazed(self, city, iPlayer):
pass
def onImprovementDestroyed(self, iImprovement, iOwner, iX, iY):
pass
def atRangeJungleAltar(self, pCaster, pPlot):
pass
def onMoveJungleAltar(self, pCaster, pPlot):
pass
def onMoveMirrorOfHeaven(self, pCaster, pPlot):
pass
def onMovePortal(self, pCaster, pPlot):
pass
def onMoveWarningPost(self, pCaster, pPlot):
pass
def onReligionFounded(self, iReligion, iFounder):
pass
def onTechAcquired(self, iTechType, iTeam, iPlayer, bAnnounce):
pass
def onUnitCreated(self, pUnit):
pass
def onUnitKilled(self, pUnit):
pass
def onVictory(self, iPlayer, iVictory):
pPlayer = gc.getPlayer(iPlayer)
gc.getGame().changeTrophyValue("TROPHY_WB_THE_SPLINTERED_COURT", 1)
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_LJOSALFAR'):
gc.getGame().setTrophyValue("TROPHY_WB_THE_SPLINTERED_COURT_LJOSALFAR", 1)
gc.getGame().setTrophyValue("TROPHY_WB_THE_SPLINTERED_COURT_SVARTALFAR", 0)
csf.addPopupWB(CyTranslator().getText("TXT_KEY_WB_THE_SPLINTERED_COURT_VICTORY_LJOSALFAR",()), 'art/interface/popups/The Splintered Court Ljosalfar Victory.dds')
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SVARALFAR'):
gc.getGame().setTrophyValue("TROPHY_WB_THE_SPLINTERED_COURT_LJOSALFAR", 0)
gc.getGame().setTrophyValue("TROPHY_WB_THE_SPLINTERED_COURT_SVARTALFAR", 1)
csf.addPopupWB(CyTranslator().getText("TXT_KEY_WB_THE_SPLINTERED_COURT_VICTORY_SVARTALFAR",()), 'art/interface/popups/The Splintered Court Svartalfar Victory.dds')
def openChest(self, caster, pPlot):
pass
def playerDefeated(self, pPlayer):
bLose = False
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_LJOSALFAR'):
bLose = True
iWinningTeam = 2
if gc.getPlayer(0).isAlive():
bLose = False
if gc.getPlayer(1).isAlive():
bLose = False
if gc.getPlayer(2).isAlive():
bLose = False
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SVARTALFAR'):
bLose = True
iWinningTeam = 1
if gc.getPlayer(3).isAlive():
bLose = False
if gc.getPlayer(4).isAlive():
bLose = False
if gc.getPlayer(5).isAlive():
bLose = False
iHumanPlayer = -1
for iLoopPlayer in range(gc.getMAX_PLAYERS()):
pLoopPlayer = gc.getPlayer(iLoopPlayer)
if pLoopPlayer.isAlive():
if pLoopPlayer.isHuman():
if pLoopPlayer.getCivilizationType() != pPlayer.getCivilizationType():
iHumanPlayer = iLoopPlayer
if iHumanPlayer != -1:
if pPlayer.getLeaderType() == gc.getInfoTypeForString('LEADER_AMELANCHIER'):
iEvent = gc.getInfoTypeForString('EVENTTRIGGER_WB_SPLINTERED_COURT_DEFEATED_AMELANCHIER')
triggerData = gc.getPlayer(iHumanPlayer).initTriggeredData(iEvent, true, -1, -1, -1, iHumanPlayer, -1, -1, -1, -1, -1)
if pPlayer.getLeaderType() == gc.getInfoTypeForString('LEADER_THESSA'):
iEvent = gc.getInfoTypeForString('EVENTTRIGGER_WB_SPLINTERED_COURT_DEFEATED_THESSA')
triggerData = gc.getPlayer(iHumanPlayer).initTriggeredData(iEvent, true, -1, -1, -1, iHumanPlayer, -1, -1, -1, -1, -1)
if pPlayer.getLeaderType() == gc.getInfoTypeForString('LEADER_RIVANNA'):
iEvent = gc.getInfoTypeForString('EVENTTRIGGER_WB_SPLINTERED_COURT_DEFEATED_RIVANNA')
triggerData = gc.getPlayer(iHumanPlayer).initTriggeredData(iEvent, true, -1, -1, -1, iHumanPlayer, -1, -1, -1, -1, -1)
if pPlayer.getLeaderType() == gc.getInfoTypeForString('LEADER_VOLANNA'):
iEvent = gc.getInfoTypeForString('EVENTTRIGGER_WB_SPLINTERED_COURT_DEFEATED_VOLANNA')
triggerData = gc.getPlayer(iHumanPlayer).initTriggeredData(iEvent, true, -1, -1, -1, iHumanPlayer, -1, -1, -1, -1, -1)
if pPlayer.getLeaderType() == gc.getInfoTypeForString('LEADER_ARENDEL'):
if not bLose:
cf.addPopup(CyTranslator().getText("TXT_KEY_WB_THE_SPLINTERED_WOOD_DEFEATED_ARENDEL",()),'art/interface/popups/Arendel.dds')
if pPlayer.getLeaderType() == gc.getInfoTypeForString('LEADER_FAERYL'):
if not bLose:
cf.addPopup(CyTranslator().getText("TXT_KEY_WB_THE_SPLINTERED_WOOD_DEFEATED_FAERYL",()),'art/interface/popups/Faeryl.dds')
if bLose:
gc.getGame().setWinner(iWinningTeam, 2)
Assuming you agree this is a good idea, how would you like me to get my files to you? (You don't want to have to duplicate what I've done). Note that this is up through patch 'd', so you'd have to merge it with 'e' before working on 'f'. I have not created a SCENARIO file for Wages of Sin since it didn't look anywhere near completion.
Do you have a version-ing system I could just check these files into or something? Let me know.