oldschool-toontown/toontown/cogdominium/DistributedCogdoInteriorAI.py

940 lines
33 KiB
Python
Raw Normal View History

2019-11-02 17:27:54 -05:00
import copy
import random
from direct.directnotify import DirectNotifyGlobal
from direct.distributed import DistributedObjectAI
from direct.distributed.ClockDelta import *
from direct.fsm import ClassicFSM, State
from direct.task import Timer
from toontown.toon import NPCToons
from otp.ai.AIBaseGlobal import *
from toontown.ai import ToonBarrier
from toontown.battle import BattleBase
from toontown.cogdominium import DistributedCogdoBattleBldgAI
from toontown.building.ElevatorConstants import *
from toontown.suit.SuitDNA import SuitDNA
from toontown.toonbase.ToontownBattleGlobals import *
from toontown.hood import ZoneUtil
from toontown.minigame.MinigameGlobals import SafeZones
from toontown.toon import NPCToons
from .DistributedCogdoElevatorIntAI import DistributedCogdoElevatorIntAI
2019-11-02 17:27:54 -05:00
from toontown.cogdominium import CogdoBarrelRoomConsts
from toontown.cogdominium import CogdoBarrelRoomAI
from .DistCogdoBoardroomGameAI import DistCogdoBoardroomGameAI
2019-11-02 17:27:54 -05:00
from toontown.cogdominium.DistCogdoCraneGameAI import DistCogdoCraneGameAI
from toontown.cogdominium.DistCogdoMazeGameAI import DistCogdoMazeGameAI
from toontown.cogdominium.DistCogdoFlyingGameAI import DistCogdoFlyingGameAI
from toontown.cogdominium import CogdoGameConsts
CogdoGames = {
'boardroom': DistCogdoBoardroomGameAI,
'crane': DistCogdoCraneGameAI,
'maze': DistCogdoMazeGameAI,
'flying': DistCogdoFlyingGameAI}
IntGames = set([
'boardroom',
'crane',
'flying',
'defense'])
simbase.forcedCogdoGame = config.GetString('cogdo-game', '')
GameRequests = {}
class DistributedCogdoInteriorAI(DistributedObjectAI.DistributedObjectAI):
def __init__(self, air, elevator):
self.air = air
DistributedObjectAI.DistributedObjectAI.__init__(self, air)
(self.extZoneId, self.zoneId) = elevator.bldg.getExteriorAndInteriorZoneId()
self._numFloors = elevator.bldg.planner.numFloors
self.layout = elevator.bldg._cogdoLayout
self.avatarExitEvents = []
self.toons = []
self.toonSkillPtsGained = {}
self.toonExp = {}
self.toonOrigQuests = {}
self.toonItems = {}
self.toonOrigMerits = {}
self.toonMerits = {}
self.toonParts = {}
self.helpfulToons = []
self.shopOwnerNpcId = 0
npcDesc = NPCToons.zone2NpcDict.get(self.zoneId)
if npcDesc:
self.shopOwnerNpcId = npcDesc[0]
if not self.shopOwnerNpcId:
self.notify.warning('No npcs found for current cogdo building')
self.currentFloor = 0
self.bldg = elevator.bldg
self.elevator = elevator
self._game = None
self._CogdoGameRepeat = config.GetBool('cogdo-game-repeat', 0)
self.suits = []
self.activeSuits = []
self.reserveSuits = []
self.joinedReserves = []
self.suitsKilled = []
self.suitsKilledPerFloor = []
self.battle = None
self.timer = Timer.Timer()
self._wantBarrelRoom = config.GetBool('cogdo-want-barrel-room', 0)
self.barrelRoom = None
self.responses = {}
self.ignoreResponses = 0
self.ignoreElevatorDone = 0
self.ignoreReserveJoinDone = 0
self.toonIds = copy.copy(elevator.seats)
for toonId in self.toonIds:
if toonId != None:
self.__addToon(toonId)
self.savedByMap = {}
self.fsm = ClassicFSM.ClassicFSM('DistributedCogdoInteriorAI', [
State.State('WaitForAllToonsInside', self.enterWaitForAllToonsInside, self.exitWaitForAllToonsInside, [
'Elevator']),
State.State('Elevator', self.enterElevator, self.exitElevator, [
'Game']),
State.State('Game', self.enterGame, self.exitGame, [
'Resting',
'Failed',
'BattleIntro',
'Off']),
State.State('BarrelRoomIntro', self.enterBarrelRoomIntro, self.exitBarrelRoomIntro, [
'CollectBarrels',
'Off']),
State.State('CollectBarrels', self.enterCollectBarrels, self.exitCollectBarrels, [
'BarrelRoomReward',
'Off']),
State.State('BarrelRoomReward', self.enterBarrelRoomReward, self.exitBarrelRoomReward, [
'Battle',
'ReservesJoining',
'BattleIntro',
'Off']),
State.State('BattleIntro', self.enterBattleIntro, self.exitBattleIntro, [
'Battle',
'ReservesJoining',
'Off']),
State.State('Battle', self.enterBattle, self.exitBattle, [
'ReservesJoining',
'BattleDone',
'Off']),
State.State('ReservesJoining', self.enterReservesJoining, self.exitReservesJoining, [
'Battle',
'Off']),
State.State('BattleDone', self.enterBattleDone, self.exitBattleDone, [
'Resting',
'Reward',
'Off']),
State.State('Resting', self.enterResting, self.exitResting, [
'Elevator',
'Off']),
State.State('Reward', self.enterReward, self.exitReward, [
'Off']),
State.State('Failed', self.enterFailed, self.exitFailed, [
'Off']),
State.State('Off', self.enterOff, self.exitOff, [
'WaitForAllToonsInside'])], 'Off', 'Off', onUndefTransition = ClassicFSM.ClassicFSM.ALLOW)
self.fsm.enterInitialState()
safeZone = ZoneUtil.getCanonicalHoodId(self.extZoneId)
difficulty = SafeZones.index(safeZone)
self.SOSCard = self.chooseSOSCard(difficulty)
def generateWithRequired(self, zoneId):
self._disCleanupTask = None
self._sadCleanupTask = None
DistributedObjectAI.DistributedObjectAI.generateWithRequired(self, zoneId)
def delete(self):
self.ignoreAll()
self.toons = []
self.toonIds = []
self.fsm.requestFinalState()
del self.fsm
del self.bldg
del self.elevator
self.timer.stop()
del self.timer
self._cogdoLayout = None
self.__cleanupFloorBattle()
if self.barrelRoom:
self.barrelRoom.destroy()
self.barrelRoom = None
taskName = self.taskName('deleteInterior')
taskMgr.remove(taskName)
if self._disCleanupTask:
taskMgr.remove(self._disCleanupTask)
if self._sadCleanupTask:
taskMgr.remove(self._sadCleanupTask)
DistributedObjectAI.DistributedObjectAI.delete(self)
def requestDelete(self):
if self._game:
self._game.requestDelete()
DistributedObjectAI.DistributedObjectAI.requestDelete(self)
def getShopOwnerNpcId(self):
return self.shopOwnerNpcId
def getSOSNpcId(self):
return self.SOSCard
def __handleUnexpectedExit(self, toonId):
self.notify.warning('toon: %d exited unexpectedly' % toonId)
self.__removeToon(toonId)
if self._game:
self._game.handleToonDisconnected(toonId)
if len(self.toons) == 0:
self.timer.stop()
if self.fsm.getCurrentState().getName() == 'Resting':
pass
elif self.battle == None:
self.fsm.requestFinalState()
self._disCleanupTask = taskMgr.doMethodLater(20, self._cleanupAfterLastToonWentDis, self.uniqueName('discleanup'))
def _cleanupAfterLastToonWentDis(self, task):
self._disCleanupTask = None
self.bldg.deleteCogdoInterior()
return task.done
def _handleToonWentSad(self, toonId):
self.notify.info('toon: %d went sad' % toonId)
self.__removeToon(toonId)
toon = self.air.getDo(toonId)
if toon:
self.ignore(toon.getGoneSadMessage())
if self._game:
self._game.handleToonWentSad(toonId)
if len(self.toons) == 0:
self.timer.stop()
if self.fsm.getCurrentState().getName() == 'Resting':
pass
elif self.battle == None:
self._sadCleanupTask = taskMgr.doMethodLater(20, self._cleanupAfterLastToonWentSad, self.uniqueName('sadcleanup'))
def _cleanupAfterLastToonWentSad(self, task):
self._sadCleanupTask = None
self.bldg.deleteCogdoInterior()
return task.done
def __addToon(self, toonId):
if toonId not in self.air.doId2do:
2019-11-02 17:27:54 -05:00
self.notify.warning('addToon() - no toon for doId: %d' % toonId)
return
event = self.air.getAvatarExitEvent(toonId)
self.avatarExitEvents.append(event)
self.accept(event, self.__handleUnexpectedExit, extraArgs = [
toonId])
self.toons.append(toonId)
self.responses[toonId] = 0
def __removeToon(self, toonId):
if self.toons.count(toonId):
self.toons.remove(toonId)
if self.toonIds.count(toonId):
self.toonIds[self.toonIds.index(toonId)] = None
if toonId in self.responses:
2019-11-02 17:27:54 -05:00
del self.responses[toonId]
event = self.air.getAvatarExitEvent(toonId)
if self.avatarExitEvents.count(event):
self.avatarExitEvents.remove(event)
self.ignore(event)
def __resetResponses(self):
self.responses = {}
for toon in self.toons:
self.responses[toon] = 0
self.ignoreResponses = 0
def __allToonsResponded(self):
for toon in self.toons:
if self.responses[toon] == 0:
return 0
self.ignoreResponses = 1
return 1
def getZoneId(self):
return self.zoneId
def getExtZoneId(self):
return self.extZoneId
def getDistBldgDoId(self):
return self.bldg.getDoId()
def getNumFloors(self):
return self._numFloors
def d_setToons(self):
self.sendUpdate('setToons', self.getToons())
def getToons(self):
sendIds = []
for toonId in self.toonIds:
if toonId == None:
sendIds.append(0)
else:
sendIds.append(toonId)
return [
sendIds,
0]
def getDroneCogDNA(self):
dna = SuitDNA()
dna.newSuitRandom(level = 2)
return dna
def d_setSuits(self):
self.sendUpdate('setSuits', self.getSuits())
def getSuits(self):
suitIds = []
for suit in self.activeSuits:
suitIds.append(suit.doId)
reserveIds = []
values = []
for info in self.reserveSuits:
reserveIds.append(info[0].doId)
values.append(info[1])
return [
suitIds,
reserveIds,
values]
def b_setState(self, state):
self.d_setState(state)
self.setState(state)
def d_setState(self, state):
stime = globalClock.getRealTime() + BattleBase.SERVER_BUFFER_TIME
self.sendUpdate('setState', [
state,
globalClockDelta.localToNetworkTime(stime)])
def setState(self, state):
self.fsm.request(state)
def getState(self):
return [
self.fsm.getCurrentState().getName(),
globalClockDelta.getRealNetworkTime()]
def setAvatarJoined(self):
avId = self.air.getAvatarIdFromSender()
if self.toons.count(avId) == 0:
self.air.writeServerEvent('suspicious', avId, 'DistributedCogdoInteriorAI.setAvatarJoined from toon not in %s.' % self.toons)
self.notify.warning('setAvatarJoined() - av: %d not in list' % avId)
return
if self.fsm.getCurrentState().getName() != 'WaitForAllToonsInside':
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.setAvatarJoined: not in wait state')
return
avatar = self.air.doId2do.get(avId)
if avatar == None:
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.setAvatarJoined: avatar not present')
return
else:
self.savedByMap[avId] = (avatar.getName(), avatar.dna.asTuple())
if avId not in self.responses:
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.setAvatarJoined: avId not in responses')
self.notify.warning('CogdoInteriorAI.setAvatarJoined: avId not in responses')
return
if self.responses[avId] > 0:
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.setAvatarJoined: av already responded')
return
self.responses[avId] += 1
if self.__allToonsResponded():
self.fsm.request('Elevator')
def elevatorDone(self):
toonId = self.air.getAvatarIdFromSender()
if self.ignoreResponses == 1:
return
elif self.toons.count(toonId) == 0:
self.air.writeServerEvent('suspicious', toonId, 'CogdoInteriorAI.elevatorDone: toon not in participant list')
self.notify.warning('elevatorDone() - toon not in toon list: %d' % toonId)
return
if self.fsm.getCurrentState().getName() != 'Elevator':
self.air.writeServerEvent('suspicious', toonId, 'CogdoInteriorAI.elevatorDone: not in Elevator state')
return
if toonId not in self.responses:
self.air.writeServerEvent('suspicious', toonId, 'CogdoInteriorAI.elevatorDone: toon not in responses')
self.notify.warning('CogdoInteriorAI.elevatorDone: avId not in responses')
return
self.responses[toonId] += 1
if self.__allToonsResponded() and self.ignoreElevatorDone == 0:
self.b_setState('Game')
def reserveJoinDone(self):
toonId = self.air.getAvatarIdFromSender()
if self.ignoreResponses == 1:
return
elif self.toons.count(toonId) == 0:
self.air.writeServerEvent('suspicious', toonId, 'CogdoInteriorAI.reserveJoinDone: toon not in participant list')
self.notify.warning('reserveJoinDone() - toon not in list: %d' % toonId)
return
if self.fsm.getCurrentState().getName() != 'ReservesJoining':
self.air.writeServerEvent('suspicious', toonId, 'CogdoInteriorAI.reserveJoinDone: not in ReservesJoining state')
return
if toonId not in self.responses:
self.air.writeServerEvent('suspicious', toonId, 'CogdoInteriorAI.reserveJoinDone: toon not in responses')
self.notify.warning('CogdoInteriorAI.reserveJoinDone: avId not in responses')
return
self.responses[toonId] += 1
if self.__allToonsResponded() and self.ignoreReserveJoinDone == 0:
self.b_setState('Battle')
def isBossFloor(self, floorNum):
if self.layout.hasBossBattle():
if self.layout.getBossBattleFloor() == floorNum:
return True
return False
def isTopFloor(self, floorNum):
return self.layout.getNumFloors() - 1 == floorNum
def enterOff(self):
return None
def exitOff(self):
return None
def enterWaitForAllToonsInside(self):
self.__resetResponses()
return None
def exitWaitForAllToonsInside(self):
self.__resetResponses()
return None
def enterElevator(self):
if self.isBossFloor(self.currentFloor):
self._populateFloorSuits()
else:
self.d_setToons()
self.__resetResponses()
if self._wantBarrelRoom:
if self.barrelRoom:
self.barrelRoom.reset()
else:
self.barrelRoom = CogdoBarrelRoomAI.CogdoBarrelRoomAI(self)
self._game = self._createGame()
if self._game:
self._game.makeVisible()
self.d_setState('Elevator')
self.timer.startCallback(BattleBase.ELEVATOR_T + ElevatorData[ELEVATOR_NORMAL]['openTime'] + BattleBase.SERVER_BUFFER_TIME, self.__serverElevatorDone)
return None
def _createGame(self):
game = None
if not self.isBossFloor(self.currentFloor):
for toonId in self.toonIds:
if toonId:
toon = self.air.getDo(toonId)
if toon:
self.accept(toon.getGoneSadMessage(), Functor(self._handleToonWentSad, toonId))
forcedGame = simbase.forcedCogdoGame
diff = None
pgId = None
for toonId in self.toonIds:
if toonId:
if toonId in GameRequests:
(forcedGame, keep, diff, pgId) = GameRequests[toonId]
if not keep:
GameRequests.pop(toonId)
if forcedGame:
gameCtor = CogdoGames[forcedGame]
else:
name = None
while name is None or name in IntGames:
name = random.choice(list(CogdoGames.keys()))
2019-11-02 17:27:54 -05:00
gameCtor = CogdoGames[name]
game = gameCtor(self.air, self)
game.setExteriorZone(self.extZoneId)
game.setDifficultyOverrides(diff, pgId)
game.generateWithRequired(self.zoneId)
return game
def __serverElevatorDone(self):
self.ignoreElevatorDone = 1
self.b_setState('Game')
def exitElevator(self):
self.timer.stop()
self.__resetResponses()
return None
def enterGame(self):
self.notify.info('Entering Maze Game')
self._gameScore = None
self._rewardedLaff = {}
self._penaltyLaff = {}
self.d_setState('Game')
self.elevator.d_setFloor(self.currentFloor)
if self._game:
self._game.start()
else:
self._gameDone()
def _populateFloorSuits(self):
suitHandles = self.bldg.planner.genFloorSuits(self.currentFloor)
self.suits = suitHandles['activeSuits']
self.activeSuits = []
for suit in self.suits:
self.activeSuits.append(suit)
self.reserveSuits = suitHandles['reserveSuits']
self.d_setToons()
self.d_setSuits()
def _setGameScore(self, score):
self._gameScore = score
def getGameScore(self):
return self._gameScore
def _gameDone(self):
self.__calcLaff()
for (toonId, reward) in self._rewardedLaff.items():
2019-11-02 17:27:54 -05:00
if reward:
av = self.air.doId2do.get(toonId)
av.toonUp(reward)
for (toonId, penalty) in self._penaltyLaff.items():
2019-11-02 17:27:54 -05:00
if penalty:
av = self.air.doId2do.get(toonId)
if config.GetBool('want-cogdo-maze-no-sad', 1):
avHp = av.getHp()
if avHp < 1:
avHp = 1
if penalty >= avHp:
penalty = avHp - 1
if penalty:
av.takeDamage(penalty, quietly = 0)
if self._game and self._game.wasEnded():
self.b_setState('Resting')
elif self._game and self._game.isDoorOpen():
self.b_setState('Resting')
elif self._game and not self._game.isDoorOpen():
self.b_setState('Failed')
else:
self.b_setState('BattleIntro')
def exitGame(self):
self.sendUpdate('setSOSNpcId', [
self.SOSCard])
self.sendUpdate('setFOType', [
ord(self.bldg.track)])
def __calcLaff(self):
self.notify.debug('__calcLaff()')
self._rewardedLaff = {}
self._penaltyLaff = {}
if self._game:
score = self.getGameScore()
if score:
maxToAward = self._game.getDifficulty() * CogdoGameConsts.LaffRewardRange + CogdoGameConsts.LaffRewardMin
reward = score * maxToAward
for toonId in self.toons:
if self._game.isToonInDoor(toonId):
self._rewardedLaff[toonId] = reward
if self._rewardedLaff:
self.air.writeServerEvent('CogdoLaffReward', list(self._rewardedLaff.keys()), 'Awarded %s Laff for difficulty %s and score %s' % (reward, self._game.getDifficulty(), score))
2019-11-02 17:27:54 -05:00
penalty = self._game.getDifficulty() * CogdoGameConsts.LaffPenalty
for toonId in self.toons:
if not self._game.isToonInDoor(toonId):
self._penaltyLaff[toonId] = penalty
if self._penaltyLaff:
self.air.writeServerEvent('CogdoLaffPenalty', list(self._penaltyLaff.keys()), 'Penalized %s Laff for difficulty %s (did not reach exit)' % (penalty, self._game.getDifficulty()))
2019-11-02 17:27:54 -05:00
def toonBarrelRoomIntroDone(self):
avId = self.air.getAvatarIdFromSender()
if self.fsm.getCurrentState().getName() != 'BarrelRoomIntro':
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.toonBarrelRoomIntroDone: not in BarrelRoomIntro state')
return
if avId not in self.responses:
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.toonBarrelRoomIntroDone: unknown avId')
return
if hasattr(self, 'brBarrier'):
self.brBarrier.clear(avId)
else:
self.notify.warning('toonBarrelRoomIntroDone from %s in invalid state' % avId)
def __brIntroDone(self, clearedAvIds = []):
self.b_setState('CollectBarrels')
def enterBarrelRoomIntro(self):
if not self._wantBarrelRoom:
pass
if self._wantBarrelRoom and not self.isBossFloor(self.currentFloor):
self.barrelRoom.setScore(1.0)
self.brBarrier = ToonBarrier.ToonBarrier('waitBrIntroDone', self.uniqueName('waitBrIntroDone'), self.toons, CogdoBarrelRoomConsts.BarrelRoomIntroTimeout, doneFunc = self.__brIntroDone)
else:
self.__brIntroDone()
def exitBarrelRoomIntro(self):
if hasattr(self, 'brBarrier'):
self.brBarrier.cleanup()
del self.brBarrier
def __endCollectBarrels(self):
if len(self.toons) > 0:
self.notify.info('%d toons in barrel room.' % len(self.toons))
self.b_setState('BarrelRoomReward')
else:
self.notify.warning('0 toons in barrel room.')
self.bldg.deleteCogdoInterior()
def toonLeftBarrelRoom(self):
avId = self.air.getAvatarIdFromSender()
self.notify.info('avId=%s left the barrel room via teleport' % avId)
if self.fsm.getCurrentState().getName() != 'CollectBarrels':
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.toonLeftBarrelRoom called outside of CollectBarrels state')
return
if avId not in self.responses:
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.toonLeftBarrelRoom: unknown avId')
return
self.__removeToon(avId)
self.notify.info('%d toon(s) remaining in barrel room.' % len(self.toons))
if len(self.toons) == 0:
self.notify.warning('0 toons in barrel room.')
self.bldg.deleteCogdoInterior()
def enterCollectBarrels(self):
if self._wantBarrelRoom and not self.isBossFloor(self.currentFloor):
self.acceptOnce(self.barrelRoom.collectionDoneEvent, self.__endCollectBarrels)
self.barrelRoom.activate()
else:
self.__endCollectBarrels()
def exitCollectBarrels(self):
if self.barrelRoom:
self.ignore(self.barrelRoom.collectionDoneEvent)
self.barrelRoom.deactivate()
def toonBarrelRoomRewardDone(self):
avId = self.air.getAvatarIdFromSender()
if self.fsm.getCurrentState().getName() != 'BarrelRoomReward':
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.toonBarrelRoomIntroDone: not in BarrelRoomReward state')
return
if avId not in self.responses:
self.air.writeServerEvent('suspicious', avId, 'CogdoInteriorAI.toonBarrelRoomRewardDone: unknown avId')
return
if hasattr(self, 'brBarrier'):
self.brBarrier.clear(avId)
else:
self.notify.warning('toonBarrelRoomRewardDone from %s in invalid state' % avId)
def __brRewardDone(self, clearedAvIds = []):
if len(self.toons) > 0:
if not self.isBossFloor(self.currentFloor):
self._populateFloorSuits()
self.b_setState('Battle')
else:
self.b_setState('BattleIntro')
else:
self.notify.warning('0 toons in barrel room.')
self.bldg.deleteCogdoInterior()
def enterBarrelRoomReward(self):
if self._wantBarrelRoom and not self.isBossFloor(self.currentFloor):
self.sendUpdate('setBarrelRoomReward', self.barrelRoom.results)
self.brBarrier = ToonBarrier.ToonBarrier('waitBrRewardDone', self.uniqueName('waitBrRewardDone'), self.toons, CogdoBarrelRoomConsts.RewardUiTime + 5.0, doneFunc = self.__brRewardDone)
else:
self.__brRewardDone()
def exitBarrelRoomReward(self):
if hasattr(self, 'brBarrier'):
self.brBarrier.cleanup()
del self.brBarrier
def __createFloorBattle(self):
if self.isBossFloor(self.currentFloor):
self.notify.info('%d toon(s) in boss battle' % len(self.toons))
bossBattle = 1
else:
self.notify.info('%d toon(s) in barrel battle' % len(self.toons))
bossBattle = 0
self.battle = DistributedCogdoBattleBldgAI.DistributedCogdoBattleBldgAI(self.air, self.zoneId, self.__handleRoundDone, self.__handleBattleDone, bossBattle = bossBattle)
self.battle.suitsKilled = self.suitsKilled
self.battle.suitsKilledPerFloor = self.suitsKilledPerFloor
self.battle.battleCalc.toonSkillPtsGained = self.toonSkillPtsGained
self.battle.toonExp = self.toonExp
self.battle.toonOrigQuests = self.toonOrigQuests
self.battle.toonItems = self.toonItems
self.battle.toonOrigMerits = self.toonOrigMerits
self.battle.toonMerits = self.toonMerits
self.battle.toonParts = self.toonParts
self.battle.helpfulToons = self.helpfulToons
self.battle.setInitialMembers(self.toons, self.suits)
self.battle.generateWithRequired(self.zoneId)
mult = getCreditMultiplier(self.currentFloor)
if self.air.suitInvasionManager.getInvading():
mult *= getInvasionMultiplier()
self.battle.battleCalc.setSkillCreditMultiplier(mult)
def __cleanupFloorBattle(self):
for suit in self.suits:
self.notify.debug('cleaning up floor suit: %d' % suit.doId)
if suit.isDeleted():
self.notify.debug('whoops, suit %d is deleted.' % suit.doId)
else:
suit.requestDelete()
self.suits = []
self.reserveSuits = []
self.activeSuits = []
if self.battle != None:
self.battle.requestDelete()
self.battle = None
def __handleRoundDone(self, toonIds, totalHp, deadSuits):
totalMaxHp = 0
for suit in self.suits:
totalMaxHp += suit.maxHP
for suit in deadSuits:
self.activeSuits.remove(suit)
if len(self.reserveSuits) > 0 and len(self.activeSuits) < 4:
self.joinedReserves = []
hpPercent = 100 - (totalHp / totalMaxHp) * 100.0
for info in self.reserveSuits:
if info[1] <= hpPercent and len(self.activeSuits) < 4:
self.suits.append(info[0])
self.activeSuits.append(info[0])
self.joinedReserves.append(info)
for info in self.joinedReserves:
self.reserveSuits.remove(info)
if len(self.joinedReserves) > 0:
self.fsm.request('ReservesJoining')
self.d_setSuits()
return
if len(self.activeSuits) == 0:
self.fsm.request('BattleDone', [
toonIds])
else:
self.battle.resume()
def __handleBattleDone(self, zoneId, toonIds):
if len(toonIds) == 0:
self.notify.info('handleBattleDone() - last toon gone')
taskName = self.taskName('deleteInterior')
taskMgr.doMethodLater(10, self.__doDeleteInterior, taskName)
elif self.isTopFloor(self.currentFloor):
self.setState('Reward')
else:
self.b_setState('Resting')
def __doDeleteInterior(self, task):
self.bldg.deleteCogdoInterior()
def enterBattleIntro(self):
timeLeft = 7.0
self._battleIntroTaskName = self.taskName('BattleIntro')
taskMgr.doMethodLater(timeLeft, self._battleIntroDone, self._battleIntroTaskName)
def _battleIntroDone(self, task):
self.b_setState('Battle')
return task.done
def exitBattleIntro(self):
taskMgr.remove(self._battleIntroTaskName)
self._battleIntroTaskName = None
def enterBattle(self):
if self.battle == None:
self.__createFloorBattle()
def exitBattle(self):
return None
def enterReservesJoining(self):
self.__resetResponses()
self.timer.startCallback(ElevatorData[ELEVATOR_NORMAL]['openTime'] + SUIT_HOLD_ELEVATOR_TIME + BattleBase.SERVER_BUFFER_TIME, self.__serverReserveJoinDone)
return None
def __serverReserveJoinDone(self):
self.ignoreReserveJoinDone = 1
self.b_setState('Battle')
def exitReservesJoining(self):
self.timer.stop()
self.__resetResponses()
for info in self.joinedReserves:
self.battle.suitRequestJoin(info[0])
self.battle.resume()
self.joinedReserves = []
return None
def enterBattleDone(self, toonIds):
if len(toonIds) != len(self.toons):
deadToons = []
for toon in self.toons:
if toonIds.count(toon) == 0:
deadToons.append(toon)
for toon in deadToons:
self.__removeToon(toon)
self.d_setToons()
if len(self.toons) == 0:
self.bldg.deleteCogdoInterior()
elif self.isTopFloor(self.currentFloor):
self.notify.info('%d Toon(s) beat the executive suite building' % len(self.toons))
self.battle.resume(self.currentFloor, topFloor = 1)
else:
self.battle.resume(self.currentFloor, topFloor = 0)
return None
def exitBattleDone(self):
self.__cleanupFloorBattle()
self.d_setSuits()
return None
def __handleEnterElevator(self):
self.fsm.request('Elevator')
def enterResting(self):
if self._game:
self._game.requestDelete()
self._game = None
for toonId in self.toonIds:
if toonId:
toon = self.air.getDo(toonId)
if toon:
self.ignore(toon.getGoneSadMessage())
self.handleAllAboard()
def handleAllAboard(self, seats = None):
if seats == None:
seats = copy.copy(self.toonIds)
if not hasattr(self, 'fsm'):
return None
numOfEmptySeats = seats.count(None)
if numOfEmptySeats == 4:
self.bldg.deleteCogdoInterior()
return None
elif numOfEmptySeats >= 0 and numOfEmptySeats <= 3:
pass
else:
self.error('Bad number of empty seats: %s' % numOfEmptySeats)
for toon in self.toons:
if seats.count(toon) == 0:
self.__removeToon(toon)
self.toonIds = copy.copy(seats)
self.toons = []
for toonId in self.toonIds:
if toonId != None:
self.toons.append(toonId)
self.d_setToons()
if not self._CogdoGameRepeat:
self.currentFloor += 1
self.fsm.request('Elevator')
def exitResting(self):
return None
def enterReward(self):
victors = self.toonIds[:]
savedBy = []
for v in victors:
tuple = self.savedByMap.get(v)
if tuple:
savedBy.append([
v,
tuple[0],
tuple[1]])
toon = self.air.doId2do.get(v)
if toon:
self.notify.info('Reward State: toonId:%d laff:%d/%d get ready for the victors to come outside' % (toon.doId, toon.hp, toon.maxHp))
if not toon.attemptAddNPCFriend(self.SOSCard, numCalls = 1):
self.notify.info('%s.unable to add NPCFriend %s to %s.' % (self.doId, self.SOSCard, v))
self.bldg.fsm.request('waitForVictorsFromCogdo', [
victors,
savedBy])
self.d_setState('Reward')
return None
def exitReward(self):
return None
def enterFailed(self):
victors = self.toonIds[:]
savedBy = []
anyVictors = victors.count(None) < 4
if anyVictors:
self.bldg.fsm.request('waitForVictorsFromCogdo', [
victors,
savedBy])
def exitFailed(self):
return None
def chooseSOSCard(self, difficulty):
if difficulty < 0 or difficulty > 5:
return None
if difficulty <= 1:
card = random.choice(NPCToons.npcFriendsMinMaxStars(0, 1))
elif difficulty <= 3:
card = random.choice(NPCToons.npcFriendsMinMaxStars(1, 1))
else:
card = random.choice(NPCToons.npcFriendsMinMaxStars(2, 2))
return card