from toontown.toonbase.ToontownBattleGlobals import * import types from direct.fsm import StateData from direct.fsm import ClassicFSM, State from direct.fsm import State import TownBattleAttackPanel import TownBattleWaitPanel import TownBattleChooseAvatarPanel import TownBattleSOSPanel import TownBattleSOSPetSearchPanel import TownBattleSOSPetInfoPanel import TownBattleToonPanel import TownBattleCogPanel from toontown.toontowngui import TTDialog from direct.directnotify import DirectNotifyGlobal from toontown.battle import BattleBase from toontown.toonbase import ToontownTimer from direct.showbase import PythonUtil from toontown.toonbase import TTLocalizer from toontown.pets import PetConstants from direct.gui.DirectGui import * from toontown.battle import FireCogPanel class TownBattle(StateData.StateData): notify = DirectNotifyGlobal.directNotify.newCategory('TownBattle') evenPos = (0.75, 0.25, -0.25, -0.75) oddPos = (0.5, 0, -0.5) def __init__(self, doneEvent): StateData.StateData.__init__(self, doneEvent) self.numCogs = 1 self.creditLevel = None self.luredIndices = [] self.trappedIndices = [] self.numToons = 1 self.toons = [] self.localNum = 0 self.time = 0 self.bldg = 0 self.track = -1 self.level = -1 self.target = 0 self.toonAttacks = [(-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0)] self.fsm = ClassicFSM.ClassicFSM('TownBattle', [ State.State('Off', self.enterOff, self.exitOff, ['Attack']), State.State('Attack', self.enterAttack, self.exitAttack, ['ChooseCog', 'ChooseToon', 'AttackWait', 'Run', 'Fire', 'SOS']), State.State('ChooseCog', self.enterChooseCog, self.exitChooseCog, ['AttackWait', 'Attack']), State.State('AttackWait', self.enterAttackWait, self.exitAttackWait, ['ChooseCog', 'ChooseToon', 'Attack']), State.State('ChooseToon', self.enterChooseToon, self.exitChooseToon, ['AttackWait', 'Attack']), State.State('Run', self.enterRun, self.exitRun, ['Attack']), State.State('SOS', self.enterSOS, self.exitSOS, ['Attack', 'AttackWait', 'SOSPetSearch', 'SOSPetInfo']), State.State('SOSPetSearch', self.enterSOSPetSearch, self.exitSOSPetSearch, ['SOS', 'SOSPetInfo']), State.State('SOSPetInfo', self.enterSOSPetInfo, self.exitSOSPetInfo, ['SOS', 'AttackWait']), State.State('Fire', self.enterFire, self.exitFire, ['Attack', 'AttackWait'])], 'Off', 'Off') self.runPanel = TTDialog.TTDialog(dialogName='TownBattleRunPanel', text=TTLocalizer.TownBattleRun, style=TTDialog.TwoChoice, command=self.__handleRunPanelDone) self.runPanel.hide() self.attackPanelDoneEvent = 'attack-panel-done' self.attackPanel = TownBattleAttackPanel.TownBattleAttackPanel(self.attackPanelDoneEvent) self.waitPanelDoneEvent = 'wait-panel-done' self.waitPanel = TownBattleWaitPanel.TownBattleWaitPanel(self.waitPanelDoneEvent) self.chooseCogPanelDoneEvent = 'choose-cog-panel-done' self.chooseCogPanel = TownBattleChooseAvatarPanel.TownBattleChooseAvatarPanel(self.chooseCogPanelDoneEvent, 0) self.chooseToonPanelDoneEvent = 'choose-toon-panel-done' self.chooseToonPanel = TownBattleChooseAvatarPanel.TownBattleChooseAvatarPanel(self.chooseToonPanelDoneEvent, 1) self.SOSPanelDoneEvent = 'SOS-panel-done' self.SOSPanel = TownBattleSOSPanel.TownBattleSOSPanel(self.SOSPanelDoneEvent) self.SOSPetSearchPanelDoneEvent = 'SOSPetSearch-panel-done' self.SOSPetSearchPanel = TownBattleSOSPetSearchPanel.TownBattleSOSPetSearchPanel(self.SOSPetSearchPanelDoneEvent) self.SOSPetInfoPanelDoneEvent = 'SOSPetInfo-panel-done' self.SOSPetInfoPanel = TownBattleSOSPetInfoPanel.TownBattleSOSPetInfoPanel(self.SOSPetInfoPanelDoneEvent) self.fireCogPanelDoneEvent = 'fire-cog-panel-done' self.FireCogPanel = FireCogPanel.FireCogPanel(self.fireCogPanelDoneEvent) self.rolloverFrame = DirectFrame(aspect2d, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(0.6, 1.0, 0.4, 1), geom_scale=(0.5, 0.3, 0.2), text_scale=0.05, text_pos=(0, 0.0125), text='', text_fg=(0, 0, 0, 1), pos=(0.4, 0, 0)) self.rolloverFrame.setBin('gui-popup', 0) self.rolloverFrame.hide() self.toonPanels = [TownBattleToonPanel.TownBattleToonPanel(self) for i in xrange(4)] self.cogPanels = [TownBattleCogPanel.TownBattleCogPanel(self) for i in xrange(4)] self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.setScale(0.4) self.timer.hide() def cleanup(self): self.ignore(self.attackPanelDoneEvent) self.unload() del self.fsm self.runPanel.cleanup() del self.runPanel del self.attackPanel del self.waitPanel del self.chooseCogPanel del self.chooseToonPanel del self.SOSPanel del self.FireCogPanel del self.SOSPetSearchPanel del self.SOSPetInfoPanel del self.rolloverFrame for panel in self.toonPanels + self.cogPanels: panel.cleanup() del self.toonPanels del self.cogPanels self.timer.destroy() del self.timer del self.toons def enter(self, event, parentFSMState, bldg = 0, creditMultiplier = 1, tutorialFlag = 0): self.parentFSMState = parentFSMState self.parentFSMState.addChild(self.fsm) if not self.isLoaded: self.load() self.battleEvent = event self.fsm.enterInitialState() base.localAvatar.laffMeter.start() self.numToons = 1 self.numCogs = 1 self.toons = [base.localAvatar.doId] self.toonPanels[0].setLaffMeter(base.localAvatar) self.bldg = bldg self.creditLevel = None self.creditMultiplier = creditMultiplier self.tutorialFlag = tutorialFlag base.localAvatar.inventory.setBattleCreditMultiplier(self.creditMultiplier) base.localAvatar.inventory.setActivateMode('battle', heal=0, bldg=bldg, tutorialFlag=tutorialFlag) self.SOSPanel.bldg = bldg def exit(self): base.localAvatar.laffMeter.stop() self.parentFSMState.removeChild(self.fsm) del self.parentFSMState base.localAvatar.inventory.setBattleCreditMultiplier(1) def load(self): if self.isLoaded: return self.attackPanel.load() self.waitPanel.load() self.chooseCogPanel.load() self.chooseToonPanel.load() self.SOSPanel.load() if hasattr(base, 'wantPets') and base.wantPets: self.SOSPetSearchPanel.load() self.SOSPetInfoPanel.load() self.isLoaded = 1 def unload(self): if not self.isLoaded: return self.attackPanel.unload() self.waitPanel.unload() self.chooseCogPanel.unload() self.chooseToonPanel.unload() self.FireCogPanel.unload() self.SOSPanel.unload() if hasattr(base, 'wantPets') and base.wantPets: self.SOSPetSearchPanel.unload() self.SOSPetInfoPanel.unload() self.isLoaded = 0 def setState(self, state): if hasattr(self, 'fsm'): self.fsm.request(state) def updateTimer(self, time): self.time = time self.timer.setTime(time) return None def showRolloverFrame(self, parent, scale, textPos, color, pos, text, extra=None): self.rolloverFrame['geom_scale'] = scale self.rolloverFrame['text_pos'] = textPos self.rolloverFrame['geom_color'] = color self.rolloverFrame.setPos(pos) self.rolloverFrame.reparentTo(parent) self.rolloverFrame.show() self.rolloverFrame['text'] = text def hideRolloverFrame(self, extra=None): self.rolloverFrame.hide() def isAttackDangerous(self, hp): for panel in self.toonPanels: if panel.hasAvatar() and panel.avatar.getHp() <= hp: return True def __enterPanels(self, num, localNum): self.notify.debug('enterPanels() num: %d localNum: %d' % (num, localNum)) for toonPanel in self.toonPanels: toonPanel.hide() toonPanel.setPos(0, 0, -0.9) self.positionPanels(num, self.toonPanels) def __enterCogPanels(self, num): for cogPanel in self.cogPanels: cogPanel.hide() cogPanel.updateHealthBar() cogPanel.updateRolloverBind() cogPanel.setPos(0, 0, 0.62) self.positionPanels(num, self.cogPanels) def positionPanels(self, num, panels): pos = self.evenPos if num % 2 == 0 else self.oddPos for i, panel in enumerate(panels): if num > i: panel.setX(pos[i if num >= 3 else i + 1]) panel.show() def updateChosenAttacks(self, battleIndices, tracks, levels, targets): self.notify.debug('updateChosenAttacks bi=%s tracks=%s levels=%s targets=%s' % (battleIndices, tracks, levels, targets)) for i in xrange(4): if battleIndices[i] == -1: pass else: if tracks[i] == BattleBase.NO_ATTACK: numTargets = 0 target = -2 elif tracks[i] == BattleBase.PASS_ATTACK: numTargets = 0 target = -2 elif tracks[i] == BattleBase.NPCSOS: numTargets = 0 target = targets[i] elif tracks[i] == BattleBase.SOS or tracks[i] == BattleBase.PETSOS: numTargets = 0 target = -2 elif tracks[i] == HEAL_TRACK: numTargets = self.numToons if self.__isGroupHeal(levels[i]): target = -2 else: target = targets[i] else: numTargets = self.numCogs if self.__isGroupAttack(tracks[i], levels[i]): target = -1 else: target = targets[i] if target == -1: numTargets = None self.toonPanels[battleIndices[i]].setValues(battleIndices[i], tracks[i], levels[i], numTargets, target, self.localNum) def chooseDefaultTarget(self): if self.track > -1: response = {} response['mode'] = 'Attack' response['track'] = self.track response['level'] = self.level response['target'] = self.target messenger.send(self.battleEvent, [response]) return 1 return 0 def updateLaffMeter(self, toonNum, hp): self.toonPanels[toonNum].updateLaffMeter(hp) def enterOff(self): if self.isLoaded: for toonPanel in self.toonPanels: toonPanel.hide() for cogPanel in self.cogPanels: cogPanel.hide() self.toonAttacks = [(-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0)] self.target = 0 if hasattr(self, 'timer'): self.timer.hide() return None def exitOff(self): if self.isLoaded: self.__enterPanels(self.numToons, self.localNum) if settings['cogInterface']: self.__enterCogPanels(self.numCogs) self.timer.show() self.track = -1 self.level = -1 self.target = 0 return None def enterAttack(self): self.attackPanel.enter() self.accept(self.attackPanelDoneEvent, self.__handleAttackPanelDone) return None def exitAttack(self): self.ignore(self.attackPanelDoneEvent) self.attackPanel.exit() return None def __handleAttackPanelDone(self, doneStatus): self.notify.debug('doneStatus: %s' % doneStatus) mode = doneStatus['mode'] if mode == 'Inventory': self.track = doneStatus['track'] self.level = doneStatus['level'] self.toonPanels[self.localNum].setValues(self.localNum, self.track, self.level) if self.track == HEAL_TRACK: if self.__isGroupHeal(self.level): response = {} response['mode'] = 'Attack' response['track'] = self.track response['level'] = self.level response['target'] = self.target messenger.send(self.battleEvent, [response]) self.fsm.request('AttackWait') elif self.numToons == 3 or self.numToons == 4: self.fsm.request('ChooseToon') elif self.numToons == 2: response = {} response['mode'] = 'Attack' response['track'] = self.track response['level'] = self.level if self.localNum == 0: response['target'] = 1 elif self.localNum == 1: response['target'] = 0 else: self.notify.error('Bad localNum value: %s' % self.localNum) messenger.send(self.battleEvent, [response]) self.fsm.request('AttackWait') else: self.notify.error('Heal was chosen when number of toons is %s' % self.numToons) elif self.__isCogChoiceNecessary(): self.notify.debug('choice needed') self.fsm.request('ChooseCog') response = {} response['mode'] = 'Attack' response['track'] = self.track response['level'] = self.level response['target'] = -1 messenger.send(self.battleEvent, [response]) else: self.notify.debug('no choice needed') self.fsm.request('AttackWait') response = {} response['mode'] = 'Attack' response['track'] = self.track response['level'] = self.level response['target'] = 0 messenger.send(self.battleEvent, [response]) elif mode == 'Run': self.fsm.request('Run') elif mode == 'SOS': self.fsm.request('SOS') elif mode == 'Fire': self.fsm.request('Fire') elif mode == 'Pass': response = {} response['mode'] = 'Pass' response['id'] = -1 messenger.send(self.battleEvent, [response]) self.fsm.request('AttackWait') else: self.notify.warning('unknown mode: %s' % mode) def checkHealTrapLure(self): self.notify.debug('numToons: %s, numCogs: %s, lured: %s, trapped: %s' % (self.numToons, self.numCogs, self.luredIndices, self.trappedIndices)) if len(PythonUtil.union(self.trappedIndices, self.luredIndices)) == self.numCogs: canTrap = 0 else: canTrap = 1 if len(self.luredIndices) == self.numCogs: canLure = 0 canTrap = 0 else: canLure = 1 if self.numToons == 1: canHeal = 0 else: canHeal = 1 return (canHeal, canTrap, canLure) def adjustCogsAndToons(self, cogs, luredIndices, trappedIndices, toons): numCogs = len(cogs) self.notify.debug('adjustCogsAndToons() numCogs: %s self.numCogs: %s' % (numCogs, self.numCogs)) self.notify.debug('adjustCogsAndToons() luredIndices: %s self.luredIndices: %s' % (luredIndices, self.luredIndices)) self.notify.debug('adjustCogsAndToons() trappedIndices: %s self.trappedIndices: %s' % (trappedIndices, self.trappedIndices)) toonIds = map(lambda toon: toon.doId, toons) self.notify.debug('adjustCogsAndToons() toonIds: %s self.toons: %s' % (toonIds, self.toons)) maxSuitLevel = 0 for cog in cogs: maxSuitLevel = max(maxSuitLevel, cog.getActualLevel()) creditLevel = maxSuitLevel resetActivateMode = numCogs != self.numCogs or creditLevel != self.creditLevel or luredIndices != self.luredIndices or trappedIndices != self.trappedIndices or toonIds != self.toons self.notify.debug('adjustCogsAndToons() resetActivateMode: %s' % resetActivateMode) self.numCogs = numCogs self.creditLevel = creditLevel self.luredIndices = luredIndices self.trappedIndices = trappedIndices self.toons = toonIds self.numToons = len(toons) self.localNum = toons.index(base.localAvatar) currStateName = self.fsm.getCurrentState().getName() if resetActivateMode: self.__enterPanels(self.numToons, self.localNum) for i in xrange(len(toons)): self.toonPanels[i].setLaffMeter(toons[i]) if settings['cogInterface']: self.__enterCogPanels(self.numCogs) for i in xrange(len(cogs)): self.cogPanels[i].setSuit(cogs[i]) if currStateName == 'ChooseCog': self.chooseCogPanel.adjustCogs(self.numCogs, self.luredIndices, self.trappedIndices, self.track) elif currStateName == 'ChooseToon': self.chooseToonPanel.adjustToons(self.numToons, self.localNum) canHeal, canTrap, canLure = self.checkHealTrapLure() base.localAvatar.inventory.setBattleCreditMultiplier(self.creditMultiplier) base.localAvatar.inventory.setActivateMode('battle', heal=canHeal, trap=canTrap, lure=canLure, bldg=self.bldg, creditLevel=self.creditLevel, tutorialFlag=self.tutorialFlag) def enterChooseCog(self): self.cog = 0 self.chooseCogPanel.enter(self.numCogs, luredIndices=self.luredIndices, trappedIndices=self.trappedIndices, track=self.track) self.accept(self.chooseCogPanelDoneEvent, self.__handleChooseCogPanelDone) return None def exitChooseCog(self): self.ignore(self.chooseCogPanelDoneEvent) self.chooseCogPanel.exit() return None def __handleChooseCogPanelDone(self, doneStatus): mode = doneStatus['mode'] if mode == 'Back': self.fsm.request('Attack') elif mode == 'Avatar': self.cog = doneStatus['avatar'] self.target = self.cog self.fsm.request('AttackWait') response = {} response['mode'] = 'Attack' response['track'] = self.track response['level'] = self.level response['target'] = self.cog messenger.send(self.battleEvent, [response]) else: self.notify.warning('unknown mode: %s' % mode) def enterAttackWait(self, chosenToon = -1): self.accept(self.waitPanelDoneEvent, self.__handleAttackWaitBack) self.waitPanel.enter(self.numToons) def exitAttackWait(self): self.waitPanel.exit() self.ignore(self.waitPanelDoneEvent) def __handleAttackWaitBack(self, doneStatus): mode = doneStatus['mode'] if mode == 'Back': if self.track == HEAL_TRACK: self.fsm.request('Attack') elif self.track == BattleBase.NO_ATTACK: self.fsm.request('Attack') elif self.__isCogChoiceNecessary(): self.fsm.request('ChooseCog') else: self.fsm.request('Attack') response = {} response['mode'] = 'UnAttack' messenger.send(self.battleEvent, [response]) else: self.notify.error('unknown mode: %s' % mode) def enterChooseToon(self): self.toon = 0 self.chooseToonPanel.enter(self.numToons, localNum=self.localNum) self.accept(self.chooseToonPanelDoneEvent, self.__handleChooseToonPanelDone) return None def exitChooseToon(self): self.ignore(self.chooseToonPanelDoneEvent) self.chooseToonPanel.exit() return None def __handleChooseToonPanelDone(self, doneStatus): mode = doneStatus['mode'] if mode == 'Back': self.fsm.request('Attack') elif mode == 'Avatar': self.toon = doneStatus['avatar'] self.target = self.toon self.fsm.request('AttackWait', [self.toon]) response = {} response['mode'] = 'Attack' response['track'] = self.track response['level'] = self.level response['target'] = self.toon messenger.send(self.battleEvent, [response]) else: self.notify.warning('unknown mode: %s' % mode) def enterRun(self): self.runPanel.show() def exitRun(self): self.runPanel.hide() def __handleRunPanelDone(self, doneStatus): if doneStatus == DGG.DIALOG_OK: response = {} response['mode'] = 'Run' messenger.send(self.battleEvent, [response]) else: self.fsm.request('Attack') def enterFire(self): canHeal, canTrap, canLure = self.checkHealTrapLure() self.FireCogPanel.enter(self.numCogs, luredIndices=self.luredIndices, trappedIndices=self.trappedIndices, track=self.track) self.accept(self.fireCogPanelDoneEvent, self.__handleCogFireDone) return None def exitFire(self): self.ignore(self.fireCogPanelDoneEvent) self.FireCogPanel.exit() return None def __handleCogFireDone(self, doneStatus): mode = doneStatus['mode'] if mode == 'Back': self.fsm.request('Attack') elif mode == 'Avatar': self.cog = doneStatus['avatar'] self.target = self.cog self.fsm.request('AttackWait') response = {} response['mode'] = 'Fire' response['target'] = self.cog messenger.send(self.battleEvent, [response]) else: self.notify.warning('unknown mode: %s' % mode) def enterSOS(self): canHeal, canTrap, canLure = self.checkHealTrapLure() self.SOSPanel.enter(canLure, canTrap) self.accept(self.SOSPanelDoneEvent, self.__handleSOSPanelDone) return None def exitSOS(self): self.ignore(self.SOSPanelDoneEvent) self.SOSPanel.exit() return None def __handleSOSPanelDone(self, doneStatus): mode = doneStatus['mode'] if mode == 'Friend': doId = doneStatus['friend'] response = {} response['mode'] = 'SOS' response['id'] = doId messenger.send(self.battleEvent, [response]) self.fsm.request('AttackWait') elif mode == 'Pet': self.petId = doneStatus['petId'] self.petName = doneStatus['petName'] self.fsm.request('SOSPetSearch') elif mode == 'NPCFriend': doId = doneStatus['friend'] response = {} response['mode'] = 'NPCSOS' response['id'] = doId messenger.send(self.battleEvent, [response]) self.fsm.request('AttackWait') elif mode == 'Back': self.fsm.request('Attack') def enterSOSPetSearch(self): response = {} response['mode'] = 'PETSOSINFO' response['id'] = self.petId self.SOSPetSearchPanel.enter(self.petId, self.petName) self.proxyGenerateMessage = 'petProxy-%d-generated' % self.petId self.accept(self.proxyGenerateMessage, self.__handleProxyGenerated) self.accept(self.SOSPetSearchPanelDoneEvent, self.__handleSOSPetSearchPanelDone) messenger.send(self.battleEvent, [response]) return None def exitSOSPetSearch(self): self.ignore(self.proxyGenerateMessage) self.ignore(self.SOSPetSearchPanelDoneEvent) self.SOSPetSearchPanel.exit() return None def __handleSOSPetSearchPanelDone(self, doneStatus): mode = doneStatus['mode'] if mode == 'Back': self.fsm.request('SOS') else: self.notify.error('invalid mode in handleSOSPetSearchPanelDone') def __handleProxyGenerated(self): self.fsm.request('SOSPetInfo') def enterSOSPetInfo(self): self.SOSPetInfoPanel.enter(self.petId) self.accept(self.SOSPetInfoPanelDoneEvent, self.__handleSOSPetInfoPanelDone) return None def exitSOSPetInfo(self): self.ignore(self.SOSPetInfoPanelDoneEvent) self.SOSPetInfoPanel.exit() return None def __handleSOSPetInfoPanelDone(self, doneStatus): mode = doneStatus['mode'] if mode == 'OK': response = {} response['mode'] = 'PETSOS' response['id'] = self.petId response['trickId'] = doneStatus['trickId'] messenger.send(self.battleEvent, [response]) self.fsm.request('AttackWait') bboard.post(PetConstants.OurPetsMoodChangedKey, True) elif mode == 'Back': self.fsm.request('SOS') def __isCogChoiceNecessary(self): if self.numCogs > 1 and not self.__isGroupAttack(self.track, self.level): return 1 else: return 0 def __isGroupAttack(self, trackNum, levelNum): retval = BattleBase.attackAffectsGroup(trackNum, levelNum) return retval def __isGroupHeal(self, levelNum): retval = BattleBase.attackAffectsGroup(HEAL_TRACK, levelNum) return retval