text: from toontown.building import DistributedElevatorFSMAI
  from toontown.building.ElevatorConstants import *
  from direct.directnotify import DirectNotifyGlobal
  from direct.distributed.ClockDelta import *
  from direct.fsm.FSM import FSM
  from direct.task import Task
  from otp.ai.AIBase import *
  from toontown.toonbase import ToontownGlobals
  
  class DistributedElevatorFloorAI(DistributedElevatorFSMAI.DistributedElevatorFSMAI):
      notify = DirectNotifyGlobal.directNotify.newCategory('DistributedElevatorFloorAI')
      defaultTransitions = {
          'Off': [
              'Opening',
              'Closed'],
          'Opening': [
              'WaitEmpty',
              'WaitCountdown',
              'Opening',
              'Closing'],
          'WaitEmpty': [
              'WaitCountdown',
              'Closing',
              'WaitEmpty'],
          'WaitCountdown': [
              'WaitEmpty',
              'AllAboard',
              'Closing',
              'WaitCountdown'],
          'AllAboard': [
              'WaitEmpty',
              'Closing'],
          'Closing': [
              'Closed',
              'WaitEmpty',
              'Closing',
              'Opening'],
          'Closed': [
              'Opening'] }
      id = 0
  
      def __init__(self, air, lawOfficeId, bldg, avIds, markerId = None, numSeats = 4, antiShuffle = 0, minLaff = 0):
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.__init__(self, air, bldg, numSeats, antiShuffle = antiShuffle, minLaff = minLaff)
          FSM.__init__(self, 'ElevatorFloor_%s_FSM' % self.id)
          self.type = ELEVATOR_STAGE
          self.countdownTime = ElevatorData[self.type]['countdown']
          self.lawOfficeId = lawOfficeId
          self.anyToonsBailed = 0
          self.avIds = avIds
          self.isEntering = 0
          self.isLocked = 0
          self.setLocked(0)
          self.wantState = None
          self.latchRoom = None
          self.setLatch(markerId)
          self.zoneId = bldg.zoneId
  
      def generate(self):
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.generate(self)
  
      def generateWithRequired(self, zoneId):
          self.zoneId = zoneId
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.generateWithRequired(self, self.zoneId)
  
      def delete(self):
          for seatIndex in xrange(len(self.seats)):
              avId = self.seats[seatIndex]
              if avId:
                  self.clearFullNow(seatIndex)
                  self.clearEmptyNow(seatIndex)
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.delete(self)
  
      def getEntranceId(self):
          return self.entranceId
  
      def d_setFloor(self, floorNumber):
          self.sendUpdate('setFloor', [floorNumber])
  
      def avIsOKToBoard(self, av):
          if av.hp > 0 and self.accepting:
              pass
          return not (self.isLocked)
  
      def acceptBoarder(self, avId, seatIndex):
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.acceptBoarder(self, avId, seatIndex)
          self.acceptOnce(self.air.getAvatarExitEvent(avId), self._DistributedElevatorFloorAI__handleUnexpectedExit, extraArgs = [
              avId])
          if self.state == 'WaitEmpty' and self.countFullSeats() < self.countAvsInZone():
              self.request('WaitCountdown')
              self.bldg.elevatorAlert(avId)
          elif self.state in ('WaitCountdown', 'WaitEmpty') and self.countFullSeats() >= self.countAvsInZone():
              taskMgr.doMethodLater(TOON_BOARD_ELEVATOR_TIME, self.goAllAboard, self.quickBoardTask)
  
      def countAvsInZone(self):
          matchingZones = 0
          for avId in self.bldg.avIds:
              av = self.air.doId2do.get(avId)
              if av:
                  if av.zoneId == self.bldg.zoneId:
                      matchingZones += 1
          return matchingZones
  
      def goAllAboard(self, throwAway = 1):
          self.request('Closing')
          return Task.done
  
      def _DistributedElevatorFloorAI__handleUnexpectedExit(self, avId):
          self.notify.warning('Avatar: ' + str(avId) + ' has exited unexpectedly')
          seatIndex = self.findAvatar(avId)
          if seatIndex == None:
              pass
          self.clearFullNow(seatIndex)
          self.clearEmptyNow(seatIndex)
          if self.countFullSeats() == 0:
              self.request('WaitEmpty')
  
      def acceptExiter(self, avId):
          seatIndex = self.findAvatar(avId)
          if seatIndex == None:
              pass
          self.clearFullNow(seatIndex)
          bailFlag = 0
          if self.anyToonsBailed == 0:
              bailFlag = 1
              self.resetCountdown()
              self.anyToonsBailed = 1
          self.sendUpdate('emptySlot' + str(seatIndex), [avId, bailFlag, globalClockDelta.getRealNetworkTime()])
          if self.countFullSeats() == 0:
              self.request('WaitEmpty')
          taskMgr.doMethodLater(TOON_EXIT_ELEVATOR_TIME, self.clearEmptyNow, self.uniqueName('clearEmpty-%s' % seatIndex), extraArgs = (seatIndex,))
  
      def enterOpening(self):
          self.d_setState('Opening')
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.enterOpening(self)
          taskMgr.doMethodLater(ElevatorData[ELEVATOR_NORMAL]['openTime'], self.waitEmptyTask, self.uniqueName('opening-timer'))
  
      def exitOpening(self):
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.exitOpening(self)
          if self.isLocked:
              self.wantState = 'closed'
          if self.wantState == 'closed':
              self.demand('Closing')
  
      def waitEmptyTask(self, task):
          self.request('WaitEmpty')
          return Task.done
  
      def enterWaitEmpty(self):
          self.lastState = self.state
          for i in xrange(len(self.seats)):
              self.seats[i] = None
          print self.seats
          if self.wantState == 'closed':
              self.demand('Closing')
          else:
              self.d_setState('WaitEmpty')
              self.accepting = 1
  
      def enterWaitCountdown(self):
          self.lastState = self.state
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.enterWaitCountdown(self)
          taskMgr.doMethodLater(self.countdownTime, self.timeToGoTask, self.uniqueName('countdown-timer'))
          if self.lastState == 'WaitCountdown':
              pass
  
      def timeToGoTask(self, task):
          if self.countFullSeats() > 0:
              self.request('AllAboard')
          else:
              self.request('WaitEmpty')
          return Task.done
  
      def resetCountdown(self):
          taskMgr.remove(self.uniqueName('countdown-timer'))
          taskMgr.doMethodLater(self.countdownTime, self.timeToGoTask, self.uniqueName('countdown-timer'))
  
      def enterAllAboard(self):
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.enterAllAboard(self)
          currentTime = globalClock.getRealTime()
          elapsedTime = currentTime - self.timeOfBoarding
          self.notify.debug('elapsed time: ' + str(elapsedTime))
          waitTime = max(TOON_BOARD_ELEVATOR_TIME - elapsedTime, 0)
          taskMgr.doMethodLater(waitTime, self.closeTask, self.uniqueName('waitForAllAboard'))
  
      def closeTask(self, task):
          if self.countFullSeats() >= 1:
              self.request('Closing')
          else:
              self.request('WaitEmpty')
          return Task.done
  
      def enterClosing(self):
          if self.countFullSeats() > 0:
              self.sendUpdate('kickToonsOut')
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.enterClosing(self)
          taskMgr.doMethodLater(ElevatorData[ELEVATOR_STAGE]['closeTime'], self.elevatorClosedTask, self.uniqueName('closing-timer'))
          self.d_setState('Closing')
  
      def elevatorClosedTask(self, task):
          self.elevatorClosed()
          return Task.done
  
      def elevatorClosed(self):
          if self.isLocked:
              self.request('Closed')
              return None
          numPlayers = self.countFullSeats()
          if numPlayers > 0:
              players = []
              for i in self.seats:
                  if i not in [None, 0]:
                      players.append(i)
                      continue
              sittingAvIds = []
              for seatIndex in xrange(len(self.seats)):
                  avId = self.seats[seatIndex]
                  if avId:
                      sittingAvIds.append(avId)
                      continue
              for avId in self.avIds:
                  if avId not in sittingAvIds:
                      continue
              self.bldg.startNextFloor()
          else:
              self.notify.warning('The elevator left, but was empty.')
          self.request('Closed')
  
      def setLocked(self, locked):
          self.isLocked = locked
          if locked:
              if self.state == 'WaitEmpty':
                  self.request('Closing')
  
              if self.countFullSeats() == 0:
                  self.wantState = 'closed'
              else:
                  self.wantState = 'opening'
          else:
              self.wantState = 'waitEmpty'
              if self.state == 'Closed':
                  self.request('Opening')
  
      def getLocked(self):
          return self.isLocked
  
      def unlock(self):
          if self.isLocked:
              self.setLocked(0)
  
      def lock(self):
          if not self.isLocked:
              self.setLocked(1)
  
      def start(self):
          self.quickBoardTask = self.uniqueName('quickBoard')
          self.request('Opening')
  
      def beClosed(self):
          pass
  
      def setEntering(self, entering):
          self.isEntering = entering
  
      def getEntering(self):
          return self.isEntering
  
      def enterClosed(self):
          DistributedElevatorFSMAI.DistributedElevatorFSMAI.enterClosed(self)
          if self.wantState == 'closed':
              pass
          self.demand('Opening')
  
      def enterOff(self):
          self.lastState = self.state
          if self.wantState == 'closed':
              self.demand('Closing')
          elif self.wantState == 'waitEmpty':
              self.demand('WaitEmpty')
  
      def setPos(self, pointPos):
          self.sendUpdate('setPos', [pointPos[0], pointPos[1], pointPos[2]])
  
      def setH(self, H):
          self.sendUpdate('setH', [H])
  
      def setLatch(self, markerId):
          self.latch = markerId
  
      def getLatch(self):
          return self.latch
  