from otp.ai.AIBase import * from toontown.toonbase.ToontownGlobals import * from direct.distributed.ClockDelta import * from TrolleyConstants import * from toontown.toonbase import ToontownGlobals from direct.distributed import DistributedObjectAI from direct.fsm import ClassicFSM, State from direct.fsm import State from direct.task import Task from direct.directnotify import DirectNotifyGlobal from direct.showbase import RandomNumGen from toontown.minigame import MinigameCreatorAI from toontown.quest import Quests from toontown.minigame import TrolleyHolidayMgrAI from toontown.golf import GolfManagerAI from toontown.golf import GolfGlobals class DistributedPicnicBasketAI(DistributedObjectAI.DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPicnicBasketAI') def __init__(self, air, tableNumber, x, y, z, h, p, r): DistributedObjectAI.DistributedObjectAI.__init__(self, air) self.seats = [ None, None, None, None] self.posHpr = (x, y, z, h, p, r) self.tableNumber = int(tableNumber) self.seed = RandomNumGen.randHash(globalClock.getRealTime()) self.accepting = 0 self.numPlayersExiting = 0 self.trolleyCountdownTime = simbase.config.GetFloat('picnic-countdown-time', ToontownGlobals.PICNIC_COUNTDOWN_TIME) self.fsm = ClassicFSM.ClassicFSM('DistributedPicnicBasketAI', [ State.State('off', self.enterOff, self.exitOff, [ 'waitEmpty']), State.State('waitEmpty', self.enterWaitEmpty, self.exitWaitEmpty, [ 'waitCountdown']), State.State('waitCountdown', self.enterWaitCountdown, self.exitWaitCountdown, [ 'waitEmpty'])], 'off', 'off') self.fsm.enterInitialState() return def delete(self): self.fsm.requestFinalState() del self.fsm DistributedObjectAI.DistributedObjectAI.delete(self) def findAvailableSeat(self): for i in range(len(self.seats)): if self.seats[i] == None: return i return def findAvatar(self, avId): for i in range(len(self.seats)): if self.seats[i] == avId: return i return None def countFullSeats(self): avCounter = 0 for i in self.seats: if i: avCounter += 1 return avCounter def rejectingBoardersHandler(self, avId, si): self.rejectBoarder(avId) def rejectBoarder(self, avId): self.sendUpdateToAvatarId(avId, 'rejectBoard', [avId]) def acceptingBoardersHandler(self, avId, si): self.notify.debug('acceptingBoardersHandler') seatIndex = si if not seatIndex == None: self.acceptBoarder(avId, seatIndex) return def acceptBoarder(self, avId, seatIndex): self.notify.debug('acceptBoarder %d' % avId) if self.findAvatar(avId) != None: return self.seats[seatIndex] = avId self.acceptOnce(self.air.getAvatarExitEvent(avId), self.__handleUnexpectedExit, extraArgs=[avId]) self.timeOfBoarding = globalClock.getRealTime() self.sendUpdate('fillSlot' + str(seatIndex), [ avId]) self.waitCountdown() return def __handleUnexpectedExit(self, avId): self.notify.warning('Avatar: ' + str(avId) + ' has exited unexpectedly') seatIndex = self.findAvatar(avId) if seatIndex == None: pass else: self.clearFullNow(seatIndex) self.clearEmptyNowUnexpected(seatIndex) if self.countFullSeats() == 0: self.waitEmpty() return def clearEmptyNowUnexpected(self, seatIndex): self.sendUpdate('emptySlot' + str(seatIndex), [ 1, globalClockDelta.getRealNetworkTime()]) def rejectingExitersHandler(self, avId): self.rejectExiter(avId) def rejectExiter(self, avId): pass def acceptingExitersHandler(self, avId): self.acceptExiter(avId) def acceptExiter(self, avId): seatIndex = self.findAvatar(avId) if seatIndex == None: pass else: self.clearFullNow(seatIndex) self.sendUpdate('emptySlot' + str(seatIndex), [ avId, globalClockDelta.getRealNetworkTime()]) taskMgr.doMethodLater(TOON_EXIT_TIME, self.clearEmptyNow, self.uniqueName('clearEmpty-%s' % seatIndex), extraArgs=(seatIndex,)) return def clearEmptyNow(self, seatIndex): self.notify.debugStateCall(self) self.sendUpdate('emptySlot' + str(seatIndex), [ 0, globalClockDelta.getRealNetworkTime()]) def clearFullNow(self, seatIndex): avId = self.seats[seatIndex] if avId == 0: self.notify.warning('Clearing an empty seat index: ' + str(seatIndex) + ' ... Strange...') else: self.seats[seatIndex] = None self.sendUpdate('fillSlot' + str(seatIndex), [ 0]) self.ignore(self.air.getAvatarExitEvent(avId)) return def d_setState(self, state, seed): self.sendUpdate('setState', [state, seed, globalClockDelta.getRealNetworkTime()]) def getState(self): return self.fsm.getCurrentState().getName() def requestBoard(self, si): self.notify.debug('requestBoard') avId = self.air.getAvatarIdFromSender() if self.findAvatar(avId) != None: self.notify.warning('Ignoring multiple requests from %s to board.' % avId) return av = self.air.doId2do.get(avId) if av: if av.hp > 0 and self.accepting and self.seats[si] == None: self.notify.debug('accepting boarder %d' % avId) self.acceptingBoardersHandler(avId, si) else: self.notify.debug('rejecting boarder %d' % avId) self.rejectingBoardersHandler(avId, si) else: self.notify.warning('avid: %s does not exist, but tried to board a trolley' % avId) return def requestExit(self, *args): self.notify.debug('requestExit') avId = self.air.getAvatarIdFromSender() av = self.air.doId2do.get(avId) if av: if self.countFullSeats() > 0: newArgs = ( avId,) + args self.numPlayersExiting += 1 if self.accepting: self.acceptingExitersHandler(*newArgs) else: self.rejectingExitersHandler(*newArgs) else: self.notify.debug('Player tried to exit after AI already kicked everyone out') else: self.notify.warning('avId: %s does not exist, but tried to exit a trolley' % avId) def doneExit(self): if self.numPlayersExiting > 0: self.numPlayersExiting -= 1 if self.numPlayersExiting == 0 and self.countFullSeats() == 0: self.waitEmpty() def start(self): self.waitEmpty() def enterOff(self): self.accepting = 0 if hasattr(self, 'doId'): for seatIndex in range(4): taskMgr.remove(self.uniqueName('clearEmpty-' + str(seatIndex))) def exitOff(self): self.accepting = 0 def waitEmptyTask(self, task): self.waitEmpty() return Task.done def waitEmpty(self): self.fsm.request('waitEmpty') def enterWaitEmpty(self): self.notify.debugStateCall(self) self.d_setState('waitEmpty', self.seed) self.seats = [None, None, None, None] self.accepting = 1 return def exitWaitEmpty(self): self.notify.debugStateCall(self) self.accepting = 0 def waitCountdown(self): self.notify.debugStateCall(self) self.fsm.request('waitCountdown') def enterWaitCountdown(self): self.notify.debugStateCall(self) self.d_setState('waitCountdown', self.seed) self.accepting = 1 taskMgr.doMethodLater(self.trolleyCountdownTime, self.timeToGoTask, self.uniqueName('countdown-timer')) def timeToGoTask(self, task): self.accepting = 0 if self.countFullSeats() > 0: for x in range(len(self.seats)): if not self.seats[x] == None: self.sendUpdateToAvatarId(self.seats[x], 'setPicnicDone', []) self.acceptExiter(self.seats[x]) self.numPlayersExiting += 1 self.waitEmpty() return Task.done def exitWaitCountdown(self): self.notify.debugStateCall(self) self.accepting = 0 taskMgr.remove(self.uniqueName('countdown-timer')) def getPosHpr(self): return self.posHpr def getTableNumber(self): return self.tableNumber