class DistributedPicnicTable(DistributedNode.DistributedNode): def __init__(self, cr): self.cr = cr NodePath.__init__(self, 'DistributedPicnicTable') DistributedNode.DistributedNode.__init__(self, cr) self.reparentTo(render) self.picnicTable = loader.loadModel('phase_6/models/golf/game_table') self.picnicTable.reparentTo(self) self.picnicTableSphereNodes = [] self.numSeats = 6 self.seats = [] self.jumpOffsets = [] self.inGame = False self.requestSeat = None self.gameState = None self.cameraBoardTrack = Func(self.doNothing) self.seatBumpForObserve = 0 self.winTrack = Sequence() self.outTrack = Sequence() self.joinButton = None self.observeButton = None self.tutorialButton = None self.exitButton = None self.isPlaying = False self.gameMenu = None self.game = None self.gameZone = None self.tutorial = None self.timerFunc = None self.gameDoId = None self.gameWantTimer = False self.tableState = [None, None, None, None, None, None] self.haveAnimated = [] self.winSound = base.loadSfx('phase_6/audio/sfx/KART_Applause_1.ogg') self.happyDance = base.loadSfx('phase_5/audio/sfx/AA_heal_happydance.ogg') self.accept('stoppedAsleep', self.handleSleep) base.localAvatar.startSleepWatch(self.handleSleep) self.__toonTracks = {} self.fsm = ClassicFSM.ClassicFSM('PicnicTable', [State.State('off', self.enterOff, self.exitOff, ['chooseMode', 'observing']), State.State('chooseMode', self.enterChooseMode, self.exitChooseMode, ['sitting', 'off', 'observing']), State.State('sitting', self.enterSitting, self.exitSitting, ['off']), State.State('observing', self.enterObserving, self.exitObserving, ['off'])], 'off', 'off') self.fsm.enterInitialState() for i in range(self.numSeats): self.seats.append(self.picnicTable.find('**/*seat%d' % (i + 1))) self.jumpOffsets.append(self.picnicTable.find('**/*jumpOut%d' % (i + 1))) self.tableCloth = self.picnicTable.find('**/basket_locator') self.tableclothSphereNode = self.tableCloth.attachNewNode(CollisionNode('tablecloth_sphere')) self.tableclothSphereNode.node().addSolid(CollisionSphere(0, 0, -2, 5.5)) self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) for i in range(self.numSeats): self.picnicTableSphereNodes.append(self.seats[i].attachNewNode(CollisionNode('picnicTable_sphere_%d_%d' % (self.getDoId(), i)))) self.picnicTableSphereNodes[i].node().addSolid(CollisionSphere(0, 0, 0, 2)) self.tableState = [None, None, None, None, None, None] self.requestTableState() self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') angle = self.getH() angle -= 90 radAngle = deg2Rad(angle) unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0) unitVec *= 30.0 self.endPos = self.getPos() + unitVec dist = Vec3(self.endPos - self.getPos()).length() wheelAngle = dist / (0.7 * math.pi) * 360 self.__enableCollisions() def handleSleep(self, task = None): if self.fsm.getCurrentState().getName() == 'chooseMode': self.cancelButtonPushed() elif self.fsm.getCurrentState().getName() == 'sitting': self.sendUpdate('requestExit', []) if self.gameMenu != None: self.gameMenu.removeButtons() self.gameMenu.picnicFunction = None self.gameMenu = None if task != None: task.done def disable(self): DistributedNode.DistributedNode.disable(self) self.ignore('stoppedAsleep') self.clearToonTracks() self.__disableCollisions() self.disableChoiceButtons() self.picnicTable.removeNode() self.cameraBoardTrack = None def delete(self): self.__disableCollisions() self.ignore('stoppedAsleep') DistributedNode.DistributedNode.delete(self) self.disableChoiceButtons() self.cameraBoardTrack = None del self.winTrack del self.outTrack self.fsm = None self.gameZone = None self.clearToonTracks() self.cameraBoardTrack = None def setName(self, name): self.name = name def setGameDoId(self, doId): self.gameDoId = doId self.game = self.cr.doId2do[doId] self.game.setHpr(self.getHpr()) self.gameWantTimer = self.game.wantTimer if self.gameState == 1: self.game.fsm.request('playing') def setTimerFunc(self, function): self.timerFunc = function def setTimer(self, timerEnd): self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) self.timeLeft = int(time - globalClock.getRealTime()) if self.gameWantTimer and self.game != None: self.showTimer() def showTimer(self): self.clockNode.stop() self.clockNode.countdown(self.timeLeft, self.timerFunc) self.clockNode.show() def requestTableState(self): self.sendUpdate('requestTableState', []) def setTableState(self, tableStateList, isplaying): y = 0 print 'SET TABLE STATE' if isplaying == 0: self.isPlaying = False else: self.isPlaying = True for x in tableStateList: if x != 0: if x not in self.tableState and self.cr.doId2do.has_key(x) and x not in self.haveAnimated: seatIndex = tableStateList.index(x) toon = self.cr.doId2do[x] toon.stopSmooth() toon.setAnimState('Sit', 1.0) dest = self.seats[seatIndex].getPos(self.tableCloth) hpr = self.seats[seatIndex].getHpr(render) toon.setHpr(hpr) if seatIndex > 2: toon.setH(self.getH() + 180) toon.wrtReparentTo(self) toon.setPos(dest) toon.setZ(toon.getZ() + 1.35) if seatIndex > 2: toon.setY(toon.getY() - 1.0) else: toon.setY(toon.getY() + 1.0) if x != 0: self.tableState[y] = x else: self.tableState[y] = None y += 1 numPlayers = 0 for x in self.tableState: if x != None: numPlayers += 1 print ' GETTING 2', self.gameMenu, numPlayers if self.gameMenu: if numPlayers > 2: print ' GETTING HERE!!' self.gameMenu.FindFour.setColor(0.7, 0.7, 0.7, 0.7) self.gameMenu.FindFour['command'] = self.doNothing self.gameMenu.findFourText['fg'] = (0.7, 0.7, 0.7, 0.7) self.gameMenu.Checkers.setColor(0.7, 0.7, 0.7, 0.7) self.gameMenu.Checkers['command'] = self.doNothing self.gameMenu.checkersText['fg'] = (0.7, 0.7, 0.7, 0.7) def setIsPlaying(self, isPlaying): if isPlaying == 0: self.isPlaying = False elif isPlaying == 1: self.isPlaying = True def announceWinner(self, winString, avId): if avId == base.localAvatar.getDoId(): sound = Sequence(Wait(2.0), Parallel(SoundInterval(self.winSound), SoundInterval(self.happyDance))) sound.start() base.cr.playGame.getPlace().setState('walk') if winString == 'Chinese Checkers': whisper = WhisperPopup(TTLocalizer.ChineseCheckersYouWon, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == 'Checkers': whisper = WhisperPopup(TTLocalizer.RegularCheckersYouWon, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == 'Find Four': whisper = WhisperPopup('You won a game of Find Four!', OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif self.cr.doId2do.has_key(avId): stateString = self.fsm.getCurrentState().getName() if stateString == 'sitting' or stateString == 'observing': base.cr.playGame.getPlace().setState('walk') av = self.cr.doId2do[avId] if winString == 'Chinese Checkers': whisper = WhisperPopup(av.getName() + TTLocalizer.ChineseCheckersGameOf + TTLocalizer.ChineseCheckers, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == 'Checkers': whisper = WhisperPopup(av.getName() + TTLocalizer.RegularCheckersGameOf + TTLocalizer.RegularCheckers, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == 'Find Four': whisper = WhisperPopup(av.getName() + ' has won a game of' + ' Find Four!', OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) if self.cr.doId2do.has_key(avId): toon = self.cr.doId2do[avId] self.winTrack = Sequence(autoFinish=1) if self.outTrack.isPlaying(): self.winTrack.append(Wait(2.0)) if avId == base.localAvatar.getDoId(): self.winTrack.append(Func(self.stopToWalk)) self.winTrack.append(ActorInterval(toon, 'happy-dance')) if avId == base.localAvatar.getDoId(): self.winTrack.append(Func(self.allowToWalk)) self.winTrack.start() whisper.manage(base.marginManager) def handleEnterPicnicTableSphere(self, i, collEntry): self.notify.debug('Entering Picnic Table Sphere.... %s' % self.getDoId()) self.requestSeat = i self.seatBumpForObserve = i self.fsm.request('chooseMode') def enableChoiceButtons(self): if self.tableState[self.seatBumpForObserve] == None and self.isPlaying == False: self.joinButton = DirectButton(relief=None, text=TTLocalizer.PicnicTableJoinButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, 0.8), scale=0.15, command=lambda self = self: self.joinButtonPushed()) if self.isPlaying: self.observeButton = DirectButton(relief=None, text=TTLocalizer.PicnicTableObserveButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, 0.6), scale=0.15, command=lambda self = self: self.observeButtonPushed()) self.exitButton = DirectButton(relief=None, text=TTLocalizer.PicnicTableCancelButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(1, 0, 0.6), scale=0.15, command=lambda self = self: self.cancelButtonPushed()) self.tutorialButton = DirectButton(relief=None, text=TTLocalizer.PicnicTableTutorial, text_fg=(1, 1, 0.65, 1), text_pos=(-0.05, -0.13), text_scale=0.55, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-1, 0, 0.6), scale=0.15, command=lambda self = self: self.tutorialButtonPushed()) base.cr.playGame.getPlace().setState('stopped') def tutorialButtonPushed(self): self.disableChoiceButtons() self.gameMenu = GameMenu(self.tutorialFunction, 1) self.tutorialButton.destroy() self.tutorialButton = None def tutorialFunction(self, tutVal): if tutVal == 1: self.tutorial = ChineseTutorial(self.tutorialDone) elif tutVal == 2: self.tutorial = CheckersTutorial(self.tutorialDone) self.gameMenu.picnicFunction = None self.gameMenu = None def tutorialDone(self): self.requestSeat = None self.fsm.request('off') self.tutorial = None def joinButtonPushed(self): toon = base.localAvatar self.sendUpdate('requestJoin', [self.requestSeat, toon.getX(), toon.getY(), toon.getZ(), toon.getH(), toon.getP(), toon.getR()]) self.requestSeat = None self.fsm.request('sitting') def rejectJoin(self): self.fsm.request('off') self.allowToWalk() def cancelButtonPushed(self): base.cr.playGame.getPlace().setState('walk') self.requestSeat = None self.fsm.request('off') def disableChoiceButtons(self): if self.joinButton: self.joinButton.destroy() if self.observeButton: self.observeButton.destroy() if self.exitButton: self.exitButton.destroy() if self.tutorialButton: self.tutorialButton.destroy() def pickFunction(self, gameNum): if gameNum == 1: self.sendUpdate('requestPickedGame', [gameNum]) elif gameNum == 2: self.sendUpdate('requestPickedGame', [gameNum]) elif gameNum == 3: self.sendUpdate('requestPickedGame', [gameNum]) def allowPick(self): self.gameMenu = GameMenu(self.pickFunction, 2) def setZone(self, zoneId): if self.fsm.getCurrentState().getName() == 'sitting' or self.fsm.getCurrentState().getName() == 'observing': if self.tutorial == None: self.gameZone = base.cr.addInterest(base.localAvatar.defaultShard, zoneId, 'gameBoard') if self.gameMenu != None: self.gameMenu.removeButtons() self.gameMenu.picnicFunction = None self.gameMenu = None def fillSlot(self, avId, index, x, y, z, h, p, r, timestamp, parentDoId): self.notify.debug('fill Slot: %d for %d' % (index, avId)) if avId not in self.haveAnimated: self.haveAnimated.append(avId) if avId == base.localAvatar.getDoId(): if self.inGame: return self.inGame = True self.seatPos = index if self.cr.doId2do.has_key(avId): toon = self.cr.doId2do[avId] toon.stopSmooth() toon.wrtReparentTo(self.tableCloth) sitStartDuration = toon.getDuration('sit-start') jumpTrack = self.generateToonJumpTrack(toon, index) track = Sequence(autoFinish=1) if avId == base.localAvatar.getDoId(): if not base.cr.playGame.getPlace() == None: self.moveCamera(index) track.append(Func(self.__disableCollisions)) track.append(jumpTrack) track.append(Func(toon.setAnimState, 'Sit', 1.0)) track.append(Func(self.clearToonTrack, avId)) self.storeToonTrack(avId, track) track.start() def emptySlot(self, avId, index, timestamp): self.notify.debug('### seat %s now empty' % index) if index == 255 and self.game != None: self.stopObserveButtonPushed() return if avId in self.haveAnimated: self.haveAnimated.remove(avId) if self.cr.doId2do.has_key(avId): if avId == base.localAvatar.getDoId(): if self.gameZone: base.cr.removeInterest(self.gameZone) if self.inGame: self.inGame = False else: return toon = self.cr.doId2do[avId] toon.stopSmooth() sitStartDuration = toon.getDuration('sit-start') jumpOutTrack = self.generateToonReverseJumpTrack(toon, index) self.outTrack = Sequence(jumpOutTrack) if base.localAvatar.getDoId() == avId: self.outTrack.append(Func(self.__enableCollisions)) self.outTrack.append(Func(self.allowToWalk)) self.fsm.request('off') val = self.jumpOffsets[index].getPos(render) self.outTrack.append(Func(toon.setPos, val)) self.outTrack.append(Func(toon.startSmooth)) self.outTrack.start() def stopToWalk(self): base.cr.playGame.getPlace().setState('stopped') def allowToWalk(self): base.cr.playGame.getPlace().setState('walk') def moveCamera(self, seatIndex): self.oldCameraPos = camera.getPos() self.oldCameraHpr = camera.getHpr() camera.wrtReparentTo(self.picnicTable) heading = PythonUtil.fitDestAngle2Src(camera.getH(), 90) if seatIndex < 3: self.cameraBoardTrack = LerpPosHprInterval(camera, 2.0, Point3(0, 0, 17), Point3(0, -90, 0)) elif camera.getH() < 0: self.cameraBoardTrack = LerpPosHprInterval(camera, 2.0, Point3(0, 0, 17), Point3(-180, -90, 0)) else: self.cameraBoardTrack = LerpPosHprInterval(camera, 2.0, Point3(0, 0, 17), Point3(180, -90, 0)) self.cameraBoardTrack.start() def moveCameraBack(self): self.cameraBoardTrack = LerpPosHprInterval(camera, 2.5, self.oldCameraPos, self.oldCameraHpr) self.cameraBoardTrack.start() def __enableCollisions(self): for i in range(self.numSeats): self.accept('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTableSphere, [i]) self.picnicTableSphereNodes[i].setCollideMask(ToontownGlobals.WallBitmask) self.tableclothSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def __disableCollisions(self): for i in range(self.numSeats): self.ignore('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i)) self.ignore('enterPicnicTableOK_%d_%d' % (self.getDoId(), i)) for i in range(self.numSeats): self.picnicTableSphereNodes[i].setCollideMask(BitMask32(0)) self.tableclothSphereNode.setCollideMask(BitMask32(0)) def enterOff(self): base.setCellsAvailable(base.leftCells + base.bottomCells, 0) def exitOff(self): base.setCellsAvailable(base.bottomCells, 0) def enterChooseMode(self): self.winTrack = Sequence(autoFinish=1) self.enableChoiceButtons() def exitChooseMode(self): self.disableChoiceButtons() def enterObserving(self): self.enableStopObserveButton() self.moveCamera(self.seatBumpForObserve) self.sendUpdate('requestGameZone') def exitObserving(self): if self.cameraBoardTrack.isPlaying(): self.cameraBoardTrack.pause() self.allowToWalk() self.stopObserveButton.destroy() def enterSitting(self): pass def exitSitting(self): self.gameMenu = None def setGameZone(self, zoneId, gamestate): self.gameZone = base.cr.addInterest(base.localAvatar.defaultShard, zoneId, 'gameBoard') self.gameState = gamestate def observeButtonPushed(self): self.requestSeat = None self.fsm.request('observing') def enableStopObserveButton(self): self.stopObserveButton = DirectButton(relief=None, text='Stop Observing', text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.45, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self = self: self.stopObserveButtonPushed()) def stopObserveButtonPushed(self): self.sendUpdate('leaveObserve', []) self.gameState = None if self.game: self.game.fsm.request('gameOver') base.cr.removeInterest(self.gameZone) self.fsm.request('off') def generateToonReverseJumpTrack(self, av, seatIndex): self.notify.debug('av.getH() = %s' % av.getH()) def getToonJumpTrack(av, destNode): def getJumpDest(av = av, node = destNode): dest = node.getPos(self.tableCloth) dest += self.jumpOffsets[seatIndex].getPos(self.tableCloth) return dest def getJumpHpr(av = av, node = destNode): hpr = node.getHpr(av.getParent()) hpr.setX(hpr.getX() + 180) angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX()) hpr.setX(angle) return hpr toonJumpTrack = Parallel(ActorInterval(av, 'jump'), Sequence(Wait(0.1), Parallel(ProjectileInterval(av, endPos=getJumpDest, duration=0.9)))) return toonJumpTrack toonJumpTrack = getToonJumpTrack(av, self.tableCloth) jumpTrack = Sequence(toonJumpTrack, Func(av.loop, 'neutral'), Func(av.wrtReparentTo, render)) return jumpTrack def generateToonJumpTrack(self, av, seatIndex): av.pose('sit', 47) hipOffset = av.getHipsParts()[2].getPos(av) def getToonJumpTrack(av, seatIndex): def getJumpDest(av = av, node = self.tableCloth): dest = Vec3(self.tableCloth.getPos(av.getParent())) seatNode = self.picnicTable.find('**/seat' + str(seatIndex + 1)) dest += seatNode.getPos(self.tableCloth) dna = av.getStyle() dest -= hipOffset if seatIndex > 2: dest.setY(dest.getY() - 2.0) if seatIndex == 1: dest.setY(dest.getY() - 0.5) dest.setZ(dest.getZ() + 0.2) return dest def getJumpHpr(av = av, node = self.tableCloth): hpr = self.seats[seatIndex].getHpr(av.getParent()) if seatIndex < 3: hpr.setX(hpr.getX()) elif av.getH() < 0: hpr.setX(hpr.getX() - 180) else: hpr.setX(hpr.getX() + 180) return hpr toonJumpTrack = Parallel(ActorInterval(av, 'jump'), Sequence(Wait(0.43), Parallel(LerpHprInterval(av, hpr=getJumpHpr, duration=1), ProjectileInterval(av, endPos=getJumpDest, duration=1)))) return toonJumpTrack def getToonSitTrack(av): toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit')) return toonSitTrack toonJumpTrack = getToonJumpTrack(av, seatIndex) toonSitTrack = getToonSitTrack(av) jumpTrack = Sequence(Parallel(toonJumpTrack, Sequence(Wait(1), toonSitTrack)), Func(av.wrtReparentTo, self.tableCloth)) return jumpTrack def storeToonTrack(self, avId, track): self.clearToonTrack(avId) self.__toonTracks[avId] = track def clearToonTrack(self, avId): oldTrack = self.__toonTracks.get(avId) if oldTrack: oldTrack.pause() DelayDelete.cleanupDelayDeletes(oldTrack) def clearToonTracks(self): keyList = [] for key in self.__toonTracks: keyList.append(key) for key in keyList: if self.__toonTracks.has_key(key): self.clearToonTrack(key) def doNothing(self): pass
class DistributedChineseCheckers(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, 'DistributedChineseCheckers') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel('phase_6/models/golf/checker_game.bam') self.boardNode.reparentTo(self) self.board = ChineseCheckersBoard() self.playerTags = render.attachNewNode('playerTags') self.playerTagList = [] self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.1599999999999999, 0, -0.82999999999999996) self.clockNode.setScale(0.29999999999999999) self.clockNode.hide() self.playerColors = [ Vec4(0, 0.90000000000000002, 0, 1), Vec4(0.90000000000000002, 0.90000000000000002, 0, 1), Vec4(0.45000000000000001, 0, 0.45000000000000001, 1), Vec4(0.20000000000000001, 0.40000000000000002, 0.80000000000000004, 1), Vec4(1, 0.45000000000000001, 1, 1), Vec4(0.80000000000000004, 0, 0, 1)] self.tintConstant = Vec4(0.25, 0.25, 0.25, 0) self.ghostConstant = Vec4(0, 0, 0, 0.5) self.startingPositions = [ [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [ 10, 11, 12, 13, 23, 24, 25, 35, 36, 46], [ 65, 75, 76, 86, 87, 88, 98, 99, 100, 101], [ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [ 74, 84, 85, 95, 96, 97, 107, 108, 109, 110], [ 19, 20, 21, 22, 32, 33, 34, 44, 45, 55]] self.nonOpposingPositions = [] self.knockSound = base.loadSfx('phase_5/audio/sfx/GUI_knock_1.mp3') self.clickSound = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.mp3') self.moveSound = base.loadSfx('phase_6/audio/sfx/CC_move.mp3') self.accept('stoppedAsleep', self.handleSleep) ClassicFSM = ClassicFSM State = State import direct.fsm self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [ State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, [ 'playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, [ 'gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, [ 'waitingToBegin'])], 'waitingToBegin', 'waitingToBegin') x = self.boardNode.find('**/locators') self.locatorList = x.getChildren() tempList = [] for x in range(0, 121): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) tempList.append(self.locatorList[x].attachNewNode(CollisionNode('picker%d' % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.115)) for z in self.locatorList: y = loader.loadModel('phase_6/models/golf/checker_marble.bam') z.setColor(0, 0, 0, 0) y.reparentTo(z) def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: self.seatPos = self.table.tableState.index(base.localAvatar.doId) self.playerTags.setPos(self.getPos()) def handleSleep(self, task = None): if self.fsm.getCurrentState().getName() == 'waitingToBegin': self.exitButtonPushed() if task != None: pass 1 def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.cleanPlayerTags() def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None self.cleanPlayerTags() del self.playerTags del self.playerTagList self.playerSeats = None self.yourTurnBlinker.finish() def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'waitingToBegin' and not (self.table.fsm.getCurrentState().getName() == 'observing'): self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0 and timerEnd != 0: if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.1599999999999999, 0, -0.82999999999999996) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(-0.73999999999999999, 0, -0.20000000000000001) if self.isMyTurn: self.clockNode.countdown(timeLeft, self.doRandomMove) else: self.clockNode.countdown(timeLeft, self.doNothing) self.clockNode.show() def gameStart(self, playerNum): if playerNum != 255: self.playerNum = playerNum self.playerColor = self.playerColors[playerNum - 1] self.moveCameraForGame() playerPos = playerNum - 1 import copy as copy self.nonOpposingPositions = copy.deepcopy(self.startingPositions) if playerPos == 0: self.nonOpposingPositions.pop(0) self.opposingPositions = self.nonOpposingPositions.pop(2) elif playerPos == 1: self.nonOpposingPositions.pop(1) self.opposingPositions = self.nonOpposingPositions.pop(3) elif playerPos == 2: self.nonOpposingPositions.pop(2) self.opposingPositions = self.nonOpposingPositions.pop(4) elif playerPos == 3: self.nonOpposingPositions.pop(3) self.opposingPositions = self.nonOpposingPositions.pop(0) elif playerPos == 4: self.nonOpposingPositions.pop(4) self.opposingPositions = self.nonOpposingPositions.pop(1) elif playerPos == 5: self.nonOpposingPositions.pop(5) self.opposingPositions = self.nonOpposingPositions.pop(2) self.fsm.request('playing') def sendTurn(self, playersTurn): self.playersTurnBlinker.finish() if self.fsm.getCurrentState().getName() == 'playing': if self.playerSeats == None: self.sendUpdate('requestSeatPositions', []) elif playersTurn == self.playerNum: self.isMyTurn = True self.enableTurnScreenText(playersTurn) self.playersTurnBlinker = Sequence() origColor = self.playerColors[playersTurn - 1] self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], 0.40000000000000002, origColor - self.tintConstant - self.ghostConstant, origColor)) self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], 0.40000000000000002, origColor, origColor - self.tintConstant - self.ghostConstant)) self.playersTurnBlinker.loop() def announceSeatPositions(self, playerPos): self.playerSeats = playerPos for x in range(6): pos = self.table.seats[x].getPos(render) renderedPeice = loader.loadModel('phase_6/models/golf/checker_marble.bam') renderedPeice.reparentTo(self.playerTags) renderedPeice.setPos(pos) renderedPeice.setScale(1.5) if x == 1: renderedPeice.setZ(renderedPeice.getZ() + 3.2999999999999998) renderedPeice.setScale(1.3) elif x == 4: renderedPeice.setZ(renderedPeice.getZ() + 3.2999999999999998) renderedPeice.setScale(1.45) else: renderedPeice.setZ(renderedPeice.getZ() + 3.2999999999999998) renderedPeice.hide() self.playerTagList = self.playerTags.getChildren() for x in playerPos: if x != 0: self.playerTagList[playerPos.index(x)].setColor(self.playerColors[x - 1]) self.playerTagList[playerPos.index(x)].show() continue def cleanPlayerTags(self): for x in self.playerTagList: x.removeNode() self.playerTagList = [] self.playerTags.removeNode() def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.finish() rotation = 0 if self.seatPos > 2: if self.playerNum == 1: rotation = 180 elif self.playerNum == 2: rotation = -120 elif self.playerNum == 3: rotation = -60 elif self.playerNum == 4: rotation = 0 elif self.playerNum == 5: rotation = 60 elif self.playerNum == 6: rotation = 120 elif self.playerNum == 1: rotation = 0 elif self.playerNum == 2: rotation = 60 elif self.playerNum == 3: rotation = 120 elif self.playerNum == 4: rotation = 180 elif self.playerNum == 5: rotation = -120 elif self.playerNum == 6: rotation = -60 if rotation == 60 or rotation == -60: int = LerpHprInterval(self.boardNode, 2.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) elif rotation == 120 or rotation == -120: int = LerpHprInterval(self.boardNode, 3.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) else: int = LerpHprInterval(self.boardNode, 4.2000000000000002, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) int.start() def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.cleanPlayerTags() def enterGameOver(self): pass def exitGameOver(self): pass def exitWaitCountdown(self): self._DistributedChineseCheckers__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton(relief = None, text = TTLocalizer.ChineseCheckersGetUpButton, text_fg = (1, 1, 0.65000000000000002, 1), text_pos = (0, -0.23000000000000001), text_scale = 0.80000000000000004, image = (self.upButton, self.downButton, self.rolloverButton), image_color = (1, 0, 0, 1), image_scale = (20, 1, 11), pos = (0.92000000000000004, 0, 0.40000000000000002), scale = 0.14999999999999999, command = lambda self = self: self.exitButtonPushed()) def enableScreenText(self): defaultPos = (-0.80000000000000004, -0.40000000000000002) if self.playerNum == 1: message = TTLocalizer.ChineseCheckersColorG color = self.playerColors[0] elif self.playerNum == 2: message = TTLocalizer.ChineseCheckersColorY color = self.playerColors[1] elif self.playerNum == 3: message = TTLocalizer.ChineseCheckersColorP color = self.playerColors[2] elif self.playerNum == 4: message = TTLocalizer.ChineseCheckersColorB color = self.playerColors[3] elif self.playerNum == 5: message = TTLocalizer.ChineseCheckersColorPink color = self.playerColors[4] elif self.playerNum == 6: message = TTLocalizer.ChineseCheckersColorR color = self.playerColors[5] else: message = TTLocalizer.ChineseCheckersColorO color = Vec4(0.0, 0.0, 0.0, 1.0) defaultPos = (-0.80000000000000004, -0.40000000000000002) self.screenText = OnscreenText(text = message, pos = defaultPos, scale = 0.10000000000000001, fg = color, align = TextNode.ACenter, mayChange = 1) def enableStartButton(self): self.startButton = DirectButton(relief = None, text = TTLocalizer.ChineseCheckersStartButton, text_fg = (1, 1, 0.65000000000000002, 1), text_pos = (0, -0.23000000000000001), text_scale = 0.59999999999999998, image = (self.upButton, self.downButton, self.rolloverButton), image_color = (1, 0, 0, 1), image_scale = (20, 1, 11), pos = (0.92000000000000004, 0, 0.10000000000000001), scale = 0.14999999999999999, command = lambda self = self: self.startButtonPushed()) def enableLeaveButton(self): self.leaveButton = DirectButton(relief = None, text = TTLocalizer.ChineseCheckersQuitButton, text_fg = (1, 1, 0.65000000000000002, 1), text_pos = (0, -0.13), text_scale = 0.5, image = (self.upButton, self.downButton, self.rolloverButton), image_color = (1, 0, 0, 1), image_scale = (20, 1, 11), pos = (0.92000000000000004, 0, 0.40000000000000002), scale = 0.14999999999999999, command = lambda self = self: self.exitButtonPushed()) def enableTurnScreenText(self, player): self.yourTurnBlinker.finish() playerOrder = [ 1, 4, 2, 5, 3, 6] message1 = TTLocalizer.ChineseCheckersIts if self.turnText != None: self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) elif player == 1: message2 = TTLocalizer.ChineseCheckersGreenTurn color = self.playerColors[0] elif player == 2: message2 = TTLocalizer.ChineseCheckersYellowTurn color = self.playerColors[1] elif player == 3: message2 = TTLocalizer.ChineseCheckersPurpleTurn color = self.playerColors[2] elif player == 4: message2 = TTLocalizer.ChineseCheckersBlueTurn color = self.playerColors[3] elif player == 5: message2 = TTLocalizer.ChineseCheckersPinkTurn color = self.playerColors[4] elif player == 6: message2 = TTLocalizer.ChineseCheckersRedTurn color = self.playerColors[5] self.turnText = OnscreenText(text = message1 + message2, pos = (-0.80000000000000004, -0.5), scale = 0.091999999999999998, fg = color, align = TextNode.ACenter, mayChange = 1) if player == self.playerNum: self.yourTurnBlinker = Sequence() self.yourTurnBlinker.append(LerpScaleInterval(self.turnText, 0.59999999999999998, 1.0449999999999999, 1)) self.yourTurnBlinker.append(LerpScaleInterval(self.turnText, 0.59999999999999998, 1, 1.0449999999999999)) self.yourTurnBlinker.loop() def startButtonPushed(self): self.sendUpdate('requestBegin') self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate('requestExit') def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True: mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() pickedObj = self.myHandler.getEntry(0).getIntoNodePath() pickedObj = pickedObj.getNetTag('GamePeiceLocator') if pickedObj: self.handleClicked(int(pickedObj)) def handleClicked(self, index): self.sound = Sequence(SoundInterval(self.clickSound)) if self.moveList == []: if index not in self.mySquares: return None self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False self.blinker = Sequence() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.69999999999999996, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.69999999999999996, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() elif self.board.squareList[index].getState() == self.playerNum: for x in self.moveList: self.locatorList[x].setColor(1, 1, 1, 1) self.locatorList[x].hide() self.blinker.finish() self.blinker = Sequence() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.69999999999999996, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.69999999999999996, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() self.locatorList[self.moveList[0]].setColor(self.playerColor) self.locatorList[self.moveList[0]].show() self.moveList = [] self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False elif self.board.squareList[index].getState() != 0: return None elif len(self.moveList) == 1 and self.board.squareList[index].getState() == 0: if index in self.board.squareList[self.moveList[0]].getAdjacent(): for x in self.nonOpposingPositions: if index in x: return None continue self.moveList.append(index) self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() if len(self.moveList) >= 1: if index == self.moveList[len(self.moveList) - 1]: for x in self.nonOpposingPositions: if index in x: return None continue if self.existsLegalJumpsFrom(index) == True: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() elif self.checkLegalMove(self.board.getSquare(self.moveList[len(self.moveList) - 1]), self.board.getSquare(index)) == True: if index not in self.board.squareList[self.moveList[len(self.moveList) - 1]].getAdjacent(): for x in self.nonOpposingPositions: if self.existsLegalJumpsFrom(index) == False: if index in x: return None index in x self.moveList.append(index) self.locatorList[index].setColor(self.playerColor - self.tintConstant - self.ghostConstant) self.locatorList[index].show() self.sound.start() if self.existsLegalJumpsFrom(index) == False: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False def existsLegalJumpsFrom(self, index): for x in self.board.squareList[index].getAdjacent(): if x == None: continue if x in self.moveList: continue if self.board.getState(x) == 0: continue if self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)] == None: continue if self.board.getState(self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)]) == 0 and self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)] not in self.moveList: return True continue return False def checkLegalMove(self, firstSquare, secondSquare): if secondSquare.getNum() in firstSquare.getAdjacent(): return True else: for x in firstSquare.getAdjacent(): if x == None: continue if self.board.squareList[x].getState() == 0: continue if self.board.squareList[x].getAdjacent()[firstSquare.getAdjacent().index(x)] == secondSquare.getNum(): return True continue return False def d_requestMove(self, moveList): self.sendUpdate('requestMove', [ moveList]) def setGameState(self, tableState, moveList): if moveList != []: self.animatePeice(tableState, moveList) else: self.updateGameState(tableState) def updateGameState(self, squares): self.board.setStates(squares) self.mySquares = [] messenger.send('wakeup') for x in range(121): self.locatorList[x].clearColor() owner = self.board.squareList[x].getState() if owner == self.playerNum: self.mySquares.append(x) if owner == 0: self.locatorList[x].hide() else: self.locatorList[x].show() if owner == 1: self.locatorList[x].setColor(self.playerColors[0]) continue if owner == 2: self.locatorList[x].setColor(self.playerColors[1]) continue if owner == 3: self.locatorList[x].setColor(self.playerColors[2]) continue if owner == 4: self.locatorList[x].setColor(self.playerColors[3]) continue if owner == 5: self.locatorList[x].setColor(self.playerColors[4]) continue if owner == 6: self.locatorList[x].setColor(self.playerColors[5]) continue self.mySquares.sort() self.checkForWin() def animatePeice(self, tableState, moveList): messenger.send('wakeup') gamePeiceForAnimation = loader.loadModel('phase_6/models/golf/checker_marble.bam') gamePeiceForAnimation.setColor(self.locatorList[moveList[0]].getColor()) gamePeiceForAnimation.reparentTo(self.boardNode) gamePeiceForAnimation.setPos(self.locatorList[moveList[0]].getPos()) self.locatorList[moveList[0]].hide() checkersPeiceTrack = Sequence() length = len(moveList) for x in range(length - 1): checkersPeiceTrack.append(Parallel(SoundInterval(self.moveSound), ProjectileInterval(gamePeiceForAnimation, endPos = self.locatorList[moveList[x + 1]].getPos(), duration = 0.5))) checkersPeiceTrack.append(Func(gamePeiceForAnimation.removeNode)) checkersPeiceTrack.append(Func(self.updateGameState, tableState)) checkersPeiceTrack.start() def checkForWin(self): if self.playerNum == 1: if self.mySquares == self.startingPositions[3]: self.sendUpdate('requestWin', []) elif self.playerNum == 2: if self.mySquares == self.startingPositions[4]: self.sendUpdate('requestWin', []) elif self.playerNum == 3: if self.mySquares == self.startingPositions[5]: self.sendUpdate('requestWin', []) elif self.playerNum == 4: if self.mySquares == self.startingPositions[0]: self.sendUpdate('requestWin', []) elif self.playerNum == 5: if self.mySquares == self.startingPositions[1]: self.sendUpdate('requestWin', []) elif self.playerNum == 6: if self.mySquares == self.startingPositions[2]: self.sendUpdate('requestWin', []) def announceWin(self, avId): self.fsm.request('gameOver') def doRandomMove(self): if len(self.moveList) >= 2: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.playSound = Sequence(SoundInterval(self.knockSound)) self.playSound.start() else: import random as random move = [] foundLegal = False self.blinker.pause() self.numRandomMoves += 1 while not foundLegal: x = random.randint(0, 9) for y in self.board.getAdjacent(self.mySquares[x]): if y != None and self.board.getState(y) == 0: for zz in self.nonOpposingPositions: if y not in zz: move.append(self.mySquares[x]) move.append(y) foundLegal = True break continue break continue if move == []: pass 1 playSound = Sequence(SoundInterval(self.knockSound)) playSound.start() self.d_requestMove(move) self.moveList = [] self.isMyTurn = False if self.numRandomMoves >= 5: self.exitButtonPushed() def doNothing(self): pass
class CogdoMazeGuiManager: def __init__(self, maze, bossCode): self.maze = maze self.root = NodePath('CogdoMazeGui') self.root.reparentTo(aspect2d) self.mazeMapGui = CogdoMazeMapGui(self.maze.collisionTable) if bossCode is not None: self._bossGui = CogdoMazeBossGui(bossCode) else: self._bossGui = None self._memoGui = CogdoMemoGui(self.root) self._memoGui.posNextToLaffMeter() self._presentGuiIval = None self._presentTimerIval = None self._hud = CogdoMazeHud() self._timer = None self._initMessageDisplay() return def _initTimer(self): self._timer = ToontownTimer() self._timer.hide() self._timer.posInTopRightCorner() def _initMessageDisplay(self): self.messageDisplay = CogdoGameMessageDisplay( 'CogdoMazeMessageDisplay', self.root, pos=Globals.MessageLabelPos) def destroy(self): ToontownIntervals.cleanup('present_gui') ToontownIntervals.cleanup('present_timer') ToontownIntervals.cleanup('present_memo') self._hud.destroy() self._hud = None self._memoGui.destroy() self._memoGui = None if self._bossGui is not None: self._bossGui.destroy() self._bossGui = None self.messageDisplay.destroy() self.messageDisplay = None self.destroyMazeMap() self.destroyTimer() if self._presentGuiIval: self._presentGuiIval.pause() self._presentGuiIval = None if self._presentTimerIval: self._presentTimerIval.pause() self._presentTimerIval = None return def destroyMazeMap(self): if hasattr(self, 'mazeMapGui') and self.mazeMapGui is not None: self.mazeMapGui.destroy() del self.mazeMapGui return def destroyTimer(self): if self._timer is not None: self._timer.stop() self._timer.destroy() self._timer = None return def showPickupCounter(self): ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._memoGui, 'present_memo')) def startGame(self, firstMessage): self._presentGuiIval = ToontownIntervals.start( Sequence(ToontownIntervals.getPresentGuiIval(self._bossGui, '', startPos=(0, 0, -0.15)), Func(self.mazeMapGui.show), ToontownIntervals.getPulseLargerIval( self.mazeMapGui, '', scale=self.mazeMapGui.getScale()), Func(self.setMessage, firstMessage), name='present_gui')) def hideMazeMap(self): self.mazeMapGui.hide() def showBossGui(self): if self._bossGui is not None: self._bossGui.show() return def hideBossGui(self): if self._bossGui is not None: self._bossGui.hide() return def revealMazeMap(self): self.mazeMapGui.revealAll() def hideLock(self, lockIndex): self.mazeMapGui.hideLock(lockIndex) def showTimer(self, duration, timerExpiredCallback=None): if self._timer is None: self._initTimer() self._timer.setTime(duration) self._timer.countdown(duration, timerExpiredCallback) self._presentTimerIval = ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._timer, 'present_timer', startPos=(0, 0, 0.35))) return def hideTimer(self): if hasattr(self, 'timer') and self._timer is not None: self._timer.hide() self._timer.stop() return def setMessage(self, text, color=None, transition='fade'): self.messageDisplay.updateMessage(text, color, transition) def setMessageTemporary(self, text, time=3.0): self.messageDisplay.showMessageTemporarily(text, time) def clearMessage(self): self.messageDisplay.updateMessage('') def setPickupCount(self, count): self._memoGui.setCount(count) def showBossCode(self, bossIndex): self._bossGui.showNumber(bossIndex) def showBossHit(self, bossIndex): self._bossGui.showHit(bossIndex) def showQuestArrow(self, toon, target, offset): self._hud.showQuestArrow(toon, target, offset) def hideQuestArrow(self): self._hud.hideQuestArrow()
class DistributedChineseCheckers(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, "DistributedChineseCheckers") DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel( "phase_6/models/golf/checker_game.bam") self.boardNode.reparentTo(self) #self.boardNode.setZ(2.85) #self.boardNode.setZ(3.5) #self.boardNode.setZ(0.3) #self.boardNode.setZ(self.getZ()) self.board = ChineseCheckersBoard() self.playerTags = render.attachNewNode("playerTags") self.playerTagList = [] #game variables self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None ###self.playerTags = [None, None, None, None, None, None #Mouse picking required stuff self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel( "phase_3.5/models/gui/inventory_gui") self.upButton = self.buttonModels.find("**//InventoryButtonUp") self.downButton = self.buttonModels.find("**/InventoryButtonDown") self.rolloverButton = self.buttonModels.find( "**/InventoryButtonRollover") self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() #[0] GREEN [1] YELLOW [2] PURPLE [3] BLUE [4] PINK [5] RED self.playerColors = [ Vec4(0, .90, 0, 1), Vec4(.9, .9, 0, 1), Vec4(.45, 0, .45, 1), Vec4(.2, .4, .8, 1), Vec4(1, .45, 1, 1), Vec4(.8, 0, 0, 1) ] self.tintConstant = Vec4(.25, .25, .25, 0) self.ghostConstant = Vec4(0, 0, 0, .5) #starting positions are used to check and see if a player has gone into #his opposing players starting position, thus to tell if he won. self.startingPositions = [ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 23, 24, 25, 35, 36, 46], [65, 75, 76, 86, 87, 88, 98, 99, 100, 101], [111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [74, 84, 85, 95, 96, 97, 107, 108, 109, 110], [19, 20, 21, 22, 32, 33, 34, 44, 45, 55] ] self.nonOpposingPositions = [] self.knockSound = base.loadSfx("phase_5/audio/sfx/GUI_knock_1.mp3") self.clickSound = base.loadSfx( "phase_3/audio/sfx/GUI_balloon_popup.mp3") self.moveSound = base.loadSfx("phase_6/audio/sfx/CC_move.mp3") self.accept('stoppedAsleep', self.handleSleep) #base.setCellsAvailable(base.leftCells + #[base.bottomCells[0]], 0) #base.setCellsAvailable(base.bottomCells,0) ####################### #Fsm and State Data from direct.fsm import ClassicFSM, State self.fsm = ClassicFSM.ClassicFSM( 'ChineseCheckers', [ State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin']) ], # Initial State 'waitingToBegin', # Final State 'waitingToBegin', ) ######################### #Set up the Board Locators ## x = self.boardNode.find("**/locators") #set up the locator list so we can mess with it self.locatorList = x.getChildren() #tag the locators for "picking" ingame #also add colision spheres for movement tempList = [] for x in range(0, 121): self.locatorList[x].setTag("GamePeiceLocator", "%d" % x) tempList.append(self.locatorList[x].attachNewNode( CollisionNode("picker%d" % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, .115)) for z in self.locatorList: y = loader.loadModel("phase_6/models/golf/checker_marble.bam") z.setColor(0, 0, 0, 0) y.reparentTo(z) #y.show() #y.hide() def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: # Fix for strange state #TEMP until i find the cause self.seatPos = self.table.tableState.index( base.localAvatar.doId) self.playerTags.setPos(self.getPos()) def handleSleep(self, task=None): if self.fsm.getCurrentState().getName() == "waitingToBegin": self.exitButtonPushed() if task != None: task.done #task.done ########## ##setTableDoId (required broadcast ram) # #Upon construction, sets local pointer to the table, as well as #sets the pointer on the table to itself. #This is necessary to handle events that occur on the table, not #particularly inside of any one game. ### def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) #self.table.tempCheckers.hide() #self.boardNode.setP(self.table.getP()) ######### ##Disable/Delete #Must be sure to remove/delete any buttons, screen text #that may be on the screen in the event of a chosen ( or asynchrinous ) #disable or deletion - Code redundance here is necessary #being that "disable" is called upon server crash, and delete is #called upon zone exit ### def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.cleanPlayerTags() ###self.table = None def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None self.cleanPlayerTags() del self.playerTags del self.playerTagList self.playerSeats = None self.yourTurnBlinker.finish() ########## ##Timer Functions #setTimer (broadcast ram required) #setTurnTimer(broadcast ram required) # #setTimer() controlls the timer for game begin, which upon its timout #calls the startButton. # #turnTimer() does just that # #Important to note that both timers run on the same clockNode. ########## def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): #print "TIMEREND! ", timerEnd if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState( ).getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if (timeLeft > 0 and timerEnd != 0): if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(-.74, 0, -0.20) if self.isMyTurn: self.clockNode.countdown(timeLeft, self.doRandomMove) else: self.clockNode.countdown(timeLeft, self.doNothing) self.clockNode.show() ########### ##Game start(broadcast) and Send Turn (broadcast ram) # #IMPORTANT - 255 is the Uint8 sent to the player when a game starts #to dictate to him that a game is beginning and he is labeled as an observer #for that game - this affects the visual queues for his player color ect. ########## def gameStart(self, playerNum): if playerNum != 255: #observer value self.playerNum = playerNum self.playerColor = self.playerColors[playerNum - 1] self.moveCameraForGame() playerPos = playerNum - 1 import copy self.nonOpposingPositions = copy.deepcopy(self.startingPositions) if playerPos == 0: self.nonOpposingPositions.pop(0) self.opposingPositions = self.nonOpposingPositions.pop(2) elif playerPos == 1: self.nonOpposingPositions.pop(1) self.opposingPositions = self.nonOpposingPositions.pop(3) elif playerPos == 2: self.nonOpposingPositions.pop(2) self.opposingPositions = self.nonOpposingPositions.pop(4) elif playerPos == 3: self.nonOpposingPositions.pop(3) self.opposingPositions = self.nonOpposingPositions.pop(0) elif playerPos == 4: self.nonOpposingPositions.pop(4) self.opposingPositions = self.nonOpposingPositions.pop(1) elif playerPos == 5: self.nonOpposingPositions.pop(5) self.opposingPositions = self.nonOpposingPositions.pop(2) self.fsm.request('playing') def sendTurn(self, playersTurn): self.playersTurnBlinker.finish() if self.fsm.getCurrentState().getName() == 'playing': #print "GETTING HERE!", playersTurn - 1, " LENGTH!!!" , self.playerTagList #self.playerTagList if self.playerSeats == None: self.sendUpdate("requestSeatPositions", []) else: if playersTurn == self.playerNum: self.isMyTurn = True self.enableTurnScreenText(playersTurn) self.playersTurnBlinker = Sequence() origColor = self.playerColors[playersTurn - 1] self.playersTurnBlinker.append( LerpColorInterval( self.playerTagList[self.playerSeats.index( playersTurn)], .4, origColor - self.tintConstant - self.ghostConstant, origColor)) self.playersTurnBlinker.append( LerpColorInterval( self.playerTagList[self.playerSeats.index( playersTurn)], .4, origColor, origColor - self.tintConstant - self.ghostConstant)) self.playersTurnBlinker.loop() def announceSeatPositions(self, playerPos): #print "ANNOUNCESEATPOSITIONS!", playerPos self.playerSeats = playerPos for x in range(6): pos = self.table.seats[x].getPos(render) renderedPeice = loader.loadModel( "phase_6/models/golf/checker_marble.bam") #renderedPeice.setColor(self.playerColors[x-1]) renderedPeice.reparentTo(self.playerTags) renderedPeice.setPos(pos) renderedPeice.setScale(1.5) if x == 1: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.setScale(1.3) elif x == 4: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.setScale(1.45) else: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.hide() self.playerTagList = self.playerTags.getChildren() for x in playerPos: if x != 0: self.playerTagList[playerPos.index(x)].setColor( self.playerColors[x - 1]) self.playerTagList[playerPos.index(x)].show() #if game is already going #if self.fsm.getCurrentState().getName() == 'playing': # if not self.playersTurnBlinker.isPlaying(): # self.playersTurnBlinker = Sequence() # origColor = self.playerColors[playersTurn-1] # self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], .4, origColor - self.tintConstant - self.ghostConstant, origColor)) # self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], .4,origColor, origColor - self.tintConstant - self.ghostConstant)) # self.playersTurnBlinker.loop() def cleanPlayerTags(self): for x in self.playerTagList: x.removeNode() self.playerTagList = [] self.playerTags.removeNode() ########## ##Move camera # #To make camera movement not seem weird (turning 270 degrees example) #Must check the clients orientation between the seatPos and his current H # so that he turns the least possible amount for the camera orientation # # ########## def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.finish() rotation = 0 if self.seatPos > 2: if self.playerNum == 1: rotation = 180 elif self.playerNum == 2: rotation = -120 elif self.playerNum == 3: rotation = -60 elif self.playerNum == 4: rotation = 0 elif self.playerNum == 5: rotation = 60 elif self.playerNum == 6: rotation = 120 else: if self.playerNum == 1: rotation = 0 elif self.playerNum == 2: rotation = 60 elif self.playerNum == 3: rotation = 120 elif self.playerNum == 4: rotation = 180 elif self.playerNum == 5: rotation = -120 elif self.playerNum == 6: rotation = -60 #print self.boardNode.getHpr() # int = LerpHprInterval(camera, 3,Vec3(camera.getH(),camera.getP(),rotation), camera.getHpr()) #self.table.tempCheckers.hide() if rotation == 60 or rotation == -60: int = LerpHprInterval( self.boardNode, 2.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) elif rotation == 120 or rotation == -120: int = LerpHprInterval( self.boardNode, 3.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) else: int = LerpHprInterval( self.boardNode, 4.2, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) #self.table.tempCheckers.setHpr( Vec3(rotation, self.table.tempCheckers.getP(), self.table.tempCheckers.getR())) int.start() ##################### #FSM Stuff ### def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.cleanPlayerTags() def enterGameOver(self): pass def exitGameOver(self): pass ################################################## # Button Functions and Text ### def exitWaitCountdown(self): self.__disableCollisions() self.ignore("trolleyExitButton") self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersGetUpButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.4), scale=0.15, command=lambda self=self: self.exitButtonPushed(), ) return def enableScreenText(self): defaultPos = (-.80, -0.40) if self.playerNum == 1: message = TTLocalizer.ChineseCheckersColorG color = self.playerColors[0] elif self.playerNum == 2: message = TTLocalizer.ChineseCheckersColorY color = self.playerColors[1] elif self.playerNum == 3: message = TTLocalizer.ChineseCheckersColorP color = self.playerColors[2] elif self.playerNum == 4: message = TTLocalizer.ChineseCheckersColorB color = self.playerColors[3] elif self.playerNum == 5: message = TTLocalizer.ChineseCheckersColorPink color = self.playerColors[4] elif self.playerNum == 6: message = TTLocalizer.ChineseCheckersColorR color = self.playerColors[5] else: message = TTLocalizer.ChineseCheckersColorO color = Vec4(0.0, 0.0, 0.0, 1.0) defaultPos = (-.80, -0.40) self.screenText = OnscreenText(text=message, pos=defaultPos, scale=0.10, fg=color, align=TextNode.ACenter, mayChange=1) def enableStartButton(self): self.startButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersStartButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.6, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.1), scale=0.15, command=lambda self=self: self.startButtonPushed(), ) return def enableLeaveButton(self): self.leaveButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersQuitButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.13), text_scale=0.5, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.4), scale=0.15, command=lambda self=self: self.exitButtonPushed(), ) return def enableTurnScreenText(self, player): self.yourTurnBlinker.finish() playerOrder = [1, 4, 2, 5, 3, 6] message1 = TTLocalizer.ChineseCheckersIts if (self.turnText != None): self.turnText.destroy() #print "player ---",player #print "playerNum --" ,self.playerNum if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) else: if player == 1: message2 = TTLocalizer.ChineseCheckersGreenTurn color = self.playerColors[0] elif player == 2: message2 = TTLocalizer.ChineseCheckersYellowTurn color = self.playerColors[1] elif player == 3: message2 = TTLocalizer.ChineseCheckersPurpleTurn color = self.playerColors[2] elif player == 4: message2 = TTLocalizer.ChineseCheckersBlueTurn color = self.playerColors[3] elif player == 5: message2 = TTLocalizer.ChineseCheckersPinkTurn color = self.playerColors[4] elif player == 6: message2 = TTLocalizer.ChineseCheckersRedTurn color = self.playerColors[5] self.turnText = OnscreenText(text=message1 + message2, pos=(-0.80, -0.50), scale=0.092, fg=color, align=TextNode.ACenter, mayChange=1) if player == self.playerNum: self.yourTurnBlinker = Sequence() self.yourTurnBlinker.append( LerpScaleInterval(self.turnText, .6, 1.045, 1)) self.yourTurnBlinker.append( LerpScaleInterval(self.turnText, .6, 1, 1.045)) self.yourTurnBlinker.loop() #This function is called either if the player clicks on it (to begin a game) #or if the game begin timer runs out. (timer is in sync with server so results should be # + or - ~ 1 second def startButtonPushed(self): self.sendUpdate("requestBegin") self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate("requestExit") ########## #Mouse Picking/clicking operations # # #These functions handle all of the mous clicking functions #Its best to look through the code for comments for it to make #the most sense. # #The self.blinker that is referenced in these functions, is a cosmetic #colorLerp that gives the player a visual feedback as to what checkers peice #he has (currently) selected. ########## def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True: #cant pick stuff if its not your turn mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() #get the closest Object pickedObj = self.myHandler.getEntry(0).getIntoNodePath() #will return the INT for the locator node closest parent pickedObj = pickedObj.getNetTag("GamePeiceLocator") if pickedObj: #make sure something actually was "picked" self.handleClicked(int(pickedObj)) def handleClicked(self, index): #self.inOpposing = False self.sound = Sequence(SoundInterval( self.clickSound)) #You clicked something play the click sound #First Moved Square if self.moveList == []: #check if owned if not index in self.mySquares: return self.moveList.append(index) #put this on the movelist if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False #Start blinking the new "active" peice self.blinker = Sequence() self.blinker.append( LerpColorInterval(self.locatorList[index], .7, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append( LerpColorInterval(self.locatorList[index], .7, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() else: #Check if the square clicked is not open, if so break out not legal #If the Player Clicks on one of his peices after an array of clicking new peices #will reset his "move" and start a new movelist if self.board.squareList[index].getState() == self.playerNum: for x in self.moveList: #clear the already selected Nodes back to white self.locatorList[x].setColor(1, 1, 1, 1) self.locatorList[x].hide() #Blinker is the color lerp for the peice "flashing" - need to stop the flashing of the old one self.blinker.finish() self.blinker = Sequence() self.blinker.append( LerpColorInterval(self.locatorList[index], .7, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append( LerpColorInterval(self.locatorList[index], .7, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() #Swap back to the original peice #set the original node back to playercolor self.locatorList[self.moveList[0]].setColor(self.playerColor) self.locatorList[self.moveList[0]].show() self.moveList = [] self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False elif self.board.squareList[index].getState() != 0: return #do nothing because he clicked someone elses peice else: #Check for Explicit adjacent move if len(self.moveList ) == 1 and self.board.squareList[index].getState() == 0: #print "I AM OUTSIDE" if index in self.board.squareList[ self.moveList[0]].getAdjacent(): #print "I AM INSIDE" for x in self.nonOpposingPositions: if index in x: return #You cannot end a move in a non opposing players square self.moveList.append(index) self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() #Check for mid series jumps stoppage #print len(self.moveList), len(self.moveList)-1 if len(self.moveList) >= 1: if index == self.moveList[ len(self.moveList) - 1]: #you clicked the same thing TWICE for x in self.nonOpposingPositions: if index in x: return #Will force you to jump out ... if self.existsLegalJumpsFrom(index) == True: self.blinker.finish() #self.locatorList[index].setColor(self.playerColor - self.tintConstant) #self.locatorList[index].show() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() #Check for Normal jump #Also check if its a 'finishing jump' #Therefore no jumps possible after it ###print "CHECK LEGAL JUMP!", self.checkLegalMove(self.board.getSquare(self.moveList[len(self.moveList)-1]), self.board.getSquare(index)) == True elif self.checkLegalMove( self.board.getSquare( self.moveList[len(self.moveList) - 1]), self.board.getSquare(index)) == True: #this is the part that adds moves to a series of jumps ## #This if statement is an Explicit check to make sure that #the clicked peice, after a series of jumps #is not in the middle jump adjacent, This results in a #bug due to the way ive detected "legal moves" #but this explicit check should fix that. if not index in self.board.squareList[self.moveList[ len(self.moveList) - 1]].getAdjacent(): for x in self.nonOpposingPositions: #print " LEGAL JUMPS FROM! ", self.existsLegalJumpsFrom(index) if self.existsLegalJumpsFrom(index) == False: if index in x: return #He tried to JUMP into non opposing players startPos => Illegal self.moveList.append(index) #ghostConstant here is a small alpha offset to give it a transparent look #tintConstant makes the peice a bit darker (necessary when ghosting) self.locatorList[index].setColor( self.playerColor - self.tintConstant - self.ghostConstant) self.locatorList[index].show() self.sound.start() if self.existsLegalJumpsFrom(index) == False: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False ################################################################## # Legal Move Request/Checker # (COPY PASTED FROM AI) # (Logic here reflects the (NEXT) move not a series of moves, but still #Checks the validity of two different move peices # #This is probably the most complicated as well as most important part #of the chinese checkers code. To completely understand the CheckLegalMoves, #get out a peice of paper and try to DRAW out what the logic is doing, ill do #my best to explain it. # # #Players request moves as a list of Uint8s (already should be verified on the client side) #but since players are cheating bastards, we check on the server. Basically, how the logic works #is it takes pairs one at a time and checks for a legal move between the two, ect and traverses the #list. # #A move is Legal if (it is adjacent to its last move) - in a checkerboard adjacent is stored in a list #of 6 integers representing the other squares (see ChineseCheckerBoard.py) # #board.squareList[x].getAdjacent() visually looks like this # 1 2 # 0 x 3 where those values [ ] are integers to adjacent squares. # 5 4 # # If a adjacent square does not exist on the board, say the first square only has two adjacent, # the squares in the adjacent list are set to None # #A move is also legal if there exists a legal Jump from A to B. the logic here is difficult to #express without a picture, but for instance, say A is jumping to B # # 1 2 1 2 # 0 A 3 B 3 # 5 4 5 6 # # You check all of A's adjacents, and check the index of that \ # particular one (of A's adjacents) that it sits in A, #if that is equal to B, there is a legal jump, if no one is found the move is illegal. # # EX. board.squareList[A].adjacent[3] == (some number to the left of b) # board.squareList[that number].getAdjacent[self.board.squareList[A].index(some number) # # in this case it equals B (draw it out, Trust me it helps) #### def existsLegalJumpsFrom(self, index): for x in self.board.squareList[index].getAdjacent(): if x == None: pass elif x in self.moveList: pass elif self.board.getState(x) == 0: pass elif self.board.squareList[x].getAdjacent( )[self.board.squareList[index].getAdjacent().index(x)] == None: pass elif self.board.getState(self.board.squareList[x].getAdjacent( )[self.board.squareList[index].getAdjacent().index( x)]) == 0 and not (self.board.squareList[x].getAdjacent()[ self.board.squareList[index].getAdjacent().index(x)] ) in self.moveList: return True return False def checkLegalMove(self, firstSquare, secondSquare): if secondSquare.getNum() in firstSquare.getAdjacent(): return True else: for x in firstSquare.getAdjacent(): if x == None: pass elif self.board.squareList[x].getState() == 0: pass else: #print " FIRSTSQUARE ADJACENT AND X -- " , firstSquare.getAdjacent(), " X == " , x #print "Xs Adjacent and its Index", self.board.squareList[x].getAdjacent(), " INDEX == " , firstSquare.getAdjacent().index(x) if (self.board.squareList[x].getAdjacent()[ firstSquare.getAdjacent().index(x)] ) == secondSquare.getNum(): return True return False def d_requestMove(self, moveList): self.sendUpdate('requestMove', [moveList]) ########## ##setGameState (required broadcast ram) # #This is the function that handles the moves made after a move is parsed by the AI #and deemed to be valid # #If moveList is the empty List, then the player is asynchronously joining the game, (OBSERVING) #and just wants the board state. # #otherwise there is a series of jumps (or jump) that needs to be parsed and animated, then #consequently setting the board state # #after every setGameState, the client checks to see the current #Status of his peices (checkForWin), if he belives he won, he requests it to the server ######### def setGameState(self, tableState, moveList): if moveList != []: self.animatePeice(tableState, moveList) else: self.updateGameState(tableState) def updateGameState(self, squares): self.board.setStates(squares) self.mySquares = [] messenger.send('wakeup') for x in range(121): self.locatorList[x].clearColor() owner = self.board.squareList[x].getState() if owner == self.playerNum: self.mySquares.append(x) if owner == 0: self.locatorList[x].hide() else: self.locatorList[x].show() if owner == 1: self.locatorList[x].setColor(self.playerColors[0]) elif owner == 2: self.locatorList[x].setColor(self.playerColors[1]) elif owner == 3: self.locatorList[x].setColor(self.playerColors[2]) elif owner == 4: self.locatorList[x].setColor(self.playerColors[3]) elif owner == 5: self.locatorList[x].setColor(self.playerColors[4]) elif owner == 6: self.locatorList[x].setColor(self.playerColors[5]) self.mySquares.sort() self.checkForWin() def animatePeice(self, tableState, moveList): messenger.send('wakeup') gamePeiceForAnimation = loader.loadModel( "phase_6/models/golf/checker_marble.bam") gamePeiceForAnimation.setColor( self.locatorList[moveList[0]].getColor()) gamePeiceForAnimation.reparentTo(self.boardNode) gamePeiceForAnimation.setPos(self.locatorList[moveList[0]].getPos()) self.locatorList[moveList[0]].hide() checkersPeiceTrack = Sequence() length = len(moveList) for x in range(length - 1): checkersPeiceTrack.append( Parallel( SoundInterval(self.moveSound), ProjectileInterval( gamePeiceForAnimation, endPos=self.locatorList[moveList[x + 1]].getPos(), duration=.5))) checkersPeiceTrack.append(Func(gamePeiceForAnimation.removeNode)) checkersPeiceTrack.append(Func(self.updateGameState, tableState)) checkersPeiceTrack.start() def checkForWin(self): if self.playerNum == 1: if (self.mySquares == self.startingPositions[3]): self.sendUpdate('requestWin', []) elif self.playerNum == 2: if (self.mySquares == self.startingPositions[4]): self.sendUpdate('requestWin', []) elif self.playerNum == 3: if (self.mySquares == self.startingPositions[5]): self.sendUpdate('requestWin', []) elif self.playerNum == 4: if (self.mySquares == self.startingPositions[0]): self.sendUpdate('requestWin', []) elif self.playerNum == 5: if (self.mySquares == self.startingPositions[1]): self.sendUpdate('requestWin', []) elif self.playerNum == 6: if (self.mySquares == self.startingPositions[2]): self.sendUpdate('requestWin', []) def announceWin(self, avId): self.fsm.request('gameOver') ########### ##doRandomMove # #If a clients move Timer runs out, it will calculate a random move for him #after 3 random moves, it kicks the client out of the game by pushing the #"get up" button for him. ########### def doRandomMove(self): if len(self.moveList) >= 2: self.blinker.finish() #self.locatorList[index].setColor(self.playerColor - self.tintConstant) #self.locatorList[index].show() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.playSound = Sequence(SoundInterval(self.knockSound)) self.playSound.start() else: import random move = [] foundLegal = False self.blinker.pause() self.numRandomMoves += 1 ###self.blinker.finish() while not foundLegal: x = random.randint(0, 9) for y in self.board.getAdjacent(self.mySquares[x]): if y != None and self.board.getState(y) == 0: for zz in self.nonOpposingPositions: if not y in zz: move.append(self.mySquares[x]) move.append(y) foundLegal = True break break if move == []: pass #current flaw in the logic, but shouldnt really ever happen #though on live it might #print "random move is empty" playSound = Sequence(SoundInterval(self.knockSound)) playSound.start() self.d_requestMove(move) self.moveList = [] self.isMyTurn = False if (self.numRandomMoves >= 5): self.exitButtonPushed() def doNothing(self): pass
class CogdoFlyingGuiManager: ClearMessageDisplayEventName = 'ClearMessageDisplayEvent' EagleTargetingLocalPlayerEventName = 'EagleTargetingLocalPlayerEvent' EagleAttackingLocalPlayerEventName = 'EagleAttackingLocalPlayerEvent' FirstPressOfCtrlEventName = 'FirstPressOfCtrlEvent' PickedUpFirstPropellerEventName = 'PickedUpFirstPropellerEvent' InvulnerableEventName = 'InvulnerableEvent' StartRunningOutOfTimeMusicEventName = 'StartRunningOutOfTimeEvent' def __init__(self, level): self._level = level self.root = NodePath('CogdoFlyingGui') self.root.reparentTo(aspect2d) self.root.stash() self._initTimer() self._initHud() self._initMessageDisplay() self.sentTimeRunningOutMessage = False self._refuelGui = CogdoFlyingFuelGui(self.root) self._progressGui = CogdoFlyingProgressGui(self.root, self._level) def _initHud(self): self._memoGui = CogdoMemoGui(self.root) self._memoGui.posNextToLaffMeter() def _initTimer(self): self._timer = ToontownTimer() self._timer.reparentTo(self.root) self._timer.posInTopRightCorner() def _initMessageDisplay(self): audioMgr = base.cogdoGameAudioMgr sound = audioMgr.createSfx('popupHelpText') self._messageDisplay = CogdoGameMessageDisplay('CogdoFlyingMessageDisplay', self.root, sfx=sound) def destroyTimer(self): if self._timer is not None: self._timer.stop() self._timer.destroy() self._timer = None return def onstage(self): self.root.unstash() self._refuelGui.hide() self._progressGui.hide() def presentProgressGui(self): ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._progressGui, 'present_progress_gui')) def presentRefuelGui(self): ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._refuelGui, 'present_fuel_gui')) def presentTimerGui(self): ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._timer, 'present_timer_gui')) def presentMemoGui(self): ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._memoGui, 'present_memo_gui')) def offstage(self): self.root.stash() self._refuelGui.hide() self._progressGui.hide() self.hideTimer() def getTimeLeft(self): return Globals.Gameplay.SecondsUntilGameOver - self._timer.getElapsedTime() def isTimeRunningOut(self): return self.getTimeLeft() < Globals.Gameplay.TimeRunningOutSeconds def startTimer(self, duration, timerExpiredCallback = None, keepHidden = False): if self._timer is None: self._initTimer() self._timer.setTime(duration) self._timer.countdown(duration, timerExpiredCallback) if keepHidden: self.hideTimer() else: self.showTimer() return def stopTimer(self): if hasattr(self, '_timer') and self._timer is not None: self.hideTimer() self._timer.stop() return def showTimer(self): self._timer.show() def hideTimer(self): self._timer.hide() def forceTimerDone(self): if self._timer.countdownTask != None: self._timer.countdownTask.duration = 0 return def showRefuelGui(self): self._refuelGui.show() def hideRefuelGui(self): self._refuelGui.hide() def setMessage(self, text, color = None, transition = 'fade'): self._messageDisplay.updateMessage(text, color, transition) def setTemporaryMessage(self, text, duration = 3.0, color = None): self._messageDisplay.showMessageTemporarily(text, duration, color) def setFuel(self, fuel): self._refuelGui.setFuel(fuel) def resetBlades(self): self._refuelGui.resetBlades() def setBlades(self, fuelState): self._refuelGui.setBlades(fuelState) def bladeLost(self): self._refuelGui.bladeLost() def setPropellerSpinRate(self, newRate): self._refuelGui.setPropellerSpinRate(newRate) def setMemoCount(self, score): self._memoGui.setCount(score) def addToonToProgressMeter(self, toon): self._progressGui.addToon(toon) def removeToonFromProgressMeter(self, toon): self._progressGui.removeToon(toon) def update(self): if self.isTimeRunningOut() and not self.sentTimeRunningOutMessage: messenger.send(CogdoFlyingGuiManager.StartRunningOutOfTimeMusicEventName) self.sentTimeRunningOutMessage = True self._refuelGui.update() self._progressGui.update() def destroy(self): ToontownIntervals.cleanup('present_fuel_gui') ToontownIntervals.cleanup('present_timer_gui') ToontownIntervals.cleanup('present_memo_gui') ToontownIntervals.cleanup('present_progress_gui') self._refuelGui.destroy() self._refuelGui = None self._memoGui.destroy() self._memoGui = None self._progressGui.destroy() self._progressGui = None self.destroyTimer() self._messageDisplay.destroy() self._messageDisplay = None self.root.removeNode() self.root = None return
class CogdoFlyingGuiManager: ClearMessageDisplayEventName = 'ClearMessageDisplayEvent' EagleTargetingLocalPlayerEventName = 'EagleTargetingLocalPlayerEvent' EagleAttackingLocalPlayerEventName = 'EagleAttackingLocalPlayerEvent' FirstPressOfCtrlEventName = 'FirstPressOfCtrlEvent' PickedUpFirstPropellerEventName = 'PickedUpFirstPropellerEvent' InvulnerableEventName = 'InvulnerableEvent' StartRunningOutOfTimeMusicEventName = 'StartRunningOutOfTimeEvent' def __init__(self, level): self._level = level self.root = NodePath('CogdoFlyingGui') self.root.reparentTo(aspect2d) self.root.stash() self._initTimer() self._initHud() self._initMessageDisplay() self.sentTimeRunningOutMessage = False self._refuelGui = CogdoFlyingFuelGui(self.root) self._progressGui = CogdoFlyingProgressGui(self.root, self._level) def _initHud(self): self._memoGui = CogdoMemoGui(self.root) self._memoGui.posNextToLaffMeter() def _initTimer(self): self._timer = ToontownTimer() self._timer.reparentTo(self.root) self._timer.posInTopRightCorner() def _initMessageDisplay(self): audioMgr = base.cogdoGameAudioMgr sound = audioMgr.createSfx('popupHelpText') self._messageDisplay = CogdoGameMessageDisplay( 'CogdoFlyingMessageDisplay', self.root, sfx=sound) def destroyTimer(self): if self._timer is not None: self._timer.stop() self._timer.destroy() self._timer = None return def onstage(self): self.root.unstash() self._refuelGui.hide() self._progressGui.hide() def presentProgressGui(self): ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._progressGui, 'present_progress_gui')) def presentRefuelGui(self): ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._refuelGui, 'present_fuel_gui')) def presentTimerGui(self): ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._timer, 'present_timer_gui')) def presentMemoGui(self): ToontownIntervals.start( ToontownIntervals.getPresentGuiIval(self._memoGui, 'present_memo_gui')) def offstage(self): self.root.stash() self._refuelGui.hide() self._progressGui.hide() self.hideTimer() def getTimeLeft(self): return Globals.Gameplay.SecondsUntilGameOver - self._timer.getElapsedTime( ) def isTimeRunningOut(self): return self.getTimeLeft() < Globals.Gameplay.TimeRunningOutSeconds def startTimer(self, duration, timerExpiredCallback=None, keepHidden=False): if self._timer is None: self._initTimer() self._timer.setTime(duration) self._timer.countdown(duration, timerExpiredCallback) if keepHidden: self.hideTimer() else: self.showTimer() return def stopTimer(self): if hasattr(self, '_timer') and self._timer is not None: self.hideTimer() self._timer.stop() return def showTimer(self): self._timer.show() def hideTimer(self): self._timer.hide() def forceTimerDone(self): if self._timer.countdownTask != None: self._timer.countdownTask.duration = 0 return def showRefuelGui(self): self._refuelGui.show() def hideRefuelGui(self): self._refuelGui.hide() def setMessage(self, text, color=None, transition='fade'): self._messageDisplay.updateMessage(text, color, transition) def setTemporaryMessage(self, text, duration=3.0, color=None): self._messageDisplay.showMessageTemporarily(text, duration, color) def setFuel(self, fuel): self._refuelGui.setFuel(fuel) def resetBlades(self): self._refuelGui.resetBlades() def setBlades(self, fuelState): self._refuelGui.setBlades(fuelState) def bladeLost(self): self._refuelGui.bladeLost() def setPropellerSpinRate(self, newRate): self._refuelGui.setPropellerSpinRate(newRate) def setMemoCount(self, score): self._memoGui.setCount(score) def addToonToProgressMeter(self, toon): self._progressGui.addToon(toon) def removeToonFromProgressMeter(self, toon): self._progressGui.removeToon(toon) def update(self): if self.isTimeRunningOut() and not self.sentTimeRunningOutMessage: messenger.send( CogdoFlyingGuiManager.StartRunningOutOfTimeMusicEventName) self.sentTimeRunningOutMessage = True self._refuelGui.update() self._progressGui.update() def destroy(self): ToontownIntervals.cleanup('present_fuel_gui') ToontownIntervals.cleanup('present_timer_gui') ToontownIntervals.cleanup('present_memo_gui') ToontownIntervals.cleanup('present_progress_gui') self._refuelGui.destroy() self._refuelGui = None self._memoGui.destroy() self._memoGui = None self._progressGui.destroy() self._progressGui = None self.destroyTimer() self._messageDisplay.destroy() self._messageDisplay = None self.root.removeNode() self.root = None return
class DistributedPicnicBasket(DistributedObject.DistributedObject): seatState = Enum('Empty, Full, Eating') notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPicnicBasket') def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.localToonOnBoard = 0 self.seed = 0 self.random = None self.picnicCountdownTime = base.config.GetFloat('picnic-countdown-time', ToontownGlobals.PICNIC_COUNTDOWN_TIME) self.picnicBasketTrack = None self.fsm = ClassicFSM.ClassicFSM('DistributedTrolley', [ State.State('off', self.enterOff, self.exitOff, [ 'waitEmpty', 'waitCountdown']), State.State('waitEmpty', self.enterWaitEmpty, self.exitWaitEmpty, [ 'waitCountdown']), State.State('waitCountdown', self.enterWaitCountdown, self.exitWaitCountdown, [ 'waitEmpty'])], 'off', 'off') self.fsm.enterInitialState() self._DistributedPicnicBasket__toonTracks = { } def generate(self): DistributedObject.DistributedObject.generate(self) self.loader = self.cr.playGame.hood.loader self.foodLoader = [ 'phase_6/models/golf/picnic_sandwich.bam', 'phase_6/models/golf/picnic_apple.bam', 'phase_6/models/golf/picnic_cupcake.bam', 'phase_6/models/golf/picnic_chocolate_cake.bam'] self.fullSeat = [] self.food = [] for i in range(4): self.food.append(None) self.fullSeat.append(self.seatState.Empty) self.picnicItem = 0 def announceGenerate(self): self.picnicTable = self.loader.geom.find('**/*picnic_table_' + str(self.tableNumber)) self.picnicTableSphereNodes = [] self.numSeats = 4 self.seats = [] self.jumpOffsets = [] self.basket = None for i in range(self.numSeats): self.seats.append(self.picnicTable.find('**/*seat%d' % (i + 1))) self.jumpOffsets.append(self.picnicTable.find('**/*jumpOut%d' % (i + 1))) self.tablecloth = self.picnicTable.find('**/basket_locator') DistributedObject.DistributedObject.announceGenerate(self) for i in range(self.numSeats): self.picnicTableSphereNodes.append(self.seats[i].attachNewNode(CollisionNode('picnicTable_sphere_%d_%d' % (self.getDoId(), i)))) self.picnicTableSphereNodes[i].node().addSolid(CollisionSphere(0, 0, 0, 2)) self.tableclothSphereNode = self.tablecloth.attachNewNode(CollisionNode('tablecloth_sphere')) self.tableclothSphereNode.node().addSolid(CollisionSphere(0, 0, -1, 4)) angle = self.startingHpr[0] angle -= 90 radAngle = deg2Rad(angle) unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0) unitVec *= 30.0 self.endPos = self.startingPos + unitVec dist = Vec3(self.endPos - self.enteringPos).length() wheelAngle = (dist / 0.5 * 1.3999999999999999 * math.pi) * 360 self.seatNumber = 0 self.clockNode = ToontownTimer() self.clockNode.setPos(1.1599999999999999, 0, -0.82999999999999996) self.clockNode.setScale(0.29999999999999999) self.clockNode.hide() def disable(self): DistributedObject.DistributedObject.disable(self) self.fsm.request('off') self.clearToonTracks() for i in range(self.numSeats): del self.picnicTableSphereNodes[0] del self.picnicTableSphereNodes self.notify.debug('Deleted self loader ' + str(self.getDoId())) self.picnicTable.removeNode() self.picnicBasketTrack = None def delete(self): self.notify.debug('Golf kart getting deleted: %s' % self.getDoId()) DistributedObject.DistributedObject.delete(self) del self.fsm def setState(self, state, seed, timestamp): self.seed = seed if not self.random: self.random = RandomNumGen.RandomNumGen(seed) self.fsm.request(state, [ globalClockDelta.localElapsedTime(timestamp)]) def handleEnterPicnicTableSphere(self, i, collEntry): self.seatNumber = i self.notify.debug('Entering Picnic Table Sphere.... %s' % self.getDoId()) self.loader.place.detectedPicnicTableSphereCollision(self) def handleEnterPicnicTable(self, i): toon = base.localAvatar self.sendUpdate('requestBoard', [ i]) def fillSlot0(self, avId): self.fillSlot(0, avId) def fillSlot1(self, avId): self.fillSlot(1, avId) def fillSlot2(self, avId): self.fillSlot(2, avId) def fillSlot3(self, avId): self.fillSlot(3, avId) def fillSlot(self, index, avId): self.notify.debug('fill Slot: %d for %d' % (index, avId)) if avId == 0: pass 1 self.fullSeat[index] = self.seatState.Full if avId == base.localAvatar.getDoId(): self.clockNode.show() if index == 0 or index == 3: side = -1 else: side = 1 if hasattr(self.loader.place, 'trolley'): self.loader.place.trolley.fsm.request('boarding', [ self.tablecloth, side]) else: self.notify.warning('fillSlot no trolley in place') self.localToonOnBoard = 1 if avId == base.localAvatar.getDoId(): if hasattr(self.loader.place, 'trolley'): self.loader.place.trolley.fsm.request('boarded') self.loader.place.trolley.exitButton.hide() if self.cr.doId2do.has_key(avId): toon = self.cr.doId2do[avId] toon.stopSmooth() toon.wrtReparentTo(self.tablecloth) sitStartDuration = toon.getDuration('sit-start') jumpTrack = self.generateToonJumpTrack(toon, index) track = Sequence(jumpTrack, Func(toon.setAnimState, 'Sit', 1.0)) self.notify.debug('### fillSlot: fullSeat = %s' % self.fullSeat) if self.fullSeat.count(0) == 3: self.notify.debug('### fillSlot: adding basketAppear') if self.picnicBasketTrack: self.picnicBasketTrack.finish() waitDuration = track.getDuration() self.picnicBasketTrack = Sequence(Wait(waitDuration), self.generateBasketAppearTrack()) self.picnicBasketTrack.start() track.append(self.generateFoodAppearTrack(index)) track.append(Sequence(Func(self.clearToonTrack, avId), name = toon.uniqueName('fillTrolley'), autoPause = 1)) if avId == base.localAvatar.getDoId(): if hasattr(self.loader.place, 'trolley'): track.append(Func(self.loader.place.trolley.exitButton.show)) track.delayDelete = DelayDelete.DelayDelete(toon, 'PicnicBasket.fillSlot') self.storeToonTrack(avId, track) track.start() def emptySlot0(self, avId, timestamp): self.emptySlot(0, avId, timestamp) def emptySlot1(self, avId, timestamp): self.emptySlot(1, avId, timestamp) def emptySlot2(self, avId, timestamp): self.emptySlot(2, avId, timestamp) def emptySlot3(self, avId, timestamp): self.emptySlot(3, avId, timestamp) def notifyToonOffTrolley(self, toon): toon.setAnimState('neutral', 1.0) if hasattr(base, 'localAvatar') and toon == base.localAvatar: if hasattr(self.loader.place, 'trolley'): self.loader.place.trolley.handleOffTrolley() self.localToonOnBoard = 0 else: toon.startSmooth() def emptySlot(self, index, avId, timestamp): def emptySeat(index): self.notify.debug('### seat %s now empty' % index) self.fullSeat[index] = self.seatState.Empty if avId == 0: pass 1 if avId == 1: self.fullSeat[index] = self.seatState.Empty track = Sequence(self.generateFoodDisappearTrack(index)) self.notify.debug('### empty slot - unexpetected: fullSeat = %s' % self.fullSeat) if self.fullSeat.count(0) == 4: self.notify.debug('### empty slot - unexpected: losing basket') if self.picnicBasketTrack: self.picnicBasketTrack.finish() waitDuration = track.getDuration() self.picnicBasketTrack = Sequence(Wait(waitDuration), self.generateBasketDisappearTrack()) self.picnicBasketTrack.start() track.start() else: self.fullSeat[index] = self.seatState.Empty if self.cr.doId2do.has_key(avId): if avId == base.localAvatar.getDoId(): if self.clockNode: self.clockNode.hide() toon = self.cr.doId2do[avId] toon.stopSmooth() sitStartDuration = toon.getDuration('sit-start') jumpOutTrack = self.generateToonReverseJumpTrack(toon, index) track = Sequence(jumpOutTrack) track.append(self.generateFoodDisappearTrack(index)) self.notify.debug('### empty slot: fullSeat = %s' % self.fullSeat) if self.fullSeat.count(0) == 4: self.notify.debug('### empty slot: losing basket') if self.picnicBasketTrack: self.picnicBasketTrack.finish() waitDuration = track.getDuration() self.picnicBasketTrack = Sequence(Wait(waitDuration), self.generateBasketDisappearTrack()) self.picnicBasketTrack.start() track.append(Sequence(Func(self.notifyToonOffTrolley, toon), Func(self.clearToonTrack, avId), Func(self.doneExit, avId), Func(emptySeat, index), name = toon.uniqueName('emptyTrolley'), autoPause = 1)) track.delayDelete = DelayDelete.DelayDelete(toon, 'PicnicBasket.emptySlot') self.storeToonTrack(avId, track) track.start() def rejectBoard(self, avId): self.loader.place.trolley.handleRejectBoard() def _DistributedPicnicBasket__enableCollisions(self): for i in range(self.numSeats): self.accept('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTableSphere, [ i]) self.accept('enterPicnicTableOK_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTable, [ i]) self.picnicTableSphereNodes[i].setCollideMask(ToontownGlobals.WallBitmask) def _DistributedPicnicBasket__disableCollisions(self): for i in range(self.numSeats): self.ignore('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i)) self.ignore('enterPicnicTableOK_%d_%d' % (self.getDoId(), i)) for i in range(self.numSeats): self.picnicTableSphereNodes[i].setCollideMask(BitMask32(0)) def enterOff(self): pass def exitOff(self): pass def enterWaitEmpty(self, ts): self._DistributedPicnicBasket__enableCollisions() def exitWaitEmpty(self): self._DistributedPicnicBasket__disableCollisions() def enterWaitCountdown(self, ts): self._DistributedPicnicBasket__enableCollisions() self.accept('trolleyExitButton', self.handleExitButton) self.clockNode.countdown(self.picnicCountdownTime, self.handleExitButton) def handleExitButton(self): self.sendUpdate('requestExit') self.clockNode.hide() def exitWaitCountdown(self): self._DistributedPicnicBasket__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def getStareAtNodeAndOffset(self): return (self.tablecloth, Point3(0, 0, 4)) def storeToonTrack(self, avId, track): self.clearToonTrack(avId) self._DistributedPicnicBasket__toonTracks[avId] = track def clearToonTrack(self, avId): oldTrack = self._DistributedPicnicBasket__toonTracks.get(avId) if oldTrack: oldTrack.pause() DelayDelete.cleanupDelayDeletes(oldTrack) del self._DistributedPicnicBasket__toonTracks[avId] def clearToonTracks(self): keyList = [] for key in self._DistributedPicnicBasket__toonTracks: keyList.append(key) for key in keyList: if self._DistributedPicnicBasket__toonTracks.has_key(key): self.clearToonTrack(key) continue def doneExit(self, avId): if avId == base.localAvatar.getDoId(): self.sendUpdate('doneExit') def setPosHpr(self, x, y, z, h, p, r): self.startingPos = Vec3(x, y, z) self.enteringPos = Vec3(x, y, z - 10) self.startingHpr = Vec3(h, 0, 0) def setTableNumber(self, tn): self.tableNumber = tn def generateToonJumpTrack(self, av, seatIndex): av.pose('sit', 47) hipOffset = av.getHipsParts()[2].getPos(av) def getToonJumpTrack(av, seatIndex): def getJumpDest(av = av, node = self.tablecloth): dest = Vec3(self.tablecloth.getPos(av.getParent())) seatNode = self.picnicTable.find('**/seat' + str(seatIndex + 1)) dest += seatNode.getPos(self.tablecloth) dna = av.getStyle() dest -= hipOffset if seatIndex == 2 or seatIndex == 3: dest.setY(dest.getY() + 2 * hipOffset.getY()) dest.setZ(dest.getZ() + 0.20000000000000001) return dest def getJumpHpr(av = av, node = self.tablecloth): hpr = self.seats[seatIndex].getHpr(av.getParent()) angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX()) hpr.setX(angle) return hpr toonJumpTrack = Parallel(ActorInterval(av, 'jump'), Sequence(Wait(0.42999999999999999), Parallel(LerpHprInterval(av, hpr = getJumpHpr, duration = 0.90000000000000002), ProjectileInterval(av, endPos = getJumpDest, duration = 0.90000000000000002)))) return toonJumpTrack def getToonSitTrack(av): toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit')) return toonSitTrack toonJumpTrack = getToonJumpTrack(av, seatIndex) toonSitTrack = getToonSitTrack(av) jumpTrack = Sequence(Parallel(toonJumpTrack, Sequence(Wait(1), toonSitTrack)), Func(av.wrtReparentTo, self.tablecloth)) return jumpTrack def generateToonReverseJumpTrack(self, av, seatIndex): self.notify.debug('av.getH() = %s' % av.getH()) def getToonJumpTrack(av, destNode): def getJumpDest(av = av, node = destNode): dest = node.getPos(self.tablecloth) dest += self.jumpOffsets[seatIndex].getPos(self.tablecloth) return dest def getJumpHpr(av = av, node = destNode): hpr = node.getHpr(av.getParent()) hpr.setX(hpr.getX() + 180) angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX()) hpr.setX(angle) return hpr toonJumpTrack = Parallel(ActorInterval(av, 'jump'), Sequence(Wait(0.10000000000000001), Parallel(ProjectileInterval(av, endPos = getJumpDest, duration = 0.90000000000000002)))) return toonJumpTrack toonJumpTrack = getToonJumpTrack(av, self.tablecloth) jumpTrack = Sequence(toonJumpTrack, Func(av.loop, 'neutral'), Func(av.wrtReparentTo, render)) return jumpTrack def generateBasketAppearTrack(self): if self.basket == None: self.basket = loader.loadModel('phase_6/models/golf/picnic_basket.bam') self.basket.setScale(0.10000000000000001) basketTrack = Sequence(Func(self.basket.show), SoundInterval(globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node = self.basket), Func(self.basket.reparentTo, self.tablecloth), Func(self.basket.setPos, 0, 0, 0.20000000000000001), Func(self.basket.setHpr, 45, 0, 0), Func(self.basket.wrtReparentTo, render), Func(self.basket.setShear, 0, 0, 0), Sequence(LerpScaleInterval(self.basket, scale = Point3(1.1000000000000001, 1.1000000000000001, 0.10000000000000001), duration = 0.20000000000000001), LerpScaleInterval(self.basket, scale = Point3(1.6000000000000001, 1.6000000000000001, 0.20000000000000001), duration = 0.10000000000000001), LerpScaleInterval(self.basket, scale = Point3(1.0, 1.0, 0.40000000000000002), duration = 0.10000000000000001), LerpScaleInterval(self.basket, scale = Point3(1.5, 1.5, 2.5), duration = 0.20000000000000001), LerpScaleInterval(self.basket, scale = Point3(2.5, 2.5, 1.5), duration = 0.10000000000000001), LerpScaleInterval(self.basket, scale = Point3(2.0, 2.0, 2.0), duration = 0.10000000000000001), Func(self.basket.wrtReparentTo, self.tablecloth), Func(self.basket.setPos, 0, 0, 0))) return basketTrack def generateBasketDisappearTrack(self): if not self.basket: return Sequence() pos = self.basket.getPos() pos.addZ(-1) basketTrack = Sequence(LerpScaleInterval(self.basket, scale = Point3(2.0, 2.0, 1.8), duration = 0.10000000000000001), LerpScaleInterval(self.basket, scale = Point3(1.0, 1.0, 2.5), duration = 0.10000000000000001), LerpScaleInterval(self.basket, scale = Point3(2.0, 2.0, 0.5), duration = 0.20000000000000001), LerpScaleInterval(self.basket, scale = Point3(0.5, 0.5, 1.0), duration = 0.10000000000000001), LerpScaleInterval(self.basket, scale = Point3(1.1000000000000001, 1.1000000000000001, 0.10000000000000001), duration = 0.10000000000000001), LerpScaleInterval(self.basket, scale = Point3(0.10000000000000001, 0.10000000000000001, 0.10000000000000001), duration = 0.20000000000000001), SoundInterval(globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node = self.basket), Wait(0.20000000000000001), LerpPosInterval(self.basket, pos = pos, duration = 0.20000000000000001), Func(self.basket.hide)) return basketTrack def generateFoodAppearTrack(self, seat): if self.fullSeat[seat] == self.seatState.Full: self.notify.debug('### food appear: self.fullSeat = %s' % self.fullSeat) if not self.food[seat]: self.food[seat] = loader.loadModel(self.random.choice(self.foodLoader)) self.notify.debug('### food appear: self.food = %s' % self.food) self.food[seat].setScale(0.10000000000000001) self.food[seat].reparentTo(self.tablecloth) self.food[seat].setPos(self.seats[seat].getPos(self.tablecloth)[0] / 2, self.seats[seat].getPos(self.tablecloth)[1] / 2, 0) foodTrack = Sequence(Func(self.food[seat].show), SoundInterval(globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node = self.food[seat]), Func(self.food[seat].reparentTo, self.tablecloth), Func(self.food[seat].setHpr, 45, 0, 0), Func(self.food[seat].wrtReparentTo, render), Func(self.food[seat].setShear, 0, 0, 0), Sequence(LerpScaleInterval(self.food[seat], scale = Point3(1.1000000000000001, 1.1000000000000001, 0.10000000000000001), duration = 0.20000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(1.6000000000000001, 1.6000000000000001, 0.20000000000000001), duration = 0.10000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(1.0, 1.0, 0.40000000000000002), duration = 0.10000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(1.5, 1.5, 2.5), duration = 0.20000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(2.5, 2.5, 1.5), duration = 0.10000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(2.0, 2.0, 2.0), duration = 0.10000000000000001), Func(self.food[seat].wrtReparentTo, self.tablecloth))) return foodTrack else: return Sequence() def generateFoodDisappearTrack(self, seat): if not self.food[seat]: return Sequence() pos = self.food[seat].getPos() pos.addZ(-1.0) foodTrack = Sequence(LerpScaleInterval(self.food[seat], scale = Point3(2.0, 2.0, 1.8), duration = 0.10000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(1.0, 1.0, 2.5), duration = 0.10000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(2.0, 2.0, 0.5), duration = 0.20000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(0.5, 0.5, 1.0), duration = 0.10000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(1.1000000000000001, 1.1000000000000001, 0.10000000000000001), duration = 0.10000000000000001), LerpScaleInterval(self.food[seat], scale = Point3(0.10000000000000001, 0.10000000000000001, 0.10000000000000001), duration = 0.20000000000000001), SoundInterval(globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node = self.food[seat]), Wait(0.20000000000000001), LerpPosInterval(self.food[seat], pos = pos, duration = 0.20000000000000001), Func(self.food[seat].hide)) return foodTrack def destroy(self, node): node.removeNode() node = None self.basket.removeNode() self.basket = None for food in self.food: food.removeNode() self.food = None self.clockNode.removeNode() del self.clockNode self.clockNode = None def setPicnicDone(self): if self.localToonOnBoard: if hasattr(self.loader.place, 'trolley'): self.loader.place.trolley.fsm.request('final') self.loader.place.trolley.fsm.request('start') self.localToonOnBoard = 0 messenger.send('picnicDone')
class DistributedCheckers(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, "DistributedCheckers") DistributedNode.DistributedNode.__init__(self,cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel("phase_6/models/golf/regular_checker_game.bam") self.boardNode.reparentTo(self) self.board = CheckersBoard() #game variables self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.moveList = [] self.mySquares = [] self.myKings = [] self.isRotated = False #Mouse picking required stuff self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel("phase_3.5/models/gui/inventory_gui") self.upButton = self.buttonModels.find("**//InventoryButtonUp") self.downButton = self.buttonModels.find("**/InventoryButtonDown") self.rolloverButton = self.buttonModels.find("**/InventoryButtonRollover") self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() #[0] GREEN [1] YELLOW [2] PURPLE [3] BLUE [4] PINK [5] RED self.playerColors = [ Vec4(0,0,1,1), Vec4(0,1,0,1) ] self.tintConstant = Vec4(.25,.25,.25,.5) self.ghostConstant = Vec4(0,0,0,.8) #starting positions are used to check and see if a player has gone into #his opposing players starting position, thus to tell if he won. self.startingPositions = [[0,1,2,3,4,5,6,7,8,9,10,11], [20,21,22,23,24,25,26,27,28,29,30,31]] self.knockSound = base.loadSfx("phase_5/audio/sfx/GUI_knock_1.mp3") self.clickSound = base.loadSfx("phase_3/audio/sfx/GUI_balloon_popup.mp3") self.moveSound = base.loadSfx("phase_6/audio/sfx/CC_move.mp3") self.accept('stoppedAsleep', self.handleSleep) ####################### #Fsm and State Data # from direct.fsm import ClassicFSM,State self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing','gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin'])], # Initial State 'waitingToBegin', # Final State 'waitingToBegin', ) ######################### #Set up the Board Locators ## x = self.boardNode.find("**/locator*") #set up the locator list so we can mess with it self.locatorList = x.getChildren() #tag the locators for "picking" ingame #also add colision spheres for movement tempList = [] for x in range(0,32): self.locatorList[x].setTag("GamePeiceLocator", "%d" % x) tempList.append(self.locatorList[x].attachNewNode(CollisionNode("picker%d" % x))) tempList[x].node().addSolid(CollisionSphere(0,0,0,.39)) for z in self.locatorList: y = loader.loadModel("phase_6/models/golf/regular_checker_piecewhite.bam") y.find("**/checker_k*").hide() zz = loader.loadModel("phase_6/models/golf/regular_checker_pieceblack.bam") zz.find("**/checker_k*").hide() y.reparentTo(z) y.hide() zz.reparentTo(z) zz.hide() def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: # Fix for strange state #TEMP until i find the cause self.seatPos = self.table.tableState.index(base.localAvatar.doId) def handleSleep(self, task = None): if self.fsm.getCurrentState().getName() == "waitingToBegin": self.exitButtonPushed() if task != None: task.done #task.done ########## ##setTableDoId (required broadcast ram) # #Upon construction, sets local pointer to the table, as well as #sets the pointer on the table to itself. #This is necessary to handle events that occur on the table, not #particularly inside of any one game. ### def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) ######### ##Disable/Delete #Must be sure to remove/delete any buttons, screen text #that may be on the screen in the event of a chosen ( or asynchrinous ) #disable or deletion - Code redundance here is necessary #being that "disable" is called upon server crash, and delete is #called upon zone exit ### def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton : self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None ########## ##Timer Functions #setTimer (broadcast ram required) #setTurnTimer(broadcast ram required) # #setTimer() controlls the timer for game begin, which upon its timout #calls the startButton. # #turnTimer() does just that # #Important to note that both timers run on the same clockNode. ########## def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState().getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime() ) if(timeLeft > 0 and timerEnd != 0): if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime() ) if timeLeft > 0: self.clockNode.setPos(-.74, 0, -0.20) if self.isMyTurn: self.clockNode.countdown(timeLeft, self.doNothing) else: self.clockNode.countdown(timeLeft, self.doNothing) self.clockNode.show() ########### ##Game start(broadcast) and Send Turn (broadcast ram) # #IMPORTANT - 255 is the Uint8 sent to the player when a game starts #to dictate to him that a game is beginning and he is labeled as an observer #for that game - this affects the visual queues for his player color ect. ########## def gameStart(self, playerNum): if playerNum != 255: #observer value self.playerNum = playerNum if self.playerNum == 1: self.playerColorString = "white" else: self.playerColorString = "black" self.playerColor = self.playerColors[playerNum-1] self.moveCameraForGame() self.fsm.request('playing') def sendTurn(self,playersTurn): if self.fsm.getCurrentState().getName() == 'playing': if playersTurn == self.playerNum: self.isMyTurn = True self.enableTurnScreenText(playersTurn) def illegalMove(self): self.exitButtonPushed() ########## ##Move camera # #To make camera movement not seem weird (turning 270 degrees example) #Must check the clients orientation between the seatPos and his current H # so that he turns the least possible amount for the camera orientation # # ########## def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.finish() rotation = 0 if self.seatPos >2: if self.playerNum == 1: rotation = 180 elif self.playerNum == 2: rotation = 0 for x in self.locatorList: x.setH(180) self.isRotated = True else: if self.playerNum == 1: rotation = 0 elif self.playerNum == 2: rotation = 180 for x in self.locatorList: x.setH(180) self.isRotated = True int = LerpHprInterval(self.boardNode, 4.2, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) int.start() ##################### #FSM Stuff ### def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton : self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() def enterPlaying(self): self.inGame = True self.enableScreenText() #print "IM IN PLAYING?????!?!?!" if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() def enterGameOver(self): pass def exitGameOver(self): pass ################################################## # Button Functions and Text ### def exitWaitCountdown(self): self.__disableCollisions() self.ignore("trolleyExitButton") self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton( relief = None, text = TTLocalizer.ChineseCheckersGetUpButton, text_fg = (1, 1, 0.65, 1), text_pos = (0, -.23), text_scale = 0.8, image = (self.upButton, self.downButton, self.rolloverButton), image_color = (1, 0, 0, 1), image_scale = (20, 1, 11), pos = (.92, 0, 0.4), scale = 0.15, command = lambda self=self: self.exitButtonPushed(), ) return def enableScreenText(self): defaultPos = (-.80, -0.40) if self.playerNum == 1: message = TTLocalizer.CheckersColorWhite color = Vec4(1,1,1,1) elif self.playerNum == 2: message = TTLocalizer.CheckersColorBlack color = Vec4(0,0,0,1) else: message = TTLocalizer.CheckersObserver color = Vec4(0,0,0,1) defaultPos = (-.80, -0.40) self.screenText = OnscreenText(text = message, pos = defaultPos, scale = 0.10,fg=color,align=TextNode.ACenter,mayChange=1) def enableStartButton(self): self.startButton = DirectButton( relief = None, text = TTLocalizer.ChineseCheckersStartButton, text_fg = (1, 1, 0.65, 1), text_pos = (0, -.23), text_scale = 0.6, image = (self.upButton, self.downButton, self.rolloverButton), image_color = (1, 0, 0, 1), image_scale = (20, 1, 11), pos = (.92, 0, 0.1), scale = 0.15, command = lambda self=self: self.startButtonPushed(), ) return def enableLeaveButton(self): self.leaveButton = DirectButton( relief = None, text = TTLocalizer.ChineseCheckersQuitButton, text_fg = (1, 1, 0.65, 1), text_pos = (0, -.13), text_scale = 0.5, image = (self.upButton, self.downButton, self.rolloverButton), image_color = (1, 0, 0, 1), image_scale = (20, 1, 11), pos = (.92, 0, 0.4), scale = 0.15, command = lambda self=self: self.exitButtonPushed(), ) return def enableTurnScreenText(self,player): playerOrder = [1,4,2,5,3,6] message1 = TTLocalizer.CheckersIts if(self.turnText != None): self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0,0,0,1) else: if player == 1: message2 = TTLocalizer.CheckersWhiteTurn color = (1,1,1,1) elif player == 2: message2 = TTLocalizer.CheckersBlackTurn color = (0,0,0,1) self.turnText = OnscreenText(text = message1+message2, pos = (-0.80,-0.50), scale = 0.092,fg=color,align=TextNode.ACenter,mayChange=1) #This function is called either if the player clicks on it (to begin a game) #or if the game begin timer runs out. (timer is in sync with server so results should be # + or - ~ 1 second def startButtonPushed(self): self.sendUpdate("requestBegin") self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate("requestExit") ########## #Mouse Picking/clicking operations # # #These functions handle all of the mous clicking functions #Its best to look through the code for comments for it to make #the most sense. # #The self.blinker that is referenced in these functions, is a cosmetic #colorLerp that gives the player a visual feedback as to what checkers peice #he has (currently) selected. ########## def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True : #cant pick stuff if its not your turn mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode,mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries()#get the closest Object pickedObj = self.myHandler.getEntry(0).getIntoNodePath() #will return the INT for the locator node closest parent pickedObj = pickedObj.getNetTag("GamePeiceLocator") if pickedObj: #make sure something actually was "picked" self.handleClicked(int(pickedObj)) def handleClicked(self, index): self.sound = Sequence( SoundInterval(self.clickSound)) #You clicked something play the click sound #First Moved Square if self.moveList == []: #check if owned if not index in self.mySquares and not index in self.myKings: return #you clicked on nothing or an opposing peice self.moveList.append(index) #put this on the movelist type = self.board.squareList[index].getState() if type == 3 or type == 4: self.moverType = "king" else: self.moverType = "normal" #Start blinking the new "active" peice self.blinker = Sequence() col = self.locatorList[index].getColor() self.blinker.append(LerpColorInterval(self.locatorList[index], .7,self.tintConstant, col)) self.blinker.append(LerpColorInterval(self.locatorList[index], .7, col ,self.tintConstant)) self.blinker.loop() self.sound.start() else: if index in self.mySquares or index in self.myKings: #selected a new peice for x in self.moveList: #the nodes from self.locatorList[x].setColor(1,1,1,1) self.locatorList[x].hide() self.blinker.finish() self.blinker = Sequence() col = self.locatorList[index].getColor() self.blinker.append(LerpColorInterval(self.locatorList[index], .7,self.tintConstant, col)) self.blinker.append(LerpColorInterval(self.locatorList[index], .7, col ,self.tintConstant)) self.blinker.loop() self.sound.start() #Swap back to the original peice #set the original node back to playercolor #self.locatorList[self.moveList[0]].setColor(self.playerColor) self.locatorList[self.moveList[0]].show() self.moveList = [] self.moveList.append(index) type = self.board.squareList[index].getState() if type == 3 or type == 4: self.moverType = "king" else: self.moverType = "normal" else: #item is either BLANK or the opposing players (checkJump will validate if it is opposing players) self.currentMove = index lastItem = self.board.squareList[self.moveList[len(self.moveList)-1]] thisItem = self.board.squareList[index] if self.mustJump == True: if lastItem.getNum() == index: #selected the same item twice self.blinker.finish() self.d_requestMove(self.moveList) self.isMyTurn = False self.moveList= [] return #print "CHECK LEGAL JUMP", self.checkLegalJump(lastItem, thisItem, self.moverType), "TYPE == ", self.moverType if self.checkLegalJump(lastItem, thisItem, self.moverType) == True: #There is a Legal Jump #ghostConstant here is a small alpha offset to give it a transparent look #tintConstant makes the peice a bit darker (necessary when ghosting) col = self.locatorList[index].getColor() self.locatorList[index].show() self.sound.start() if self.existsLegalJumpsFrom(index, self.moverType) == False: #No more Series of jumps => Commit the move self.moveList.append(index) self.blinker.finish() self.d_requestMove(self.moveList) self.moveList= [] self.isMyTurn = False else: self.moveList.append(index) if self.playerColorString == "white": x = self.locatorList[index].getChildren()[1] x.show() else: x = self.locatorList[index].getChildren()[2] x.show() if self.moverType == "king": x.find("**/checker_k*").show() #self.locatorList[index].ls() self.locatorList[index].setColor(Vec4(.5,.5,.5,.5)) else: #must do an adjacent move! if self.checkLegalMove(lastItem, thisItem, self.moverType) == True: #there exists a legal move self.moveList.append(index) #ghostConstant here is a small alpha offset to give it a transparent look #tintConstant makes the peice a bit darker (necessary when ghosting) col = self.locatorList[index].getColor() #self.locatorList[index].setColor(col - self.tintConstant - self.ghostConstant) self.locatorList[index].show() self.sound.start() self.blinker.finish() self.d_requestMove(self.moveList) self.moveList= [] self.isMyTurn = False def existsLegalJumpsFrom(self,index, peice): if peice == "king": for x in range(4): if self.board.squareList[index].getAdjacent()[x] != None and self.board.squareList[index].getJumps()[x] != None: # Off the board adj = self.board.squareList[self.board.squareList[index].getAdjacent()[x]] jump = self.board.squareList[self.board.squareList[index].getJumps()[x]] if adj.getState() == 0: pass elif adj.getState() == self.playerNum or adj.getState() == self.playerNum+2: pass elif jump.getState() == 0: #peice is owned by other dude and its a legal jump if not index in self.moveList and not jump.getNum() in self.moveList: return True else: pass return False elif peice == "normal": if self.playerNum == 1: moveForward = [1,2] elif self.playerNum == 2: moveForward = [0,3] for x in moveForward: if self.board.squareList[index].getAdjacent()[x] != None and self.board.squareList[index].getJumps()[x] != None: adj = self.board.squareList[self.board.squareList[index].getAdjacent()[x]] jump = self.board.squareList[self.board.squareList[index].getJumps()[x]] if adj.getState() == 0: pass elif adj.getState() == self.playerNum or adj.getState() == self.playerNum+2: pass else: if jump.getState() == 0: if not index in self.moveList: return True return False def existsLegalMovesFrom(self,index, peice): if peice == "king": for x in self.board.squareList[index].getAdjacent(): if x != None: if self.board.squareList[x].getState() == 0: return True return False elif peice == "normal": if self.playerNum == 1: moveForward = [1,2] elif self.playerNum == 2: moveForward = [0,3] for x in moveForward: if self.board.squareList[index].getAdjacent()[x] != None: adj = self.board.squareList[self.board.squareList[index].getAdjacent()[x]] if adj.getState() == 0: return True return False def checkLegalMove(self, firstSquare, secondSquare, peice): if (not firstSquare.getNum() in self.mySquares) and (not firstSquare.getNum() in self.myKings): return False if self.playerNum == 1: moveForward = [1,2] else: #self.playerNum == 2: moveForward = [0,3] if peice == "king": for x in range(4): if firstSquare.getAdjacent()[x] != None: if self.board.squareList[firstSquare.getAdjacent()[x]].getState() == 0 and secondSquare.getNum() in firstSquare.getAdjacent(): return True return False elif peice == "normal": for x in moveForward: if firstSquare.getAdjacent()[x] != None and secondSquare.getNum() in firstSquare.getAdjacent(): if self.board.squareList[firstSquare.getAdjacent()[x]].getState() == 0 and firstSquare.getAdjacent().index(secondSquare.getNum()) == x: return True return False def checkLegalJump(self, firstSquare, secondSquare, peice): if (not firstSquare.getNum() in self.mySquares) and (not firstSquare.getNum() in self.myKings) and len(self.moveList) == 1: return False if self.playerNum == 1: moveForward = [1,2] opposingPeices = [2,4] else: #self.playerNum == 2: moveForward = [0,3] opposingPeices = [1,3] if peice == "king": if secondSquare.getNum() in firstSquare.getJumps(): index = firstSquare.getJumps().index(secondSquare.getNum()) if self.board.squareList[firstSquare.getAdjacent()[index]].getState() in opposingPeices: return True else: return False elif peice == "normal": if secondSquare.getNum() in firstSquare.getJumps(): index = firstSquare.getJumps().index(secondSquare.getNum()) if index in moveForward: if self.board.squareList[firstSquare.getAdjacent()[index]].getState() in opposingPeices: #is the peice jumping over yours or his return True else: return False else: return False else: return False def d_requestMove(self, moveList): self.sendUpdate('requestMove', [moveList]) ########## ##setGameState (required broadcast ram) # #This is the function that handles the moves made after a move is parsed by the AI #and deemed to be valid # #If moveList is the empty List, then the player is asynchronously joining the game, (OBSERVING) #and just wants the board state. # #otherwise there is a series of jumps (or jump) that needs to be parsed and animated, then #consequently setting the board state # #after every setGameState, the client checks to see the current #Status of his peices (checkForWin), if he belives he won, he requests it to the server ######### def setGameState(self, tableState, moveList): if moveList != []: if self.board.squareList[moveList[0]].getState() == 1 or self.board.squareList[moveList[0]].getState() == 3: playerColor = "white" else: playerColor = "black" if self.board.squareList[moveList[0]].getState() <= 2: self.animatePeice(tableState, moveList, "normal", playerColor) else: self.animatePeice(tableState, moveList, "king", playerColor) else: self.updateGameState(tableState) def updateGameState(self, squares): self.board.setStates(squares) #set the board state self.mySquares = [] self.myKings = [] messenger.send('wakeup') #Because i designed this poorly, Must do a temporary playerNum #for observers, and set it back to None when i am done. isObserve = False if self.playerNum == None: self.playerNum = 1 self.playerColorString = "white" isObserve = True #Need to traverse the list to do the showing of peices ect for xx in range(32): #self.hideChildren(self.locatorList[xx].getChildren()) # Hide all off the pieces for blah in self.locatorList[xx].getChildren(): blah.hide() if self.locatorList[xx].getChildren().index(blah) != 0: blah1 = blah.find("**/checker_k*") owner = self.board.squareList[xx].getState() #Get the State of that square #print owner # This means it is MY Peice if owner == self.playerNum: #need to see what color i am if self.playerColorString == "white": x = self.locatorList[xx].getChildren()[1] # white x.show() x.find("**/checker_k*").hide() else: x = self.locatorList[xx].getChildren()[2] # black x.show() x.find("**/checker_k*").hide() self.mySquares.append(xx) ####################### elif owner == 0: # blank Tile self.hideChildren(self.locatorList[xx].getChildren()) # Hide all off the pieces ####################### elif owner == self.playerNum + 2: #its MY peice but its a KING if self.playerColorString == "white": x = self.locatorList[xx].getChildren()[1] # white x.show() x.find("**/checker_k*").show() else: x = self.locatorList[xx].getChildren()[2] # black x.show() x.find("**/checker_k*").show() self.myKings.append(xx) ######################## else: # opposing player peice if owner <= 2: #Opposing player Non king if self.playerColorString == "white": #we are white so show the black piece x = self.locatorList[xx].getChildren()[2] x.show() x.find("**/checker_k*").hide() else: x = self.locatorList[xx].getChildren()[1] x.show() x.find("**/checker_k*").hide() else: #the peice is an opposing players KING if self.playerColorString == "white": x = self.locatorList[xx].getChildren()[2] x.show() x.find("**/checker_k*").show() else: x = self.locatorList[xx].getChildren()[1] x.show() x.find("**/checker_k*").show() ########################### if isObserve == True: self.playerNum = None self.playerColorString = None return ###### #A player MUST move if he has a legal jump #This will flag the bool making him do so ###### self.mustJump = False self.hasNormalMoves = False for x in self.myKings: if self.existsLegalJumpsFrom(x, "king") == True: self.mustJump = True break else: self.mustJump = False if self.mustJump == False: for x in self.mySquares: if self.existsLegalJumpsFrom(x, "normal") == True: self.mustJump = True break else: self.mustJump = False ############# #if i dont have any jumps, Must check to see if i have any legal moves #If i dont, then the game is over. ### if self. mustJump != True: #Check for legal moves and possibly LOSS for x in self.mySquares: if self.existsLegalMovesFrom(x, "normal") == True: self.hasNormalMoves = True break else: self.hasNormalMoves = False if self.hasNormalMoves == False: #make sure to not overRide a True for x in self.myKings: if self.existsLegalMovesFrom(x, "king") == True: self.hasNormalMoves = True break else: self.hasNormalMoves = False if self.mustJump == False and self.hasNormalMoves == False: pass #Server is calculating everything def hideChildren(self, nodeList): for x in range (1,2): nodeList[x].hide() def animatePeice(self, tableState, moveList,type, playerColor): messenger.send('wakeup') ###for x in self.locatorList: #x.show() if playerColor == "white": gamePeiceForAnimation = loader.loadModel("phase_6/models/golf/regular_checker_piecewhite.bam") else: gamePeiceForAnimation = loader.loadModel("phase_6/models/golf/regular_checker_pieceblack.bam") if type == "king": gamePeiceForAnimation.find("**/checker_k*").show() else: gamePeiceForAnimation.find("**/checker_k*").hide() gamePeiceForAnimation.reparentTo(self.boardNode) gamePeiceForAnimation.setPos(self.locatorList[moveList[0]].getPos()) if self.isRotated == True: gamePeiceForAnimation.setH(180) #self.hideChildren(self.locatorList[moveList[0]].getChildren()) #self.locatorList[moveList[0]].hide() for x in self.locatorList[moveList[0]].getChildren(): x.hide() checkersPeiceTrack = Sequence() length = len(moveList) for x in range(length - 1): checkersPeiceTrack.append(Parallel( SoundInterval(self.moveSound), ProjectileInterval(gamePeiceForAnimation, endPos = self.locatorList[moveList[x+1]].getPos(), duration = .5 ))) checkersPeiceTrack.append(Func(gamePeiceForAnimation.removeNode)) checkersPeiceTrack.append(Func(self.updateGameState, tableState)) checkersPeiceTrack.append(Func(self.unAlpha, moveList)) checkersPeiceTrack.start() def announceWin(self, avId): self.fsm.request('gameOver') def unAlpha(self, moveList): for x in moveList: self.locatorList[x].setColorOff() ########### ##doRandomMove # #If a clients move Timer runs out, it will calculate a random move for him #after 3 random moves, it kicks the client out of the game by pushing the #"get up" button for him. ########### def doRandomMove(self): import random move = [] foundLegal = False self.blinker.pause() self.numRandomMoves += 1 while not foundLegal: x = random.randint(0,9) for y in self.board.getAdjacent(self.mySquares[x]): if y != None and self.board.getState(y) == 0: move.append(self.mySquares[x]) move.append(y) foundLegal = True break if move == []: pass #current flaw in the logic, but shouldnt really ever happen #though on live it might #print "random move is empty" playSound = Sequence(SoundInterval(self.knockSound)) playSound.start() self.d_requestMove(move) self.moveList=[] self.isMyTurn = False if(self.numRandomMoves >= 5): self.exitButtonPushed() def doNothing(self): pass
class CogdoMazeGuiManager: def __init__(self, maze): self.maze = maze self.mazeMapGui = MazeMapGui(self.maze.collisionTable) self.mazeMapGui.setScale(.25) self.mazeMapGui.setPos(1.07, 0.0, 0.73) self.hud = CogdoMazeHud() self.timer = None def _initTimer(self): self.timer = ToontownTimer() self.timer.hide() self.timer.setPos(1.16, 0, -0.83) def destroy(self): self.hud.destroy() self.hud = None self.destroyMazeMap() self.destroyTimer() def destroyMazeMap(self): if hasattr(self, "mazeMapGui") and self.mazeMapGui is not None: self.mazeMapGui.destroy() del self.mazeMapGui def destroyTimer(self): if self.timer is not None: self.timer.stop() self.timer.destroy() self.timer = None def updateMazeMapPlayer(self, player, tileX, tileY): self.mazeMapGui.revealCell(tileX, tileY, player) def revealMazeMap(self): self.mazeMapGui.revealAll() def addPlayerToMazeMap(self, keyTilePos, doorTilePos, color): self.mazeMapGui.addPlayer(0, 0, color) self.mazeMapGui.addKey(keyTilePos[0], keyTilePos[1], color) self.mazeMapGui.addDoor(doorTilePos[0], doorTilePos[1], color) def showTimer(self, duration, timerExpiredCallback=None): if self.timer is None: self._initTimer() self.timer.setTime(duration) self.timer.countdown(duration, timerExpiredCallback) self.timer.show() def hideTimer(self): assert hasattr(self, "timer") and self.timer is not None self.timer.hide() self.timer.stop() def displayNotification(self, message, nextMessage=None): self.hud.displayNotification(message, nextMessage)
class DistributedGameTable(DistributedObject.DistributedObject): def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.tableModelPath = 'phase_6/models/golf/game_table.bam' self.numSeats = 6 self.__toonTracks = {} self.gameMenu = None self.game = None self.gameDoId = 0 self.timerFunc = None self.gameWantTimer = False self.cameraBoardTrack = None self.tutorial = None self.fsm = ClassicFSM.ClassicFSM('DistributedGameTable', [ State.State('off', self.enterOff, self.exitOff, ['chooseMode', 'observing']), State.State('chooseMode', self.enterChooseMode, self.exitChooseMode, ['sitting', 'off', 'observing']), State.State('sitting', self.enterSitting, self.exitSitting, ['off']), State.State('observing', self.enterObserving, self.exitObserving, ['off']) ], 'off', 'off') self.fsm.enterInitialState() def generate(self): DistributedObject.DistributedObject.generate(self) self.picnicTableNode = render.attachNewNode('gameTable') self.picnicTable = loader.loadModel(self.tableModelPath) self.picnicTable.reparentTo(self.picnicTableNode) self.loader = self.cr.playGame.hood.loader self.picnicTableNode.reparentTo(self.loader.geom) def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) self.tableCloth = self.picnicTable.find('**/basket_locator') cn = CollisionNode('tableCloth_sphere') self.tableClothSphereNode = self.tableCloth.attachNewNode(cn) cs = CollisionSphere(0, 0, -2, 5.5) self.tableClothSphereNode.node().addSolid(cs) self.seats = [] self.jumpOffsets = [] self.picnicTableSphereNodes = [] for i in xrange(self.numSeats): self.seats.append(self.picnicTable.find('**/*seat' + str(i + 1))) self.jumpOffsets.append( self.picnicTable.find('**/*jumpOut' + str(i + 1))) cn = CollisionNode('picnicTable_sphere_{0}_{1}'.format( self.doId, i)) self.picnicTableSphereNodes.append(self.seats[i].attachNewNode(cn)) cs = CollisionSphere(0, 0, 0, 2) self.picnicTableSphereNodes[i].node().addSolid(cs) self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.buttonModels = loader.loadModel( 'phase_3.5/models/gui/inventory_gui.bam') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find( '**/InventoryButtonRollover') self.joinButton = None self.observeButton = None self.exitButton = None self.tutorialButton = None angle = self.picnicTable.getH() angle -= 90 radAngle = math.radians(angle) unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0) unitVec *= 30.0 self.endPos = self.picnicTable.getPos() + unitVec self.enableCollisions() def disable(self): DistributedObject.DistributedObject.disable(self) self.fsm.request('off') self.clearToonTracks() # TODO: Disable choice buttons. # TODO: Stop sleep tracking. self.destroyGameMenu() self.disableCollisions() del self.gameMenu if self.cameraBoardTrack: self.cameraBoardTrack.finish() del self.cameraBoardTrack del self.tableClothSphereNode del self.tableCloth del self.seats del self.jumpOffsets del self.picnicTableSphereNodes del self.clockNode self.buttonModels.removeNode() del self.buttonModels del self.endPos del self.loader self.picnicTable.removeNode() self.picnicTableNode.removeNode() def delete(self): DistributedObject.DistributedObject.delete(self) del self.fsm def enableCollisions(self): for i in xrange(self.numSeats): event = 'enterpicnicTable_sphere_{0}_{1}'.format(self.doId, i) self.accept(event, self.handleEnterPicnicTableSphere, [i]) self.picnicTableSphereNodes[i].setCollideMask( ToontownGlobals.WallBitmask) self.tableClothSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def disableCollisions(self): for i in xrange(self.numSeats): self.ignore('enterpicnicTable_sphere_{0}_{1}'.format(self.doId, i)) for i in xrange(self.numSeats): self.picnicTableSphereNodes[i].setCollideMask(BitMask32(0)) self.tableClothSphereNode.setCollideMask(BitMask32(0)) def handleEnterPicnicTableSphere(self, i, collEntry): self.fsm.request('chooseMode') def enterOff(self): base.setCellsAvailable(base.leftCells + base.bottomCells, 0) def exitOff(self): base.setCellsAvailable(base.bottomCells, 0) def enterChooseMode(self): self.enableChoiceButtons() def exitChooseMode(self): self.disableChoiceButtons() def enterObserving(self): pass def exitObserving(self): pass def enterSitting(self): pass def exitSitting(self): self.destroyGameMenu() def destroyGameMenu(self): if self.gameMenu: self.gameMenu.removeButtons() self.gameMenu.picnicFunction = None self.gameMenu = None def setPosHpr(self, x, y, z, h, p, r): self.picnicTable.setPosHpr(x, y, z, h, p, r) def storeToonTrack(self, avId, track): self.clearToonTrack(avId) self.__toonTracks[avId] = track def clearToonTrack(self, avId): oldTrack = self.__toonTracks.get(avId) if oldTrack: oldTrack.pause() cleanupDelayDeletes(oldTrack) def clearToonTracks(self): for avId in self.__toonTracks: self.clearToonTrack(avId) def showTimer(self): self.clockNode.stop() self.clockNode.countdown(self.timeLeft, self.timerFunc) self.clockNode.show() def setTimer(self, timerEnd): self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) self.timeLeft = int(time - globalClock.getRealTime()) if self.gameWantTimer and (self.game is not None): self.showTimer() def setTimerFunc(self, function): self.timerFunc = function def allowWalk(self): base.cr.playGame.getPlace().setState('walk') def disallowWalk(self): base.cr.playGame.getPlace().setState('stopped') def enableChoiceButtons(self): if (not self.game) or (not self.game.playing): self.joinButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableJoinButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, 0.8), scale=0.15, command=lambda self=self: self.joinButtonPushed()) else: self.observeButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableObserveButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, 0.6), scale=0.15, command=lambda self=self: self.observeButtonPushed()) self.exitButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableCancelButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(1, 0, 0.6), scale=0.15, command=lambda self=self: self.cancelButtonPushed()) self.tutorialButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableTutorial, text_fg=(1, 1, 0.65, 1), text_pos=(-0.05, -0.13), text_scale=0.55, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-1, 0, 0.6), scale=0.15, command=lambda self=self: self.tutorialButtonPushed()) self.disallowWalk() def disableChoiceButtons(self): if self.joinButton: self.joinButton.destroy() self.joinButton = None if self.observeButton: self.observeButton.destroy() self.observeButton = None if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.tutorialButton: self.tutorialButton.destroy() self.tutorialButton = None def joinButtonPushed(self): pass def observeButtonPushed(self): pass def cancelButtonPushed(self): self.allowWalk() self.fsm.request('off') def tutorialButtonPushed(self): self.disableChoiceButtons() self.gameMenu = PicnicGameSelectMenu(self.tutorialFunction, PicnicGameGlobals.TutorialMenu) def tutorialFunction(self, gameIndex): if gameIndex == PicnicGameGlobals.CheckersGameIndex: self.tutorial = CheckersTutorial(self.tutorialDone) elif gameIndex == PicnicGameGlobals.ChineseCheckersGameIndex: self.tutorial = ChineseCheckersTutorial(self.tutorialDone) else: self.cancelButtonPushed() self.destroyGameMenu() def tutorialDone(self): self.fsm.request('off') self.tutorial = None
class DistributedFindFour(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, "DistributedFindFour") DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel( "phase_6/models/golf/findfour_game.bam") self.boardNode.reparentTo(self) #self.boardNode.setScale(.05) self.board = [[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]] #game variables self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.winningSequence = Sequence() self.moveSequence = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None self.moveCol = None self.move = None ###self.playerTags = [None, None, None, None, None, None #Mouse picking required stuff self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(BitMask32(0x1000)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel( "phase_3.5/models/gui/inventory_gui") self.upButton = self.buttonModels.find("**//InventoryButtonUp") self.downButton = self.buttonModels.find("**/InventoryButtonDown") self.rolloverButton = self.buttonModels.find( "**/InventoryButtonRollover") self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.tintConstant = Vec4(.25, .25, .25, 0) self.ghostConstant = Vec4(0, 0, 0, .5) self.knockSound = base.loader.loadSfx( "phase_5/audio/sfx/GUI_knock_1.mp3") self.clickSound = base.loader.loadSfx( "phase_3/audio/sfx/GUI_balloon_popup.mp3") self.moveSound = base.loader.loadSfx("phase_6/audio/sfx/CC_move.mp3") self.accept('stoppedAsleep', self.handleSleep) ####################### #Fsm and State Data from direct.fsm import ClassicFSM, State self.fsm = ClassicFSM.ClassicFSM( 'ChineseCheckers', [ State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin']) ], # Initial State 'waitingToBegin', # Final State 'waitingToBegin', ) ######################### #Set up the Board Locators ## startLoc = self.boardNode.find("**/locators") self.locatorList = startLoc.getChildren() self.startingPositions = self.locatorList.pop(0) self.startingPositions = self.startingPositions.getChildren() instancePiece = self.boardNode.find("**/pieces") #tag the locators for "picking" ingame #also add colision spheres for movement tempList = [] #Start Position locators #Up above the board for x in range(7): self.startingPositions[x].setTag("StartLocator", "%d" % x) collNode = CollisionNode("startpicker%d" % x) collNode.setIntoCollideMask(BitMask32(0x1000)) tempList.append(self.startingPositions[x].attachNewNode(collNode)) tempList[x].node().addSolid( CollisionTube(0, 0, .23, 0, 0, -.23, .2)) for z in self.startingPositions: y = instancePiece.copyTo(z) for val in y.getChildren(): val.hide() tempList = [] #the peices themselves inside of the board. for x in range(42): self.locatorList[x].setTag("GamePeiceLocator", "%d" % x) collNode = CollisionNode("startpicker%d" % x) collNode.setIntoCollideMask(BitMask32(0x1000)) tempList.append(self.locatorList[x].attachNewNode(collNode)) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, .2)) for z in self.locatorList: y = instancePiece.copyTo(z) for val in y.getChildren(): val.hide() dummyHide = instancePiece.getParent().attachNewNode("DummyHider") instancePiece.reparentTo(dummyHide) dummyHide.hide() def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: # Fix for strange state #TEMP until i find the cause #got to rotate all the peices so that they are facing the side the player is sitting in, #this is a byproduct of backface culling && polygon optimization self.seatPos = self.table.tableState.index( base.localAvatar.doId) if self.seatPos <= 2: for x in self.startingPositions: x.setH(0) for x in self.locatorList: x.setH(0) else: for x in self.startingPositions: x.setH(180) for x in self.locatorList: x.setH(180) self.moveCameraForGame() else: self.seatPos = self.table.seatBumpForObserve if self.seatPos > 2: for x in self.startingPositions: x.setH(180) for x in self.locatorList: x.setH(180) self.moveCameraForGame() def handleSleep(self, task=None): if self.fsm.getCurrentState().getName() == "waitingToBegin": self.exitButtonPushed() if task != None: task.done ########## ##setTableDoId (required broadcast ram) # #Upon construction, sets local pointer to the table, as well as #sets the pointer on the table to itself. #This is necessary to handle events that occur on the table, not #particularly inside of any one game. ### def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) ######### ##Disable/Delete #Must be sure to remove/delete any buttons, screen text #that may be on the screen in the event of a chosen ( or asynchrinous ) #disable or deletion - Code redundance here is necessary #being that "disable" is called upon server crash, and delete is #called upon zone exit ### def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None taskMgr.remove('playerTurnTask') #self.table = None def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None self.winningSequence.finish() taskMgr.remove('playerTurnTask') ########## ##Timer Functions #setTimer (broadcast ram required) #setTurnTimer(broadcast ram required) # #setTimer() controlls the timer for game begin, which upon its timout #calls the startButton. # #turnTimer() does just that # #Important to note that both timers run on the same clockNode. ########## def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState( ).getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if (timeLeft > 0 and timerEnd != 0): if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(.64, 0, -0.27) self.clockNode.countdown(timeLeft, self.doRandomMove) self.clockNode.show() ########### ##Game start(broadcast) and Send Turn (broadcast ram) # #IMPORTANT - 255 is the Uint8 sent to the player when a game starts #to dictate to him that a game is beginning and he is labeled as an observer #for that game - this affects the visual queues for his player color ect. ########## def gameStart(self, playerNum): if playerNum != 255: #observer value self.playerNum = playerNum if self.playerNum == 1: self.playerColorString = "Red" else: self.playerColorString = "Yellow" self.moveCameraForGame() self.fsm.request('playing') def sendTurn(self, playersTurn): if self.fsm.getCurrentState().getName() == 'playing': if playersTurn == self.playerNum: self.isMyTurn = True taskMgr.add(self.turnTask, "playerTurnTask") self.enableTurnScreenText(playersTurn) def illegalMove(self): self.exitButtonPushed() ########## ##Move camera # #Got to move the camera to the specific location in the 3d environment so that the #nametags ect do not collide with the gameboard itself. #also half to do some if statements on the camera itself so that the camera will not (for instance) #rotate 350 degrees when rather it could rotate -10 degrees to get its finishing location ########## def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.pause() rotation = 0 if self.seatPos <= 2: position = self.table.seats[1].getPos() position = position + Vec3(0, -8, 12.8) int = LerpPosHprInterval(camera, 2, position, Vec3(0, -38, 0), camera.getPos(), camera.getHpr()) else: position = self.table.seats[4].getPos() position = position + Vec3(0, -8, 12.8) if camera.getH() < 0: int = LerpPosHprInterval(camera, 2, position, Vec3(-180, -20, 0), camera.getPos(), camera.getHpr()) else: int = LerpPosHprInterval(camera, 2, position, Vec3(180, -20, 0), camera.getPos(), camera.getHpr()) int.start() ##################### #FSM Stuff ### def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() def enterGameOver(self): pass def exitGameOver(self): pass ################################################## # Button Functions and Text ### def exitWaitCountdown(self): self.__disableCollisions() self.ignore("trolleyExitButton") self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton( relief=None, text=TTLocalizer.FindFourGetUpButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.80), scale=0.15, command=lambda self=self: self.exitButtonPushed(), ) return def enableScreenText(self): defaultPos = (-.7, -0.29) if self.playerNum == 1: message = "You are Red" color = Vec4(1, 0, 0, 1) elif self.playerNum == 2: message = "You are Yellow" color = Vec4(1, 1, 0, 1) else: message = TTLocalizer.FindFourObserver color = Vec4(0, 0, 0, 1) #defaultPos = (-.80, -0.25) self.screenText = OnscreenText(text=message, pos=defaultPos, scale=0.10, fg=color, align=TextNode.ACenter, mayChange=1) def enableStartButton(self): self.startButton = DirectButton( relief=None, text=TTLocalizer.FindFourStartButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.6, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.57), scale=0.15, command=lambda self=self: self.startButtonPushed(), ) return def enableLeaveButton(self): self.leaveButton = DirectButton( relief=None, text=TTLocalizer.FindFourQuitButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.13), text_scale=0.5, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.8), scale=0.15, command=lambda self=self: self.exitButtonPushed(), ) return def enableTurnScreenText(self, player): playerOrder = [1, 4, 2, 5, 3, 6] message1 = TTLocalizer.FindFourIts if (self.turnText != None): self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.FindFourYourTurn color = (0, 0, 0, 1) else: if player == 1: message2 = TTLocalizer.FindFourRedTurn color = (1, 0, 0, 1) elif player == 2: message2 = TTLocalizer.FindFourYellowTurn color = (1, 1, 0, 1) self.turnText = OnscreenText(text=message1 + message2, pos=(-0.7, -0.39), scale=0.092, fg=color, align=TextNode.ACenter, mayChange=1) #This function is called either if the player clicks on it (to begin a game) #or if the game begin timer runs out. (timer is in sync with server so results should be # + or - ~ 1 second def startButtonPushed(self): self.sendUpdate("requestBegin") self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate("requestExit") ########## #Mouse Picking/clicking operations # # #These functions handle all of the mouse clicking functions #Its best to look through the code for comments for it to make #the most sense. # #The self.blinker that is referenced in these functions, is a cosmetic #colorLerp that gives the player a visual feedback as to what checkers peice #he has (currently) selected. # # #mouseClick is just an extention to the Task that is generated whenever it is your turn - #mouseClick simply commits the move that you have been deciding upon inside of the 'playerTurnTask" ########## def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True and not self.moveSequence.isPlaying( ): #cant pick stuff if its not your turn if self.moveCol != None: self.d_requestMove(self.moveCol) self.moveCol = None self.isMyTurn = False taskMgr.remove('playerTurnTask') def handleClicked(self, index): pass #This is the wonderul task that handles the magic for the selecting of the game piece #it is important to note that this task gets spawned up whenever it is deemed your turn #by the sendTurn stuff #I had to make some optimizations to not make this task completely bogg down the computer #(1) set the bit masks for the collision traverser so that it will not even test anything that #is not a collision sphere for the findFour Game def turnTask(self, task): if base.mouseWatcherNode.hasMouse() == False: return task.cont if self.isMyTurn == False: return task.cont if self.moveSequence.isPlaying(): return task.cont mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() #get the closest Object pickedObj = self.myHandler.getEntry(0).getIntoNodePath() #will return the INT for the locator node closest parent pickedObj = pickedObj.getNetTag("StartLocator") if pickedObj: #make sure something actually was "picked" colVal = int(pickedObj) if colVal == self.moveCol: return task.cont if self.board[0][colVal] == 0: #it is a legal move if self.moveCol != None: for x in self.startingPositions[self.moveCol].getChild( 1).getChildren(): #hide the old peices x.hide() self.moveCol = colVal if self.playerNum == 1: self.startingPositions[self.moveCol].getChild( 1).getChild(2).show() elif self.playerNum == 2: self.startingPositions[self.moveCol].getChild( 1).getChild(3).show() return task.cont def d_requestMove(self, moveCol): self.sendUpdate('requestMove', [moveCol]) ########## ##setGameState (required broadcast ram) # #This is the function that handles the moves made after a move is parsed by the AI #and deemed to be valid # #If moveList is the empty List, then the player is asynchronously joining the game, (OBSERVING) #and just wants the board state. # #otherwise there is a series of jumps (or jump) that needs to be parsed and animated, then #consequently setting the board state # #after every setGameState, the client checks to see the current #Status of his peices (checkForWin), if he belives he won, he requests it to the server ######### def setGameState(self, tableState, moveCol, movePos, turn): messenger.send('wakeup') ##Funny if statement #1 #This slew of statements is to handle a specific case that looks funny #when a client joins the game (to observe) after the game has begun # #If you notice, you will see that the movePos and the MoveCol are parts #of the game state (required RAM), so when a client joins this game asynchrinously #they too will see the last moves animation as they are sitting down at the table. # # These slew of if statements are to handle that fact, by testing the state of the #current game board, as well as the state of the board that was handed to the client #through the DC message. if self.table.fsm.getCurrentState().getName() == 'observing': isBlank = True for x in range(7): if self.board[5][x] != 0: isBlank = False break gameBlank = True for x in range(7): if tableState[5][x] != 0: gameBlank = False break if isBlank == True and gameBlank == False: for x in range(6): for y in range(7): self.board[x][y] = tableState[x][y] self.updateGameState() return ### #This if statement really doesnt apply unless the board is completely blank! if moveCol == 0 and movePos == 0 and turn == 0: #Someones coming in after a Move for x in range(6): for y in range(7): self.board[x][y] = tableState[x][y] self.updateGameState() else: #need to animate because a movePos was given in the Ram Field self.animatePeice(tableState, moveCol, movePos, turn) #Clients all check if they won in this game, where the AI #verifies - to save cycles on the AI server didIWin = self.checkForWin() if didIWin != None: self.sendUpdate("requestWin", [didIWin]) ############################################ ##UpdateGameState # #For the games (visual) state, it is important to note that child 0 and child1 #are the pieces that have been copied and reparented to that node. #Really, i just have 2 peices that are in the model, and i hide/show them #instead of instantiating them on the fly. ## def updateGameState(self): for x in range(6): for y in range(7): for z in self.locatorList[(x * 7) + y].getChild(1).getChildren(): z.hide() for x in range(6): for y in range(7): state = self.board[x][y] if state == 1: self.locatorList[(x * 7) + y].getChild(1).getChild(0).show() elif state == 2: self.locatorList[(x * 7) + y].getChild(1).getChild(1).show() ########## ##CheckForWin # #This function is pretty self explanitory, it checks all of the directions for #all of the pieces on the players current boardState to check for a win. # #this is needed because programming wise it would be a disgusting case to test #for a win if a peice is in the middle of a (4) piece run - Rather it is easier #to simply test all the pieces whether or not they are on the Edge of a win, #thus making the code 1000% easier to read and understand. ### def checkForWin(self): for x in range(6): for y in range(7): if self.board[x][y] == self.playerNum: if self.checkHorizontal(x, y, self.playerNum) == True: return [x, y] elif self.checkVertical(x, y, self.playerNum) == True: return [x, y] elif self.checkDiagonal(x, y, self.playerNum) == True: return [x, y] return None ########### ##AnnounceWinnerPosition # #Fancy function that is called after the AI determines the players' request was #in deed a true win. # #This function does all of the animations for the blinking after a person wins # #Also - Note that there are two separate functions for finding/checking a win. # #check(direction) - returns true or false #find(direction) - returns the list of 4 ints if win and [] for no win ### def announceWinnerPosition(self, x, y, winDirection, playerNum): self.isMyturn = False if self.turnText: self.turnText.hide() self.clockNode.stop() self.clockNode.hide() if winDirection == 0: blinkList = self.findHorizontal(x, y, playerNum) elif winDirection == 1: blinkList = self.findVertical(x, y, playerNum) elif winDirection == 2: blinkList = self.findDiagonal(x, y, playerNum) if blinkList != []: print(blinkList) val0 = (x * 7) + y x = blinkList[0][0] y = blinkList[0][1] val1 = (x * 7) + y x = blinkList[1][0] y = blinkList[1][1] val2 = (x * 7) + y x = blinkList[2][0] y = blinkList[2][1] val3 = (x * 7) + y self.winningSequence = Sequence() downBlinkerParallel = Parallel( LerpColorInterval(self.locatorList[val0], .3, Vec4(.5, .5, .5, .5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[val1], .3, Vec4(.5, .5, .5, .5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[val2], .3, Vec4(.5, .5, .5, .5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[val3], .3, Vec4(.5, .5, .5, .5), Vec4(1, 1, 1, 1))) upBlinkerParallel = Parallel( LerpColorInterval(self.locatorList[val0], .3, Vec4(1, 1, 1, 1), Vec4(.5, .5, .5, .5)), LerpColorInterval(self.locatorList[val1], .3, Vec4(1, 1, 1, 1), Vec4(.5, .5, .5, .5)), LerpColorInterval(self.locatorList[val2], .3, Vec4(1, 1, 1, 1), Vec4(.5, .5, .5, .5)), LerpColorInterval(self.locatorList[val3], .3, Vec4(1, 1, 1, 1), Vec4(.5, .5, .5, .5))) self.winningSequence.append(downBlinkerParallel) self.winningSequence.append(upBlinkerParallel) self.winningSequence.loop() ########## ##Tie # #This is the function that sends the tie message, and animates the whole board in a fun way such that #dictates that a tie has occurred ### def tie(self): self.tieSequence = Sequence(autoFinish=1) self.clockNode.stop() self.clockNode.hide() self.isMyTurn = False self.moveSequence.finish() if self.turnText: self.turnText.hide() for x in range(41): self.tieSequence.append( Parallel( LerpColorInterval(self.locatorList[x], .15, Vec4(.5, .5, .5, .5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[x], .15, Vec4(1, 1, 1, 1), Vec4(.5, .5, .5, .5)))) whisper = WhisperPopup("This Find Four game has resulted in a Tie!", OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) whisper.manage(base.marginManager) self.tieSequence.start() def hideChildren(self, nodeList): pass ########## ##animatePiece # #Function that handles the animation of the next move, as well as sets the current #view of the board so that the player can see it def animatePeice(self, tableState, moveCol, movePos, turn): messenger.send('wakeup') #update the board state from DC parent function for x in range(6): for y in range(7): self.board[x][y] = tableState[x][y] #show the column piece that was selected for the move pos = self.startingPositions[moveCol].getPos() if turn == 0: peice = self.startingPositions[moveCol].getChild( 1).getChildren()[2] peice.show() elif turn == 1: peice = self.startingPositions[moveCol].getChild( 1).getChildren()[3] peice.show() #animate the thing self.moveSequence = Sequence() startPos = self.startingPositions[moveCol].getPos() arrayLoc = (movePos * 7) + moveCol self.moveSequence.append( LerpPosInterval(self.startingPositions[moveCol], 1.5, self.locatorList[arrayLoc].getPos(self), startPos)) self.moveSequence.append(Func(peice.hide)) self.moveSequence.append( Func(self.startingPositions[moveCol].setPos, startPos)) self.moveSequence.append(Func(self.updateGameState)) self.moveSequence.start() def announceWin(self, avId): self.fsm.request('gameOver') ########## ##doRandomMove # #For this game, doRandom move will as well fire when the turnTimer runs out - but will also, #(if the player has been debating pieces with his cursor), will commite the last selected piece #by the 'playerTurnTask' # #It is also smart enough to not randomly commit an illegal move :) ########### def doRandomMove(self): if self.isMyTurn: if self.moveCol != None: self.d_requestMove(self.moveCol) self.moveCol = None self.isMyTurn = False taskMgr.remove('playerTurnTask') else: hasfound = False while hasfound == False: import random x = random.randint(0, 6) if self.board[0][x] == 0: self.d_requestMove(x) self.moveCol = None self.isMyTurn = False taskMgr.remove('playerTurnTask') hasfound = True def doNothing(self): pass ########## ##Large slew of check/find Functions # #I would suggest getting out paper to analyze how these things work, but hopefully #with a bit of ASCII art and some explaining it wont be too bad. # # Game board is represented as such in memory (as you see it in real life): # |0 0 0 0 0 0 0 | 0 1 2 3 4 5 6 # |0 0 0 0 0 0 0 | 0 . . . . . . . # |0 0 0 0 0 0 0 | 1 . . . . . . . # |0 0 0 0 0 0 0 | 2 . . . . . . . # |0 0 0 0 0 0 0 | 3 . . . . . . . # |0 0 0 0 0 0 0 | 4 . . . . . . . # 5 . . . . . . . # # # as you can see, (0,0) is in the top left corner, and just makes things easier to write about #because the locators, and lists seem to function well in this sense # board state looks like [ [0,0,0,0,0,0,0], # [0,0,0,0,0,0,0], # [0,0,0,0,0,0,0], # [0,0,0,0,0,0,0], # [0,0,0,0,0,0,0], # [0,0,0,0,0,0,0] ] # # #So when looking at this code just keep in mind this is how the board is working in memory # #Also, important to see that there are two types of functions here #(1) the check(direction) functions who return true or false whether or not they detect # a win in that direction #(2) the find(direction) functions who return the list of where they detected a win # or [ ] if they found nothing. ## def checkHorizontal(self, rVal, cVal, playerNum): if cVal == 3: for x in range(1, 4): if self.board[rVal][cVal - x] != playerNum: break if self.board[rVal][cVal - x] == playerNum and x == 3: return True for x in range(1, 4): if self.board[rVal][cVal + x] != playerNum: break if self.board[rVal][cVal + x] == playerNum and x == 3: return True return False elif cVal == 2: for x in range(1, 4): if self.board[rVal][cVal + x] != playerNum: break if self.board[rVal][cVal + x] == playerNum and x == 3: return True return False elif cVal == 4: for x in range(1, 4): if self.board[rVal][cVal - x] != playerNum: break if self.board[rVal][cVal - x] == playerNum and x == 3: return True return False else: return False def checkVertical(self, rVal, cVal, playerNum): if rVal == 2: for x in range(1, 4): if self.board[rVal + x][cVal] != playerNum: break if self.board[rVal + x][cVal] == playerNum and x == 3: return True return False elif rVal == 3: for x in range(1, 4): if self.board[rVal - x][cVal] != playerNum: break if self.board[rVal - x][cVal] == playerNum and x == 3: return True return False else: return False def checkDiagonal(self, rVal, cVal, playerNum): if cVal <= 2: #Cannot have Left Diagonals if rVal == 2: #cannot have upper Diagonal for x in range(1, 4): if self.board[rVal + x][cVal + x] != playerNum: break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return True return False elif rVal == 3: #cannot have downard diagonal for x in range(1, 4): if self.board[rVal - x][cVal + x] != playerNum: break if self.board[rVal - x][cVal + x] == playerNum and x == 3: return True return False elif cVal >= 4: if rVal == 2: #cannot have upper Diagonal for x in range(1, 4): if self.board[rVal + x][cVal - x] != playerNum: break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return True return False elif rVal == 3: #cannot have downard diagonal for x in range(1, 4): if self.board[rVal - x][cVal - x] != playerNum: break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return True return False else: #we are in column 3 if rVal == 3 or rVal == 4 or rVal == 5: #we have 2 upward Diagonals for x in range(1, 4): #Up left if self.board[rVal - x][cVal - x] != playerNum: break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return True for x in range(1, 4): if self.board[rVal - x][cVal - x] != playerNum: break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return True return False elif rVal == 0 or rVal == 1 or rVal == 2: for x in range(1, 4): #down left if self.board[rVal + x][cVal - x] != playerNum: break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return True for x in range(1, 4): if self.board[rVal + x][cVal + x] != playerNum: break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return True return False return False ####################################### def findHorizontal(self, rVal, cVal, playerNum): if cVal == 3: retList = [] for x in range(1, 4): retList.append([rVal, cVal - x]) if self.board[rVal][cVal - x] != playerNum: retList = [] break if self.board[rVal][cVal - x] == playerNum and x == 3: return retList for x in range(1, 4): retList.append([rVal, cVal + x]) if self.board[rVal][cVal + x] != playerNum: retList = [] break if self.board[rVal][cVal + x] == playerNum and x == 3: return retList return [] elif cVal == 2: retList = [] for x in range(1, 4): retList.append([rVal, cVal + x]) if self.board[rVal][cVal + x] != playerNum: retList = [] break if self.board[rVal][cVal + x] == playerNum and x == 3: return retList return [] elif cVal == 4: retList = [] for x in range(1, 4): retList.append([rVal, cVal - x]) if self.board[rVal][cVal - x] != playerNum: retList = [] break if self.board[rVal][cVal - x] == playerNum and x == 3: return retList return [] else: return [] def findVertical(self, rVal, cVal, playerNum): if rVal == 2: retList = [] for x in range(1, 4): retList.append([rVal + x, cVal]) if self.board[rVal + x][cVal] != playerNum: retList = [] break if self.board[rVal + x][cVal] == playerNum and x == 3: return retList return [] elif rVal == 3: retList = [] for x in range(1, 4): retList.append([rVal - x, cVal]) if self.board[rVal - x][cVal] != playerNum: retList = [] break if self.board[rVal - x][cVal] == playerNum and x == 3: return retList return [] else: return [] def findDiagonal(self, rVal, cVal, playerNum): retList = [] if cVal <= 2: #Cannot have Left Diagonals if rVal == 2: #cannot have upper Diagonal for x in range(1, 4): retList.append([rVal + x, cVal + x]) if self.board[rVal + x][cVal + x] != playerNum: retList = [] break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return retList return [] elif rVal == 3: #cannot have downard diagonal for x in range(1, 4): retList.append([rVal - x, cVal + x]) if self.board[rVal - x][cVal + x] != playerNum: retList = [] break if self.board[rVal - x][cVal + x] == playerNum and x == 3: return retList return [] elif cVal >= 4: if rVal == 2: #cannot have upper Diagonal for x in range(1, 4): retList.append([rVal + x, cVal - x]) if self.board[rVal + x][cVal - x] != playerNum: retList = [] break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return retList return [] elif rVal == 3: #cannot have downard diagonal for x in range(1, 4): retList.append([rVal - x, cVal - x]) if self.board[rVal - x][cVal - x] != playerNum: retList = [] break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return retList return [] else: #we are in column 3 if rVal == 3 or rVal == 4 or rVal == 5: #we have 2 upward Diagonals for x in range(1, 4): #Up left retList.append([rVal - x, cVal - x]) if self.board[rVal - x][cVal - x] != playerNum: retList = [] break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return retList for x in range(1, 4): retList.append([rVal + x, cVal - x]) if self.board[rVal + x][cVal - x] != playerNum: retList = [] break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return retList return [] elif rVal == 0 or rVal == 1 or rVal == 2: for x in range(1, 4): #down left retList.append([rVal + x, cVal - x]) if self.board[rVal + x][cVal - x] != playerNum: retList = [] break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return retList for x in range(1, 4): retList.append([rVal + x, cVal + x]) if self.board[rVal + x][cVal + x] != playerNum: retList = [] break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return retList return [] return []
class DistributedViewingBlock(DistributedStartingBlock): """ Derived from the starting block to provide specific movies for the Viewing pads. """ ###################################################################### # Class Variables ###################################################################### notify = DirectNotifyGlobal.directNotify.newCategory( "DistributedViewingBlock") #notify.setInfo(True) sphereRadius = 6 #cameraPos = Point3(-23, 0, 10) #cameraHpr = Point3(90, -10, 0) def __init__(self, cr): """ Comment """ # Initialize the Super Class DistributedStartingBlock.__init__(self, cr) # Initialize Instance Variables self.timer = None def delete(self): """ """ if (self.timer is not None): self.timer.destroy() del self.timer # Perform the Super Class Delete Call DistributedStartingBlock.delete(self) def generateInit(self): """ comment """ self.notify.debugStateCall(self) # skip over DistributedStartingBlock, since this method is # a cut-and-paste of DistributedStartingBlock.generateInit DistributedObject.DistributedObject.generateInit(self) # Create a NodePath to represent the spot itself. It gets # repositioned according to setPosHpr. self.nodePath = NodePath(self.uniqueName('StartingBlock')) # Make a collision sphere to detect when an avatar enters the # kart block. self.collSphere = CollisionSphere(-1, 6.75, -1, self.sphereRadius) # Make sure the sphere is intangible initially. self.collSphere.setTangible(0) self.collNode = CollisionNode(self.uniqueName('StartingBlockSphere')) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.nodePath.attachNewNode(self.collNode) def announceGenerate(self): """ Comment """ self.notify.debugStateCall(self) # skip over DistributedStartingBlock, since this method is # a cut-and-paste of DistributedStartingBlock.announceGenerate DistributedObject.DistributedObject.announceGenerate(self) # The posHpr has been set at this point, thus reparent to render # and accept the collision sphere event. #if( __debug__ ): # self.smiley = loader.loadModel( "models/misc/smiley" ) # self.smiley.setScale( 0.25 ) # self.smiley.setColorScale( 1, 0, 0, 1 ) # self.smiley.reparentTo( self.nodePath ) self.nodePath.reparentTo(render) self.accept(self.uniqueName('enterStartingBlockSphere'), self.__handleEnterSphere) if (__debug__): if self.testLOD: self.__generateKartAppearTrack() def setPadLocationId(self, padLocationId): """ Comment: """ self.notify.debugStateCall(self) # Generate a new node on the nodepath. self.movieNode = self.nodePath.attachNewNode( self.uniqueName('MovieNode')) self.exitMovieNode = self.nodePath.attachNewNode( self.uniqueName('ExitMovieNode')) if (padLocationId % 2): # padLocation is on the right-side, thus the view node should # be placed on the right-side. self.movieNode.setPosHpr(0, 6.5, 0, 0, 0, 0) else: # otherwise its on the left-side. self.movieNode.setPosHpr(0, -6.5, 0, 0, 0, 0) self.exitMovieNode.setPosHpr(3, 6.5, 0, 270, 0, 0) #if( __debug__ ): # self.smiley3 = loader.loadModel( "models/misc/smiley" ) # self.smiley3.setScale( 0.2 ) # self.smiley3.setColorScale( 1, 1, 0, 1 ) # self.smiley3.reparentTo( self.exitMovieNode ) # self.smiley2 = loader.loadModel( "models/misc/smiley" ) # self.smiley2.setScale( 0.2 ) # self.smiley2.setColorScale( 0, 1, 0, 1 ) # self.smiley2.reparentTo( self.movieNode ) self.collNodePath.reparentTo(self.movieNode) #if ( __debug__): # self.collNodePath.show() def __handleEnterSphere(self, collEntry): """ comment """ assert self.notify.debug("__handleEnterSphere") # Protect against the same toon from re-entering the sphere # immediately after exiting. It is most likely a mistake on the # toon's part. if( base.localAvatar.doId == self.lastAvId and \ globalClock.getFrameCount() <= self.lastFrame + 1 ): self.notify.debug("Ignoring duplicate entry for avatar.") return # Only toons with hp > 0 and own a kart may enter the sphere. if ((base.localAvatar.hp > 0)): def handleEnterRequest(self=self): self.ignore("stoppedAsleep") if hasattr(self.dialog, 'doneStatus') and (self.dialog.doneStatus == 'ok'): self.d_requestEnter(base.cr.isPaid()) else: self.cr.playGame.getPlace().setState("walk") self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog # take the localToon out of walk mode self.cr.playGame.getPlace().fsm.request('stopped') # make dialog go away if they fall asleep while stopped self.accept("stoppedAsleep", handleEnterRequest) # A dialog box should prompt the toon for action, to either # enter a race or ignore it. doneEvent = 'enterRequest|dialog' msg = TTLocalizer.StartingBlock_EnterShowPad self.dialog = TTGlobalDialog(msg, doneEvent, 4) self.dialog.accept(doneEvent, handleEnterRequest) #self.d_requestEnter() def generateCameraMoveTrack(self): """ """ self.cPos = camera.getPos(self.av) self.cHpr = camera.getHpr(self.av) cameraPos = Point3(23, -10, 7) cameraHpr = Point3(65, -10, 0) camera.wrtReparentTo(self.nodePath) cameraTrack = LerpPosHprInterval(camera, 1.5, cameraPos, cameraHpr) return cameraTrack def makeGui(self): self.notify.debugStateCall(self) if (self.timer is not None): return # TEMPORARY TOONTOWN TIMER FOR TIME UNTIL RACE LAUNCH self.timer = ToontownTimer() self.timer.setScale(0.3) self.timer.setPos(1.16, 0, -.73) self.timer.hide() # Make Super Class GUI DistributedStartingBlock.makeGui(self) def showGui(self): self.notify.debugStateCall(self) # Show Timer and Super class gui self.timer.show() DistributedStartingBlock.showGui(self) def hideGui(self): self.notify.debugStateCall(self) if (not hasattr(self, "timer") or self.timer is None): return self.timer.reset() self.timer.hide() DistributedStartingBlock.hideGui(self) def countdown(self): countdownTime = KartGlobals.COUNTDOWN_TIME - globalClockDelta.localElapsedTime( self.kartPad.getTimestamp(self.avId)) self.timer.countdown(countdownTime) def enterEnterMovie(self): """ """ #pdb.set_trace() self.notify.debug( "%d enterEnterMovie: Entering the Enter Movie State." % self.doId) if ConfigVariableBool('want-qa-regression', 0).getValue(): raceName = TTLocalizer.KartRace_RaceNames[self.kartPad.trackType] self.notify.info('QA-REGRESSION: KARTING: %s' % raceName) # Obtain the toon's kart. pos = self.nodePath.getPos(render) hpr = self.nodePath.getHpr(render) pos.addZ(1.7) #1.5 ) hpr.addX(270) self.kartNode.setPosHpr(pos, hpr) # Obtain the Enter Movie Tracks toonTrack = self.generateToonMoveTrack() kartTrack = self.generateKartAppearTrack() jumpTrack = self.generateToonJumpTrack() name = self.av.uniqueName("EnterRaceTrack") if ((self.av is not None) and (self.localToonKarting)): cameraTrack = self.generateCameraMoveTrack() self.finishMovie() self.movieTrack = Sequence(Parallel( cameraTrack, Sequence(), ), kartTrack, jumpTrack, Func(self.makeGui), Func(self.showGui), Func(self.countdown), Func(self.request, "Waiting"), Func(self.d_movieFinished), name=name, autoFinish=1) else: self.finishMovie() self.movieTrack = Sequence( toonTrack, kartTrack, jumpTrack, name=name, autoFinish=1, ) self.movieTrack.start() # never show the dialog on viewing pads self.exitRequested = True
class DistributedViewingBlock(DistributedStartingBlock): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedViewingBlock') sphereRadius = 6 def __init__(self, cr): DistributedStartingBlock.__init__(self, cr) self.timer = None return def delete(self): if self.timer is not None: self.timer.destroy() del self.timer DistributedStartingBlock.delete(self) return def generateInit(self): self.notify.debugStateCall(self) DistributedObject.DistributedObject.generateInit(self) self.nodePath = NodePath(self.uniqueName('StartingBlock')) self.collSphere = CollisionSphere(-1, 6.75, -1, self.sphereRadius) self.collSphere.setTangible(0) self.collNode = CollisionNode(self.uniqueName('StartingBlockSphere')) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.nodePath.attachNewNode(self.collNode) def announceGenerate(self): self.notify.debugStateCall(self) DistributedObject.DistributedObject.announceGenerate(self) self.nodePath.reparentTo(render) self.accept(self.uniqueName('enterStartingBlockSphere'), self.__handleEnterSphere) if (__debug__): if self.testLOD: self.__generateKartAppearTrack() def setPadLocationId(self, padLocationId): self.notify.debugStateCall(self) self.movieNode = self.nodePath.attachNewNode(self.uniqueName('MovieNode')) self.exitMovieNode = self.nodePath.attachNewNode(self.uniqueName('ExitMovieNode')) if padLocationId % 2: self.movieNode.setPosHpr(0, 6.5, 0, 0, 0, 0) else: self.movieNode.setPosHpr(0, -6.5, 0, 0, 0, 0) self.exitMovieNode.setPosHpr(3, 6.5, 0, 270, 0, 0) self.collNodePath.reparentTo(self.movieNode) def __handleEnterSphere(self, collEntry): if base.localAvatar.doId == self.lastAvId and globalClock.getFrameCount() <= self.lastFrame + 1: self.notify.debug('Ignoring duplicate entry for avatar.') return if base.localAvatar.hp > 0: def handleEnterRequest(self = self): self.ignore('stoppedAsleep') if hasattr(self.dialog, 'doneStatus') and self.dialog.doneStatus == 'ok': self.d_requestEnter(base.cr.isPaid()) else: self.cr.playGame.getPlace().setState('walk') self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog self.cr.playGame.getPlace().fsm.request('stopped') self.accept('stoppedAsleep', handleEnterRequest) doneEvent = 'enterRequest|dialog' msg = TTLocalizer.StartingBlock_EnterShowPad self.dialog = TTGlobalDialog(msg, doneEvent, 4) self.dialog.accept(doneEvent, handleEnterRequest) def generateCameraMoveTrack(self): self.cPos = camera.getPos(self.av) self.cHpr = camera.getHpr(self.av) cameraPos = Point3(23, -10, 7) cameraHpr = Point3(65, -10, 0) camera.wrtReparentTo(self.nodePath) cameraTrack = LerpPosHprInterval(camera, 1.5, cameraPos, cameraHpr) return cameraTrack def makeGui(self): self.notify.debugStateCall(self) if self.timer is not None: return self.timer = ToontownTimer() self.timer.setScale(0.3) self.timer.setPos(1.16, 0, -.73) self.timer.hide() DistributedStartingBlock.makeGui(self) return def showGui(self): self.notify.debugStateCall(self) self.timer.show() DistributedStartingBlock.showGui(self) def hideGui(self): self.notify.debugStateCall(self) if not hasattr(self, 'timer') or self.timer is None: return self.timer.reset() self.timer.hide() DistributedStartingBlock.hideGui(self) return def countdown(self): countdownTime = KartGlobals.COUNTDOWN_TIME - globalClockDelta.localElapsedTime(self.kartPad.getTimestamp(self.avId)) self.timer.countdown(countdownTime) def enterEnterMovie(self): self.notify.debug('%d enterEnterMovie: Entering the Enter Movie State.' % self.doId) if base.config.GetBool('want-qa-regression', 0): raceName = TTLocalizer.KartRace_RaceNames[self.kartPad.trackType] self.notify.info('QA-REGRESSION: KARTING: %s' % raceName) pos = self.nodePath.getPos(render) hpr = self.nodePath.getHpr(render) pos.addZ(1.7) hpr.addX(270) self.kartNode.setPosHpr(pos, hpr) toonTrack = self.generateToonMoveTrack() kartTrack = self.generateKartAppearTrack() jumpTrack = self.generateToonJumpTrack() name = self.av.uniqueName('EnterRaceTrack') if self.av is not None and self.localToonKarting: cameraTrack = self.generateCameraMoveTrack() self.finishMovie() self.movieTrack = Sequence(Parallel(cameraTrack, Sequence()), kartTrack, jumpTrack, Func(self.makeGui), Func(self.showGui), Func(self.countdown), Func(self.request, 'Waiting'), Func(self.d_movieFinished), name=name, autoFinish=1) else: self.finishMovie() self.movieTrack = Sequence(toonTrack, kartTrack, jumpTrack, name=name, autoFinish=1) self.movieTrack.start() self.exitRequested = True return
class DistributedCheckers(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, 'DistributedCheckers') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel( 'phase_6/models/golf/regular_checker_game') self.boardNode.reparentTo(self) self.board = CheckersBoard() self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.moveList = [] self.mySquares = [] self.myKings = [] self.isRotated = False self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel( 'phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find( '**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.playerColors = [Vec4(0, 0, 1, 1), Vec4(0, 1, 0, 1)] self.tintConstant = Vec4(0.25, 0.25, 0.25, 0.5) self.ghostConstant = Vec4(0, 0, 0, 0.8) self.startingPositions = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 ]] self.knockSound = base.loader.loadSfx( 'phase_5/audio/sfx/GUI_knock_1.ogg') self.clickSound = base.loader.loadSfx( 'phase_3/audio/sfx/GUI_balloon_popup.ogg') self.moveSound = base.loader.loadSfx('phase_6/audio/sfx/CC_move.ogg') self.accept('stoppedAsleep', self.handleSleep) self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [ State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin']) ], 'waitingToBegin', 'waitingToBegin') x = self.boardNode.find('**/locator*') self.locatorList = x.getChildren() tempList = [] for x in range(0, 32): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) tempList.append(self.locatorList[x].attachNewNode( CollisionNode('picker%d' % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.39)) for z in self.locatorList: y = loader.loadModel( 'phase_6/models/golf/regular_checker_piecewhite') y.find('**/checker_k*').hide() zz = loader.loadModel( 'phase_6/models/golf/regular_checker_pieceblack') zz.find('**/checker_k*').hide() y.reparentTo(z) y.hide() zz.reparentTo(z) zz.hide() return def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: self.seatPos = self.table.tableState.index( base.localAvatar.doId) def handleSleep(self, task=None): if self.fsm.getCurrentState().getName() == 'waitingToBegin': self.exitButtonPushed() if task != None: task.done return def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None return def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None return def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState( ).getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0 and timerEnd != 0: if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() return def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(-0.74, 0, -0.2) if self.isMyTurn: self.clockNode.countdown(timeLeft, self.doNothing) else: self.clockNode.countdown(timeLeft, self.doNothing) self.clockNode.show() return def gameStart(self, playerNum): if playerNum != 255: self.playerNum = playerNum if self.playerNum == 1: self.playerColorString = 'white' else: self.playerColorString = 'black' self.playerColor = self.playerColors[(playerNum - 1)] self.moveCameraForGame() self.fsm.request('playing') def sendTurn(self, playersTurn): if self.fsm.getCurrentState().getName() == 'playing': if playersTurn == self.playerNum: self.isMyTurn = True self.enableTurnScreenText(playersTurn) def illegalMove(self): self.exitButtonPushed() def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.finish() rotation = 0 if self.seatPos > 2: if self.playerNum == 1: rotation = 180 else: if self.playerNum == 2: rotation = 0 for x in self.locatorList: x.setH(180) self.isRotated = True else: if self.playerNum == 1: rotation = 0 else: if self.playerNum == 2: rotation = 180 for x in self.locatorList: x.setH(180) self.isRotated = True int = LerpHprInterval( self.boardNode, 4.2, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) int.start() def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() return def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() return def enterGameOver(self): pass def exitGameOver(self): pass def exitWaitCountdown(self): self.__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersGetUpButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self=self: self.exitButtonPushed()) return def enableScreenText(self): defaultPos = (-0.8, -0.4) if self.playerNum == 1: message = TTLocalizer.CheckersColorWhite color = Vec4(1, 1, 1, 1) else: if self.playerNum == 2: message = TTLocalizer.CheckersColorBlack color = Vec4(0, 0, 0, 1) else: message = TTLocalizer.CheckersObserver color = Vec4(0, 0, 0, 1) defaultPos = (-0.8, -0.4) self.screenText = OnscreenText(text=message, pos=defaultPos, scale=0.1, fg=color, align=TextNode.ACenter, mayChange=1) def enableStartButton(self): self.startButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersStartButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.6, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.1), scale=0.15, command=lambda self=self: self.startButtonPushed()) return def enableLeaveButton(self): self.leaveButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersQuitButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.13), text_scale=0.5, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self=self: self.exitButtonPushed()) return def enableTurnScreenText(self, player): playerOrder = [1, 4, 2, 5, 3, 6] message1 = TTLocalizer.CheckersIts if self.turnText != None: self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) else: if player == 1: message2 = TTLocalizer.CheckersWhiteTurn color = (1, 1, 1, 1) else: if player == 2: message2 = TTLocalizer.CheckersBlackTurn color = (0, 0, 0, 1) self.turnText = OnscreenText(text=message1 + message2, pos=(-0.8, -0.5), scale=0.092, fg=color, align=TextNode.ACenter, mayChange=1) return def startButtonPushed(self): self.sendUpdate('requestBegin') self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate('requestExit') def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True: mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() pickedObj = self.myHandler.getEntry(0).getIntoNodePath() pickedObj = pickedObj.getNetTag('GamePeiceLocator') if pickedObj: self.handleClicked(int(pickedObj)) def handleClicked(self, index): self.sound = Sequence(SoundInterval(self.clickSound)) if self.moveList == []: if index not in self.mySquares and index not in self.myKings: return self.moveList.append(index) type = self.board.squareList[index].getState() if type == 3 or type == 4: self.moverType = 'king' else: self.moverType = 'normal' self.blinker = Sequence() col = self.locatorList[index].getColor() self.blinker.append( LerpColorInterval(self.locatorList[index], 0.7, self.tintConstant, col)) self.blinker.append( LerpColorInterval(self.locatorList[index], 0.7, col, self.tintConstant)) self.blinker.loop() self.sound.start() else: if index in self.mySquares or index in self.myKings: for x in self.moveList: self.locatorList[x].setColor(1, 1, 1, 1) self.locatorList[x].hide() self.blinker.finish() self.blinker = Sequence() col = self.locatorList[index].getColor() self.blinker.append( LerpColorInterval(self.locatorList[index], 0.7, self.tintConstant, col)) self.blinker.append( LerpColorInterval(self.locatorList[index], 0.7, col, self.tintConstant)) self.blinker.loop() self.sound.start() self.locatorList[self.moveList[0]].show() self.moveList = [] self.moveList.append(index) type = self.board.squareList[index].getState() if type == 3 or type == 4: self.moverType = 'king' else: self.moverType = 'normal' else: self.currentMove = index lastItem = self.board.squareList[self.moveList[( len(self.moveList) - 1)]] thisItem = self.board.squareList[index] if self.mustJump == True: if lastItem.getNum() == index: self.blinker.finish() self.d_requestMove(self.moveList) self.isMyTurn = False self.moveList = [] return if self.checkLegalJump(lastItem, thisItem, self.moverType) == True: col = self.locatorList[index].getColor() self.locatorList[index].show() self.sound.start() if self.existsLegalJumpsFrom(index, self.moverType) == False: self.moveList.append(index) self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False else: self.moveList.append(index) if self.playerColorString == 'white': x = self.locatorList[index].getChildren()[1] x.show() else: x = self.locatorList[index].getChildren()[2] x.show() if self.moverType == 'king': x.find('**/checker_k*').show() self.locatorList[index].setColor( Vec4(0.5, 0.5, 0.5, 0.5)) else: if self.checkLegalMove(lastItem, thisItem, self.moverType) == True: self.moveList.append(index) col = self.locatorList[index].getColor() self.locatorList[index].show() self.sound.start() self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False def existsLegalJumpsFrom(self, index, peice): if peice == 'king': for x in range(4): if self.board.squareList[index].getAdjacent( )[x] != None and self.board.squareList[index].getJumps( )[x] != None: adj = self.board.squareList[ self.board.squareList[index].getAdjacent()[x]] jump = self.board.squareList[ self.board.squareList[index].getJumps()[x]] if adj.getState() == 0: pass elif adj.getState() == self.playerNum or adj.getState( ) == self.playerNum + 2: pass elif jump.getState() == 0: if index not in self.moveList and jump.getNum( ) not in self.moveList: return True return False if peice == 'normal': if self.playerNum == 1: moveForward = [1, 2] else: if self.playerNum == 2: moveForward = [0, 3] for x in moveForward: if self.board.squareList[index].getAdjacent( )[x] != None and self.board.squareList[index].getJumps( )[x] != None: adj = self.board.squareList[ self.board.squareList[index].getAdjacent()[x]] jump = self.board.squareList[ self.board.squareList[index].getJumps()[x]] if adj.getState() == 0: pass elif adj.getState() == self.playerNum or adj.getState( ) == self.playerNum + 2: pass elif jump.getState() == 0: if index not in self.moveList: return True return False return def existsLegalMovesFrom(self, index, peice): if peice == 'king': for x in self.board.squareList[index].getAdjacent(): if x != None: if self.board.squareList[x].getState() == 0: return True return False if peice == 'normal': if self.playerNum == 1: moveForward = [1, 2] else: if self.playerNum == 2: moveForward = [0, 3] for x in moveForward: if self.board.squareList[index].getAdjacent()[x] != None: adj = self.board.squareList[ self.board.squareList[index].getAdjacent()[x]] if adj.getState() == 0: return True return False return def checkLegalMove(self, firstSquare, secondSquare, peice): if firstSquare.getNum() not in self.mySquares and firstSquare.getNum( ) not in self.myKings: return False if self.playerNum == 1: moveForward = [1, 2] else: moveForward = [0, 3] if peice == 'king': for x in range(4): if firstSquare.getAdjacent()[x] != None: if self.board.squareList[firstSquare.getAdjacent( )[x]].getState() == 0 and secondSquare.getNum( ) in firstSquare.getAdjacent(): return True return False if peice == 'normal': for x in moveForward: if firstSquare.getAdjacent( )[x] != None and secondSquare.getNum( ) in firstSquare.getAdjacent(): if self.board.squareList[firstSquare.getAdjacent( )[x]].getState() == 0 and firstSquare.getAdjacent().index( secondSquare.getNum()) == x: return True return False return def checkLegalJump(self, firstSquare, secondSquare, peice): if firstSquare.getNum() not in self.mySquares and firstSquare.getNum( ) not in self.myKings and len(self.moveList) == 1: return False if self.playerNum == 1: moveForward = [1, 2] opposingPeices = [2, 4] else: moveForward = [0, 3] opposingPeices = [1, 3] if peice == 'king': if secondSquare.getNum() in firstSquare.getJumps(): index = firstSquare.getJumps().index(secondSquare.getNum()) if self.board.squareList[firstSquare.getAdjacent() [index]].getState() in opposingPeices: return True return False else: if peice == 'normal': if secondSquare.getNum() in firstSquare.getJumps(): index = firstSquare.getJumps().index(secondSquare.getNum()) if index in moveForward: if self.board.squareList[firstSquare.getAdjacent( )[index]].getState() in opposingPeices: return True return False else: return False else: return False def d_requestMove(self, moveList): self.sendUpdate('requestMove', [moveList]) def setGameState(self, tableState, moveList): if moveList != []: if self.board.squareList[moveList[0]].getState( ) == 1 or self.board.squareList[moveList[0]].getState() == 3: playerColor = 'white' else: playerColor = 'black' if self.board.squareList[moveList[0]].getState() <= 2: self.animatePeice(tableState, moveList, 'normal', playerColor) else: self.animatePeice(tableState, moveList, 'king', playerColor) else: self.updateGameState(tableState) def updateGameState(self, squares): self.board.setStates(squares) self.mySquares = [] self.myKings = [] messenger.send('wakeup') isObserve = False if self.playerNum == None: self.playerNum = 1 self.playerColorString = 'white' isObserve = True for xx in range(32): for blah in self.locatorList[xx].getChildren(): blah.hide() if self.locatorList[xx].getChildren().index(blah) != 0: blah1 = blah.find('**/checker_k*') owner = self.board.squareList[xx].getState() if owner == self.playerNum: if self.playerColorString == 'white': x = self.locatorList[xx].getChildren()[1] x.show() x.find('**/checker_k*').hide() else: x = self.locatorList[xx].getChildren()[2] x.show() x.find('**/checker_k*').hide() self.mySquares.append(xx) elif owner == 0: self.hideChildren(self.locatorList[xx].getChildren()) elif owner == self.playerNum + 2: if self.playerColorString == 'white': x = self.locatorList[xx].getChildren()[1] x.show() x.find('**/checker_k*').show() else: x = self.locatorList[xx].getChildren()[2] x.show() x.find('**/checker_k*').show() self.myKings.append(xx) elif owner <= 2: if self.playerColorString == 'white': x = self.locatorList[xx].getChildren()[2] x.show() x.find('**/checker_k*').hide() else: x = self.locatorList[xx].getChildren()[1] x.show() x.find('**/checker_k*').hide() elif self.playerColorString == 'white': x = self.locatorList[xx].getChildren()[2] x.show() x.find('**/checker_k*').show() else: x = self.locatorList[xx].getChildren()[1] x.show() x.find('**/checker_k*').show() if isObserve == True: self.playerNum = None self.playerColorString = None return self.mustJump = False self.hasNormalMoves = False for x in self.myKings: if self.existsLegalJumpsFrom(x, 'king') == True: self.mustJump = True break else: self.mustJump = False if self.mustJump == False: for x in self.mySquares: if self.existsLegalJumpsFrom(x, 'normal') == True: self.mustJump = True break else: self.mustJump = False if self.mustJump != True: for x in self.mySquares: if self.existsLegalMovesFrom(x, 'normal') == True: self.hasNormalMoves = True break else: self.hasNormalMoves = False if self.hasNormalMoves == False: for x in self.myKings: if self.existsLegalMovesFrom(x, 'king') == True: self.hasNormalMoves = True break else: self.hasNormalMoves = False if self.mustJump == False and self.hasNormalMoves == False: pass return def hideChildren(self, nodeList): for x in range(1, 2): nodeList[x].hide() def animatePeice(self, tableState, moveList, type, playerColor): messenger.send('wakeup') if playerColor == 'white': gamePeiceForAnimation = loader.loadModel( 'phase_6/models/golf/regular_checker_piecewhite') else: gamePeiceForAnimation = loader.loadModel( 'phase_6/models/golf/regular_checker_pieceblack') if type == 'king': gamePeiceForAnimation.find('**/checker_k*').show() else: gamePeiceForAnimation.find('**/checker_k*').hide() gamePeiceForAnimation.reparentTo(self.boardNode) gamePeiceForAnimation.setPos(self.locatorList[moveList[0]].getPos()) if self.isRotated == True: gamePeiceForAnimation.setH(180) for x in self.locatorList[moveList[0]].getChildren(): x.hide() checkersPeiceTrack = Sequence() length = len(moveList) for x in range(length - 1): checkersPeiceTrack.append( Parallel( SoundInterval(self.moveSound), ProjectileInterval( gamePeiceForAnimation, endPos=self.locatorList[moveList[(x + 1)]].getPos(), duration=0.5))) checkersPeiceTrack.append(Func(gamePeiceForAnimation.removeNode)) checkersPeiceTrack.append(Func(self.updateGameState, tableState)) checkersPeiceTrack.append(Func(self.unAlpha, moveList)) checkersPeiceTrack.start() def announceWin(self, avId): self.fsm.request('gameOver') def unAlpha(self, moveList): for x in moveList: self.locatorList[x].setColorOff() def doRandomMove(self): import random move = [] foundLegal = False self.blinker.pause() self.numRandomMoves += 1 while not foundLegal: x = random.randint(0, 9) for y in self.board.getAdjacent(self.mySquares[x]): if y != None and self.board.getState(y) == 0: move.append(self.mySquares[x]) move.append(y) foundLegal = True break if move == []: pass playSound = Sequence(SoundInterval(self.knockSound)) playSound.start() self.d_requestMove(move) self.moveList = [] self.isMyTurn = False if self.numRandomMoves >= 5: self.exitButtonPushed() return def doNothing(self): pass
class CogdoMazeGuiManager: def __init__(self, maze, bossCode): self.maze = maze self.root = NodePath('CogdoMazeGui') self.root.reparentTo(aspect2d) self.mazeMapGui = CogdoMazeMapGui(self.maze.collisionTable) if bossCode is not None: self._bossGui = CogdoMazeBossGui(bossCode) else: self._bossGui = None self._memoGui = CogdoMemoGui(self.root) self._memoGui.posNextToLaffMeter() self._presentGuiIval = None self._presentTimerIval = None self._hud = CogdoMazeHud() self._timer = None self._initMessageDisplay() return def _initTimer(self): self._timer = ToontownTimer() self._timer.hide() self._timer.posInTopRightCorner() def _initMessageDisplay(self): self.messageDisplay = CogdoGameMessageDisplay('CogdoMazeMessageDisplay', self.root, pos=Globals.MessageLabelPos) def destroy(self): ToontownIntervals.cleanup('present_gui') ToontownIntervals.cleanup('present_timer') ToontownIntervals.cleanup('present_memo') self._hud.destroy() self._hud = None self._memoGui.destroy() self._memoGui = None if self._bossGui is not None: self._bossGui.destroy() self._bossGui = None self.messageDisplay.destroy() self.messageDisplay = None self.destroyMazeMap() self.destroyTimer() if self._presentGuiIval: self._presentGuiIval.pause() self._presentGuiIval = None if self._presentTimerIval: self._presentTimerIval.pause() self._presentTimerIval = None return def destroyMazeMap(self): if hasattr(self, 'mazeMapGui') and self.mazeMapGui is not None: self.mazeMapGui.destroy() del self.mazeMapGui return def destroyTimer(self): if self._timer is not None: self._timer.stop() self._timer.destroy() self._timer = None return def showPickupCounter(self): ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._memoGui, 'present_memo')) def startGame(self, firstMessage): self._presentGuiIval = ToontownIntervals.start(Sequence(ToontownIntervals.getPresentGuiIval(self._bossGui, '', startPos=(0, 0, -0.15)), Func(self.mazeMapGui.show), ToontownIntervals.getPulseLargerIval(self.mazeMapGui, '', scale=self.mazeMapGui.getScale()), Func(self.setMessage, firstMessage), name='present_gui')) def hideMazeMap(self): self.mazeMapGui.hide() def showBossGui(self): if self._bossGui is not None: self._bossGui.show() return def hideBossGui(self): if self._bossGui is not None: self._bossGui.hide() return def revealMazeMap(self): self.mazeMapGui.revealAll() def hideLock(self, lockIndex): self.mazeMapGui.hideLock(lockIndex) def showTimer(self, duration, timerExpiredCallback = None): if self._timer is None: self._initTimer() self._timer.setTime(duration) self._timer.countdown(duration, timerExpiredCallback) self._presentTimerIval = ToontownIntervals.start(ToontownIntervals.getPresentGuiIval(self._timer, 'present_timer', startPos=(0, 0, 0.35))) return def hideTimer(self): if hasattr(self, 'timer') and self._timer is not None: self._timer.hide() self._timer.stop() return def setMessage(self, text, color = None, transition = 'fade'): self.messageDisplay.updateMessage(text, color, transition) def setMessageTemporary(self, text, time = 3.0): self.messageDisplay.showMessageTemporarily(text, time) def clearMessage(self): self.messageDisplay.updateMessage('') def setPickupCount(self, count): self._memoGui.setCount(count) def showBossCode(self, bossIndex): self._bossGui.showNumber(bossIndex) def showBossHit(self, bossIndex): self._bossGui.showHit(bossIndex) def showQuestArrow(self, toon, target, offset): self._hud.showQuestArrow(toon, target, offset) def hideQuestArrow(self): self._hud.hideQuestArrow()
class DistributedViewingBlock(DistributedStartingBlock): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedViewingBlock') sphereRadius = 6 def __init__(self, cr): DistributedStartingBlock.__init__(self, cr) self.timer = None return def delete(self): if self.timer is not None: self.timer.destroy() del self.timer DistributedStartingBlock.delete(self) return def generateInit(self): self.notify.debugStateCall(self) DistributedObject.DistributedObject.generateInit(self) self.nodePath = NodePath(self.uniqueName('StartingBlock')) self.collSphere = CollisionSphere(-1, 6.75, -1, self.sphereRadius) self.collSphere.setTangible(0) self.collNode = CollisionNode(self.uniqueName('StartingBlockSphere')) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.nodePath.attachNewNode(self.collNode) def announceGenerate(self): self.notify.debugStateCall(self) DistributedObject.DistributedObject.announceGenerate(self) self.nodePath.reparentTo(render) self.accept(self.uniqueName('enterStartingBlockSphere'), self.__handleEnterSphere) if (__debug__): if self.testLOD: self.__generateKartAppearTrack() def setPadLocationId(self, padLocationId): self.notify.debugStateCall(self) self.movieNode = self.nodePath.attachNewNode( self.uniqueName('MovieNode')) self.exitMovieNode = self.nodePath.attachNewNode( self.uniqueName('ExitMovieNode')) if padLocationId % 2: self.movieNode.setPosHpr(0, 6.5, 0, 0, 0, 0) else: self.movieNode.setPosHpr(0, -6.5, 0, 0, 0, 0) self.exitMovieNode.setPosHpr(3, 6.5, 0, 270, 0, 0) self.collNodePath.reparentTo(self.movieNode) def __handleEnterSphere(self, collEntry): if base.localAvatar.doId == self.lastAvId and globalClock.getFrameCount( ) <= self.lastFrame + 1: self.notify.debug('Ignoring duplicate entry for avatar.') return if base.localAvatar.hp > 0: def handleEnterRequest(self=self): self.ignore('stoppedAsleep') if hasattr(self.dialog, 'doneStatus') and self.dialog.doneStatus == 'ok': self.d_requestEnter() else: self.cr.playGame.getPlace().setState('walk') self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog self.cr.playGame.getPlace().fsm.request('stopped') self.accept('stoppedAsleep', handleEnterRequest) doneEvent = 'enterRequest|dialog' msg = TTLocalizer.StartingBlock_EnterShowPad self.dialog = TTGlobalDialog(msg, doneEvent, 4) self.dialog.accept(doneEvent, handleEnterRequest) def generateCameraMoveTrack(self): self.cPos = camera.getPos(self.av) self.cHpr = camera.getHpr(self.av) cameraPos = Point3(23, -10, 7) cameraHpr = Point3(65, -10, 0) camera.wrtReparentTo(self.nodePath) cameraTrack = LerpPosHprInterval(camera, 1.5, cameraPos, cameraHpr) return cameraTrack def makeGui(self): self.notify.debugStateCall(self) if self.timer is not None: return self.timer = ToontownTimer() self.timer.setScale(0.3) self.timer.setPos(-0.173333, 0, 0.27) self.timer.reparentTo(base.a2dBottomRight) self.timer.hide() DistributedStartingBlock.makeGui(self) return def showGui(self): self.notify.debugStateCall(self) self.timer.show() DistributedStartingBlock.showGui(self) def hideGui(self): self.notify.debugStateCall(self) if not hasattr(self, 'timer') or self.timer is None: return self.timer.reset() self.timer.hide() DistributedStartingBlock.hideGui(self) return def countdown(self): countdownTime = KartGlobals.COUNTDOWN_TIME - globalClockDelta.localElapsedTime( self.kartPad.getTimestamp(self.avId)) self.timer.countdown(countdownTime) def enterEnterMovie(self): self.notify.debug( '%d enterEnterMovie: Entering the Enter Movie State.' % self.doId) if base.config.GetBool('want-qa-regression', 0): raceName = "Display Block (No Race)" if hasattr(self.kartPad, "trackType"): raceName = TTLocalizer.KartRace_RaceNames[ self.kartPad.trackType] self.notify.info('QA-REGRESSION: KARTING: %s' % raceName) pos = self.nodePath.getPos(render) hpr = self.nodePath.getHpr(render) pos.addZ(1.7) hpr.addX(270) self.kartNode.setPosHpr(pos, hpr) toonTrack = self.generateToonMoveTrack() kartTrack = self.generateKartAppearTrack() jumpTrack = self.generateToonJumpTrack() name = self.av.uniqueName('EnterRaceTrack') if self.av is not None and self.localToonKarting: cameraTrack = self.generateCameraMoveTrack() self.finishMovie() self.movieTrack = Sequence(Parallel(cameraTrack, Sequence()), kartTrack, jumpTrack, Func(self.makeGui), Func(self.showGui), Func(self.countdown), Func(self.request, 'Waiting'), Func(self.d_movieFinished), name=name, autoFinish=1) else: self.finishMovie() self.movieTrack = Sequence(toonTrack, kartTrack, jumpTrack, name=name, autoFinish=1) self.movieTrack.start() self.exitRequested = True return
class DistributedGameTable(DistributedObject.DistributedObject): def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.tableModelPath = 'phase_6/models/golf/game_table.bam' self.numSeats = 6 self.__toonTracks = {} self.gameMenu = None self.game = None self.gameDoId = 0 self.timerFunc = None self.gameWantTimer = False self.cameraBoardTrack = None self.tutorial = None self.fsm = ClassicFSM.ClassicFSM( 'DistributedGameTable', [ State.State( 'off', self.enterOff, self.exitOff, ['chooseMode', 'observing'] ), State.State( 'chooseMode', self.enterChooseMode, self.exitChooseMode, ['sitting', 'off', 'observing'] ), State.State( 'sitting', self.enterSitting, self.exitSitting, ['off'] ), State.State( 'observing', self.enterObserving, self.exitObserving, ['off'] ) ], 'off', 'off') self.fsm.enterInitialState() def generate(self): DistributedObject.DistributedObject.generate(self) self.picnicTableNode = render.attachNewNode('gameTable') self.picnicTable = loader.loadModel(self.tableModelPath) self.picnicTable.reparentTo(self.picnicTableNode) self.loader = self.cr.playGame.hood.loader self.picnicTableNode.reparentTo(self.loader.geom) def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) self.tableCloth = self.picnicTable.find('**/basket_locator') cn = CollisionNode('tableCloth_sphere') self.tableClothSphereNode = self.tableCloth.attachNewNode(cn) cs = CollisionSphere(0, 0, -2, 5.5) self.tableClothSphereNode.node().addSolid(cs) self.seats = [] self.jumpOffsets = [] self.picnicTableSphereNodes = [] for i in xrange(self.numSeats): self.seats.append(self.picnicTable.find('**/*seat' + str(i+1))) self.jumpOffsets.append(self.picnicTable.find('**/*jumpOut' + str(i+1))) cn = CollisionNode('picnicTable_sphere_{0}_{1}'.format(self.doId, i)) self.picnicTableSphereNodes.append(self.seats[i].attachNewNode(cn)) cs = CollisionSphere(0, 0, 0, 2) self.picnicTableSphereNodes[i].node().addSolid(cs) self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui.bam') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') self.joinButton = None self.observeButton = None self.exitButton = None self.tutorialButton = None angle = self.picnicTable.getH() angle -= 90 radAngle = math.radians(angle) unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0) unitVec *= 30.0 self.endPos = self.picnicTable.getPos() + unitVec self.enableCollisions() def disable(self): DistributedObject.DistributedObject.disable(self) self.fsm.request('off') self.clearToonTracks() # TODO: Disable choice buttons. # TODO: Stop sleep tracking. self.destroyGameMenu() self.disableCollisions() del self.gameMenu if self.cameraBoardTrack: self.cameraBoardTrack.finish() del self.cameraBoardTrack del self.tableClothSphereNode del self.tableCloth del self.seats del self.jumpOffsets del self.picnicTableSphereNodes del self.clockNode self.buttonModels.removeNode() del self.buttonModels del self.endPos del self.loader self.picnicTable.removeNode() self.picnicTableNode.removeNode() def delete(self): DistributedObject.DistributedObject.delete(self) del self.fsm def enableCollisions(self): for i in xrange(self.numSeats): event = 'enterpicnicTable_sphere_{0}_{1}'.format(self.doId, i) self.accept(event, self.handleEnterPicnicTableSphere, [i]) self.picnicTableSphereNodes[i].setCollideMask(ToontownGlobals.WallBitmask) self.tableClothSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def disableCollisions(self): for i in xrange(self.numSeats): self.ignore('enterpicnicTable_sphere_{0}_{1}'.format(self.doId, i)) for i in xrange(self.numSeats): self.picnicTableSphereNodes[i].setCollideMask(BitMask32(0)) self.tableClothSphereNode.setCollideMask(BitMask32(0)) def handleEnterPicnicTableSphere(self, i, collEntry): self.fsm.request('chooseMode') def enterOff(self): base.setCellsAvailable(base.leftCells + base.bottomCells, 0) def exitOff(self): base.setCellsAvailable(base.bottomCells, 0) def enterChooseMode(self): self.enableChoiceButtons() def exitChooseMode(self): self.disableChoiceButtons() def enterObserving(self): pass def exitObserving(self): pass def enterSitting(self): pass def exitSitting(self): self.destroyGameMenu() def destroyGameMenu(self): if self.gameMenu: self.gameMenu.removeButtons() self.gameMenu.picnicFunction = None self.gameMenu = None def setPosHpr(self, x, y, z, h, p, r): self.picnicTable.setPosHpr(x, y, z, h, p, r) def storeToonTrack(self, avId, track): self.clearToonTrack(avId) self.__toonTracks[avId] = track def clearToonTrack(self, avId): oldTrack = self.__toonTracks.get(avId) if oldTrack: oldTrack.pause() cleanupDelayDeletes(oldTrack) def clearToonTracks(self): for avId in self.__toonTracks: self.clearToonTrack(avId) def showTimer(self): self.clockNode.stop() self.clockNode.countdown(self.timeLeft, self.timerFunc) self.clockNode.show() def setTimer(self, timerEnd): self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) self.timeLeft = int(time - globalClock.getRealTime()) if self.gameWantTimer and (self.game is not None): self.showTimer() def setTimerFunc(self, function): self.timerFunc = function def allowWalk(self): base.cr.playGame.getPlace().setState('walk') def disallowWalk(self): base.cr.playGame.getPlace().setState('stopped') def enableChoiceButtons(self): if (not self.game) or (not self.game.playing): self.joinButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableJoinButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, 0.8), scale=0.15, command=lambda self=self: self.joinButtonPushed()) else: self.observeButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableObserveButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, 0.6), scale=0.15, command=lambda self=self: self.observeButtonPushed()) self.exitButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableCancelButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(1, 0, 0.6), scale=0.15, command=lambda self=self: self.cancelButtonPushed()) self.tutorialButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableTutorial, text_fg=(1, 1, 0.65, 1), text_pos=(-0.05, -0.13), text_scale=0.55, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-1, 0, 0.6), scale=0.15, command=lambda self=self: self.tutorialButtonPushed()) self.disallowWalk() def disableChoiceButtons(self): if self.joinButton: self.joinButton.destroy() self.joinButton = None if self.observeButton: self.observeButton.destroy() self.observeButton = None if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.tutorialButton: self.tutorialButton.destroy() self.tutorialButton = None def joinButtonPushed(self): pass def observeButtonPushed(self): pass def cancelButtonPushed(self): self.allowWalk() self.fsm.request('off') def tutorialButtonPushed(self): self.disableChoiceButtons() self.gameMenu = PicnicGameSelectMenu( self.tutorialFunction, PicnicGameGlobals.TutorialMenu) def tutorialFunction(self, gameIndex): if gameIndex == PicnicGameGlobals.CheckersGameIndex: self.tutorial = CheckersTutorial(self.tutorialDone) elif gameIndex == PicnicGameGlobals.ChineseCheckersGameIndex: self.tutorial = ChineseCheckersTutorial(self.tutorialDone) else: self.cancelButtonPushed() self.destroyGameMenu() def tutorialDone(self): self.fsm.request('off') self.tutorial = None
class DistributedCheckers(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, 'DistributedCheckers') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel('phase_6/models/golf/regular_checker_game.bam') self.boardNode.reparentTo(self) self.board = CheckersBoard() self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.moveList = [] self.mySquares = [] self.myKings = [] self.isRotated = False self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = base.camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.playerColors = [Vec4(0, 0, 1, 1), Vec4(0, 1, 0, 1)] self.tintConstant = Vec4(0.25, 0.25, 0.25, 0.5) self.ghostConstant = Vec4(0, 0, 0, 0.8) self.startingPositions = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]] self.knockSound = base.loadSfx('phase_5/audio/sfx/GUI_knock_1.ogg') self.clickSound = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.ogg') self.moveSound = base.loadSfx('phase_6/audio/sfx/CC_move.ogg') self.accept('stoppedAsleep', self.handleSleep) self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin'])], 'waitingToBegin', 'waitingToBegin') x = self.boardNode.find('**/locator*') self.locatorList = x.getChildren() tempList = [] for x in xrange(0, 32): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) tempList.append(self.locatorList[x].attachNewNode(CollisionNode('picker%d' % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.39)) for z in self.locatorList: y = loader.loadModel('phase_6/models/golf/regular_checker_piecewhite.bam') y.find('**/checker_k*').hide() zz = loader.loadModel('phase_6/models/golf/regular_checker_pieceblack.bam') zz.find('**/checker_k*').hide() y.reparentTo(z) y.hide() zz.reparentTo(z) zz.hide() return def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: self.seatPos = self.table.tableState.index(base.localAvatar.doId) def handleSleep(self, task = None): if self.fsm.getCurrentState().getName() == 'waitingToBegin': self.exitButtonPushed() if task != None: task.done return def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None return def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None return def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState().getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0 and timerEnd != 0: if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() return def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(-.74, 0, -0.2) if self.isMyTurn: self.clockNode.countdown(timeLeft, self.doNothing) else: self.clockNode.countdown(timeLeft, self.doNothing) self.clockNode.show() return def gameStart(self, playerNum): if playerNum != 255: self.playerNum = playerNum if self.playerNum == 1: self.playerColorString = 'white' else: self.playerColorString = 'black' self.playerColor = self.playerColors[playerNum - 1] self.moveCameraForGame() self.fsm.request('playing') def sendTurn(self, playersTurn): if self.fsm.getCurrentState().getName() == 'playing': if playersTurn == self.playerNum: self.isMyTurn = True self.enableTurnScreenText(playersTurn) def illegalMove(self): self.exitButtonPushed() def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.finish() rotation = 0 if self.seatPos > 2: if self.playerNum == 1: rotation = 180 elif self.playerNum == 2: rotation = 0 for x in self.locatorList: x.setH(180) self.isRotated = True elif self.playerNum == 1: rotation = 0 elif self.playerNum == 2: rotation = 180 for x in self.locatorList: x.setH(180) self.isRotated = True int = LerpHprInterval(self.boardNode, 4.2, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) int.start() def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() return def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() return def enterGameOver(self): pass def exitGameOver(self): pass def exitWaitCountdown(self): self.__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersGetUpButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self = self: self.exitButtonPushed()) return def enableScreenText(self): defaultPos = (-.8, -0.4) if self.playerNum == 1: message = TTLocalizer.CheckersColorWhite color = Vec4(1, 1, 1, 1) elif self.playerNum == 2: message = TTLocalizer.CheckersColorBlack color = Vec4(0, 0, 0, 1) else: message = TTLocalizer.CheckersObserver color = Vec4(0, 0, 0, 1) defaultPos = (-.8, -0.4) self.screenText = OnscreenText(text=message, pos=defaultPos, scale=0.1, fg=color, align=TextNode.ACenter, mayChange=1) def enableStartButton(self): self.startButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersStartButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.6, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.1), scale=0.15, command=lambda self = self: self.startButtonPushed()) return def enableLeaveButton(self): self.leaveButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersQuitButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.13), text_scale=0.5, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self = self: self.exitButtonPushed()) return def enableTurnScreenText(self, player): playerOrder = [1, 4, 2, 5, 3, 6] message1 = TTLocalizer.CheckersIts if self.turnText != None: self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) elif player == 1: message2 = TTLocalizer.CheckersWhiteTurn color = (1, 1, 1, 1) elif player == 2: message2 = TTLocalizer.CheckersBlackTurn color = (0, 0, 0, 1) self.turnText = OnscreenText(text=message1 + message2, pos=(-0.8, -0.5), scale=0.092, fg=color, align=TextNode.ACenter, mayChange=1) return def startButtonPushed(self): self.sendUpdate('requestBegin') self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate('requestExit') def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True: mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() pickedObj = self.myHandler.getEntry(0).getIntoNodePath() pickedObj = pickedObj.getNetTag('GamePeiceLocator') if pickedObj: self.handleClicked(int(pickedObj)) def handleClicked(self, index): self.sound = Sequence(SoundInterval(self.clickSound)) if self.moveList == []: if index not in self.mySquares and index not in self.myKings: return self.moveList.append(index) type = self.board.squareList[index].getState() if type == 3 or type == 4: self.moverType = 'king' else: self.moverType = 'normal' self.blinker = Sequence() col = self.locatorList[index].getColor() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.tintConstant, col)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, col, self.tintConstant)) self.blinker.loop() self.sound.start() elif index in self.mySquares or index in self.myKings: for x in self.moveList: self.locatorList[x].setColor(1, 1, 1, 1) self.locatorList[x].hide() self.blinker.finish() self.blinker = Sequence() col = self.locatorList[index].getColor() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.tintConstant, col)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, col, self.tintConstant)) self.blinker.loop() self.sound.start() self.locatorList[self.moveList[0]].show() self.moveList = [] self.moveList.append(index) type = self.board.squareList[index].getState() if type == 3 or type == 4: self.moverType = 'king' else: self.moverType = 'normal' else: self.currentMove = index lastItem = self.board.squareList[self.moveList[len(self.moveList) - 1]] thisItem = self.board.squareList[index] if self.mustJump == True: if lastItem.getNum() == index: self.blinker.finish() self.d_requestMove(self.moveList) self.isMyTurn = False self.moveList = [] return if self.checkLegalJump(lastItem, thisItem, self.moverType) == True: col = self.locatorList[index].getColor() self.locatorList[index].show() self.sound.start() if self.existsLegalJumpsFrom(index, self.moverType) == False: self.moveList.append(index) self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False else: self.moveList.append(index) if self.playerColorString == 'white': x = self.locatorList[index].getChildren()[1] x.show() else: x = self.locatorList[index].getChildren()[2] x.show() if self.moverType == 'king': x.find('**/checker_k*').show() self.locatorList[index].setColor(Vec4(0.5, 0.5, 0.5, 0.5)) elif self.checkLegalMove(lastItem, thisItem, self.moverType) == True: self.moveList.append(index) col = self.locatorList[index].getColor() self.locatorList[index].show() self.sound.start() self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False def existsLegalJumpsFrom(self, index, peice): if peice == 'king': for x in xrange(4): if self.board.squareList[index].getAdjacent()[x] != None and \ self.board.squareList[index].getJumps()[x] != None: adj = self.board.squareList[self.board.squareList[index].getAdjacent()[x]] jump = self.board.squareList[self.board.squareList[index].getJumps()[x]] if adj.getState() == 0: pass elif adj.getState() == self.playerNum or adj.getState() == self.playerNum + 2: pass elif jump.getState() == 0: if index not in self.moveList and jump.getNum() not in self.moveList: return True return False elif peice == 'normal': if self.playerNum == 1: moveForward = [1, 2] elif self.playerNum == 2: moveForward = [0, 3] for x in moveForward: if self.board.squareList[index].getAdjacent()[x] != None and \ self.board.squareList[index].getJumps()[x] != None: adj = self.board.squareList[self.board.squareList[index].getAdjacent()[x]] jump = self.board.squareList[self.board.squareList[index].getJumps()[x]] if adj.getState() == 0: pass elif adj.getState() == self.playerNum or adj.getState() == self.playerNum + 2: pass elif jump.getState() == 0: if index not in self.moveList: return True return False def existsLegalMovesFrom(self, index, peice): if peice == 'king': for x in self.board.squareList[index].getAdjacent(): if x != None: if self.board.squareList[x].getState() == 0: return True return False elif peice == 'normal': if self.playerNum == 1: moveForward = [1, 2] elif self.playerNum == 2: moveForward = [0, 3] for x in moveForward: if self.board.squareList[index].getAdjacent()[x] != None: adj = self.board.squareList[self.board.squareList[index].getAdjacent()[x]] if adj.getState() == 0: return True return False return def checkLegalMove(self, firstSquare, secondSquare, peice): if firstSquare.getNum() not in self.mySquares and firstSquare.getNum() not in self.myKings: return False if self.playerNum == 1: moveForward = [1, 2] else: moveForward = [0, 3] if peice == 'king': for x in xrange(4): if firstSquare.getAdjacent()[x] != None: if self.board.squareList[firstSquare.getAdjacent()[x]].getState() == 0 and secondSquare.getNum() in firstSquare.getAdjacent(): return True return False elif peice == 'normal': for x in moveForward: if firstSquare.getAdjacent()[x] != None and secondSquare.getNum() in firstSquare.getAdjacent(): if self.board.squareList[firstSquare.getAdjacent()[x]].getState() == 0 and firstSquare.getAdjacent().index(secondSquare.getNum()) == x: return True return False return def checkLegalJump(self, firstSquare, secondSquare, peice): if firstSquare.getNum() not in self.mySquares and firstSquare.getNum() not in self.myKings and len(self.moveList) == 1: return False if self.playerNum == 1: moveForward = [1, 2] opposingPeices = [2, 4] else: moveForward = [0, 3] opposingPeices = [1, 3] if peice == 'king': if secondSquare.getNum() in firstSquare.getJumps(): index = firstSquare.getJumps().index(secondSquare.getNum()) if self.board.squareList[firstSquare.getAdjacent()[index]].getState() in opposingPeices: return True else: return False elif peice == 'normal': if secondSquare.getNum() in firstSquare.getJumps(): index = firstSquare.getJumps().index(secondSquare.getNum()) if index in moveForward: if self.board.squareList[firstSquare.getAdjacent()[index]].getState() in opposingPeices: return True else: return False else: return False else: return False def d_requestMove(self, moveList): self.sendUpdate('requestMove', [moveList]) def setGameState(self, tableState, moveList): if moveList != []: if self.board.squareList[moveList[0]].getState() == 1 or self.board.squareList[moveList[0]].getState() == 3: playerColor = 'white' else: playerColor = 'black' if self.board.squareList[moveList[0]].getState() <= 2: self.animatePeice(tableState, moveList, 'normal', playerColor) else: self.animatePeice(tableState, moveList, 'king', playerColor) else: self.updateGameState(tableState) def updateGameState(self, squares): self.board.setStates(squares) self.mySquares = [] self.myKings = [] messenger.send('wakeup') isObserve = False if self.playerNum == None: self.playerNum = 1 self.playerColorString = 'white' isObserve = True for xx in xrange(32): for blah in self.locatorList[xx].getChildren(): blah.hide() if self.locatorList[xx].getChildren().index(blah) != 0: blah1 = blah.find('**/checker_k*') owner = self.board.squareList[xx].getState() if owner == self.playerNum: if self.playerColorString == 'white': x = self.locatorList[xx].getChildren()[1] x.show() x.find('**/checker_k*').hide() else: x = self.locatorList[xx].getChildren()[2] x.show() x.find('**/checker_k*').hide() self.mySquares.append(xx) elif owner == 0: self.hideChildren(self.locatorList[xx].getChildren()) elif owner == self.playerNum + 2: if self.playerColorString == 'white': x = self.locatorList[xx].getChildren()[1] x.show() x.find('**/checker_k*').show() else: x = self.locatorList[xx].getChildren()[2] x.show() x.find('**/checker_k*').show() self.myKings.append(xx) elif owner <= 2: if self.playerColorString == 'white': x = self.locatorList[xx].getChildren()[2] x.show() x.find('**/checker_k*').hide() else: x = self.locatorList[xx].getChildren()[1] x.show() x.find('**/checker_k*').hide() elif self.playerColorString == 'white': x = self.locatorList[xx].getChildren()[2] x.show() x.find('**/checker_k*').show() else: x = self.locatorList[xx].getChildren()[1] x.show() x.find('**/checker_k*').show() if isObserve == True: self.playerNum = None self.playerColorString = None return self.mustJump = False self.hasNormalMoves = False for x in self.myKings: if self.existsLegalJumpsFrom(x, 'king') == True: self.mustJump = True break else: self.mustJump = False if self.mustJump == False: for x in self.mySquares: if self.existsLegalJumpsFrom(x, 'normal') == True: self.mustJump = True break else: self.mustJump = False if self.mustJump != True: for x in self.mySquares: if self.existsLegalMovesFrom(x, 'normal') == True: self.hasNormalMoves = True break else: self.hasNormalMoves = False if self.hasNormalMoves == False: for x in self.myKings: if self.existsLegalMovesFrom(x, 'king') == True: self.hasNormalMoves = True break else: self.hasNormalMoves = False if self.mustJump == False and self.hasNormalMoves == False: pass return def hideChildren(self, nodeList): for x in xrange(1, 2): nodeList[x].hide() def animatePeice(self, tableState, moveList, type, playerColor): messenger.send('wakeup') if playerColor == 'white': gamePeiceForAnimation = loader.loadModel('phase_6/models/golf/regular_checker_piecewhite.bam') else: gamePeiceForAnimation = loader.loadModel('phase_6/models/golf/regular_checker_pieceblack.bam') if type == 'king': gamePeiceForAnimation.find('**/checker_k*').show() else: gamePeiceForAnimation.find('**/checker_k*').hide() gamePeiceForAnimation.reparentTo(self.boardNode) gamePeiceForAnimation.setPos(self.locatorList[moveList[0]].getPos()) if self.isRotated == True: gamePeiceForAnimation.setH(180) for x in self.locatorList[moveList[0]].getChildren(): x.hide() checkersPeiceTrack = Sequence() length = len(moveList) for x in xrange(length - 1): checkersPeiceTrack.append(Parallel(SoundInterval(self.moveSound), ProjectileInterval(gamePeiceForAnimation, endPos=self.locatorList[moveList[x + 1]].getPos(), duration=0.5))) checkersPeiceTrack.append(Func(gamePeiceForAnimation.removeNode)) checkersPeiceTrack.append(Func(self.updateGameState, tableState)) checkersPeiceTrack.append(Func(self.unAlpha, moveList)) checkersPeiceTrack.start() def announceWin(self, avId): self.fsm.request('gameOver') def unAlpha(self, moveList): for x in moveList: self.locatorList[x].setColorOff() def doRandomMove(self): import random move = [] foundLegal = False self.blinker.pause() self.numRandomMoves += 1 while not foundLegal: x = random.randint(0, 9) for y in self.board.getAdjacent(self.mySquares[x]): if y != None and self.board.getState(y) == 0: move.append(self.mySquares[x]) move.append(y) foundLegal = True break if move == []: pass playSound = Sequence(SoundInterval(self.knockSound)) playSound.start() self.d_requestMove(move) self.moveList = [] self.isMyTurn = False if self.numRandomMoves >= 5: self.exitButtonPushed() return def doNothing(self): pass
class DistributedFindFour(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, 'DistributedFindFour') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel('phase_6/models/golf/findfour_game.bam') self.boardNode.reparentTo(self) self.board = [[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]] self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.winningSequence = Sequence() self.moveSequence = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None self.moveCol = None self.move = None self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(BitMask32(4096)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.tintConstant = Vec4(0.25, 0.25, 0.25, 0) self.ghostConstant = Vec4(0, 0, 0, 0.5) self.knockSound = base.loadSfx('phase_5/audio/sfx/GUI_knock_1.ogg') self.clickSound = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.ogg') self.moveSound = base.loadSfx('phase_6/audio/sfx/CC_move.ogg') self.accept('stoppedAsleep', self.handleSleep) from direct.fsm import ClassicFSM, State self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin'])], 'waitingToBegin', 'waitingToBegin') startLoc = self.boardNode.find('**/locators') self.locatorList = startLoc.getChildren() self.startingPositions = self.locatorList.pop(0) self.startingPositions = self.startingPositions.getChildren() instancePiece = self.boardNode.find('**/pieces') tempList = [] for x in xrange(7): self.startingPositions[x].setTag('StartLocator', '%d' % x) collNode = CollisionNode('startpicker%d' % x) collNode.setIntoCollideMask(BitMask32(4096)) tempList.append(self.startingPositions[x].attachNewNode(collNode)) tempList[x].node().addSolid(CollisionTube(0, 0, 0.23, 0, 0, -.23, 0.2)) for z in self.startingPositions: y = instancePiece.copyTo(z) for val in y.getChildren(): val.hide() tempList = [] for x in xrange(42): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) collNode = CollisionNode('startpicker%d' % x) collNode.setIntoCollideMask(BitMask32(4096)) tempList.append(self.locatorList[x].attachNewNode(collNode)) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.2)) for z in self.locatorList: y = instancePiece.copyTo(z) for val in y.getChildren(): val.hide() dummyHide = instancePiece.getParent().attachNewNode('DummyHider') instancePiece.reparentTo(dummyHide) dummyHide.hide() return def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: self.seatPos = self.table.tableState.index(base.localAvatar.doId) if self.seatPos <= 2: for x in self.startingPositions: x.setH(0) for x in self.locatorList: x.setH(0) else: for x in self.startingPositions: x.setH(180) for x in self.locatorList: x.setH(180) self.moveCameraForGame() else: self.seatPos = self.table.seatBumpForObserve if self.seatPos > 2: for x in self.startingPositions: x.setH(180) for x in self.locatorList: x.setH(180) self.moveCameraForGame() def handleSleep(self, task = None): if self.fsm.getCurrentState().getName() == 'waitingToBegin': self.exitButtonPushed() if task != None: task.done return def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None taskMgr.remove('playerTurnTask') return def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None self.winningSequence.finish() taskMgr.remove('playerTurnTask') return def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState().getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0 and timerEnd != 0: if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() return def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(0.64, 0, -0.27) self.clockNode.countdown(timeLeft, self.doRandomMove) self.clockNode.show() return def gameStart(self, playerNum): if playerNum != 255: self.playerNum = playerNum if self.playerNum == 1: self.playerColorString = 'Red' else: self.playerColorString = 'Yellow' self.moveCameraForGame() self.fsm.request('playing') def sendTurn(self, playersTurn): if self.fsm.getCurrentState().getName() == 'playing': if playersTurn == self.playerNum: self.isMyTurn = True taskMgr.add(self.turnTask, 'playerTurnTask') self.enableTurnScreenText(playersTurn) def illegalMove(self): self.exitButtonPushed() def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.pause() rotation = 0 if self.seatPos <= 2: position = self.table.seats[1].getPos() position = position + Vec3(0, -8, 12.8) int = LerpPosHprInterval(camera, 2, position, Vec3(0, -38, 0), camera.getPos(), camera.getHpr()) else: position = self.table.seats[4].getPos() position = position + Vec3(0, -8, 12.8) if camera.getH() < 0: int = LerpPosHprInterval(camera, 2, position, Vec3(-180, -20, 0), camera.getPos(), camera.getHpr()) else: int = LerpPosHprInterval(camera, 2, position, Vec3(180, -20, 0), camera.getPos(), camera.getHpr()) int.start() def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() return def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() return def enterGameOver(self): pass def exitGameOver(self): pass def exitWaitCountdown(self): self.__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersGetUpButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.8), scale=0.15, command=lambda self = self: self.exitButtonPushed()) return def enableScreenText(self): defaultPos = (-.7, -0.29) if self.playerNum == 1: message = 'You are Red' color = Vec4(1, 0, 0, 1) elif self.playerNum == 2: message = 'You are Yellow' color = Vec4(1, 1, 0, 1) else: message = TTLocalizer.CheckersObserver color = Vec4(0, 0, 0, 1) self.screenText = OnscreenText(text=message, pos=defaultPos, scale=0.1, fg=color, align=TextNode.ACenter, mayChange=1) def enableStartButton(self): self.startButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersStartButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.6, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.57), scale=0.15, command=lambda self = self: self.startButtonPushed()) return def enableLeaveButton(self): self.leaveButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersQuitButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.13), text_scale=0.5, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.8), scale=0.15, command=lambda self = self: self.exitButtonPushed()) return def enableTurnScreenText(self, player): playerOrder = [1, 4, 2, 5, 3, 6] message1 = TTLocalizer.CheckersIts if self.turnText != None: self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) elif player == 1: message2 = "Red's Turn" color = (1, 0, 0, 1) elif player == 2: message2 = "Yellow's Turn" color = (1, 1, 0, 1) self.turnText = OnscreenText(text=message1 + message2, pos=(-0.7, -0.39), scale=0.092, fg=color, align=TextNode.ACenter, mayChange=1) return def startButtonPushed(self): self.sendUpdate('requestBegin') self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate('requestExit') def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True and not self.moveSequence.isPlaying(): if self.moveCol != None: self.d_requestMove(self.moveCol) self.moveCol = None self.isMyTurn = False taskMgr.remove('playerTurnTask') return def handleClicked(self, index): pass def turnTask(self, task): if base.mouseWatcherNode.hasMouse() == False: return task.cont if self.isMyTurn == False: return task.cont if self.moveSequence.isPlaying(): return task.cont mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() pickedObj = self.myHandler.getEntry(0).getIntoNodePath() pickedObj = pickedObj.getNetTag('StartLocator') if pickedObj: colVal = int(pickedObj) if colVal == self.moveCol: return task.cont if self.board[0][colVal] == 0: if self.moveCol != None: for x in self.startingPositions[self.moveCol].getChild(1).getChildren(): x.hide() self.moveCol = colVal if self.playerNum == 1: self.startingPositions[self.moveCol].getChild(1).getChild(2).show() elif self.playerNum == 2: self.startingPositions[self.moveCol].getChild(1).getChild(3).show() return task.cont def d_requestMove(self, moveCol): self.sendUpdate('requestMove', [moveCol]) def setGameState(self, tableState, moveCol, movePos, turn): messenger.send('wakeup') if self.table.fsm.getCurrentState().getName() == 'observing': isBlank = True for x in xrange(7): if self.board[5][x] != 0: isBlank = False break gameBlank = True for x in xrange(7): if tableState[5][x] != 0: gameBlank = False break if isBlank == True and gameBlank == False: for x in xrange(6): for y in xrange(7): self.board[x][y] = tableState[x][y] self.updateGameState() return if moveCol == 0 and movePos == 0 and turn == 0: for x in xrange(6): for y in xrange(7): self.board[x][y] = tableState[x][y] self.updateGameState() else: self.animatePeice(tableState, moveCol, movePos, turn) didIWin = self.checkForWin() if didIWin != None: self.sendUpdate('requestWin', [didIWin]) return def updateGameState(self): for x in xrange(6): for y in xrange(7): for z in self.locatorList[x * 7 + y].getChild(1).getChildren(): z.hide() for x in xrange(6): for y in xrange(7): state = self.board[x][y] if state == 1: self.locatorList[x * 7 + y].getChild(1).getChild(0).show() elif state == 2: self.locatorList[x * 7 + y].getChild(1).getChild(1).show() def checkForWin(self): for x in xrange(6): for y in xrange(7): if self.board[x][y] == self.playerNum: if self.checkHorizontal(x, y, self.playerNum) == True: return [x, y] elif self.checkVertical(x, y, self.playerNum) == True: return [x, y] elif self.checkDiagonal(x, y, self.playerNum) == True: return [x, y] return None def announceWinnerPosition(self, x, y, winDirection, playerNum): self.isMyturn = False if self.turnText: self.turnText.hide() self.clockNode.stop() self.clockNode.hide() if winDirection == 0: blinkList = self.findHorizontal(x, y, playerNum) elif winDirection == 1: blinkList = self.findVertical(x, y, playerNum) elif winDirection == 2: blinkList = self.findDiagonal(x, y, playerNum) if blinkList != []: print blinkList val0 = x * 7 + y x = blinkList[0][0] y = blinkList[0][1] val1 = x * 7 + y x = blinkList[1][0] y = blinkList[1][1] val2 = x * 7 + y x = blinkList[2][0] y = blinkList[2][1] val3 = x * 7 + y self.winningSequence = Sequence() downBlinkerParallel = Parallel(LerpColorInterval(self.locatorList[val0], 0.3, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[val1], 0.3, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[val2], 0.3, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[val3], 0.3, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1))) upBlinkerParallel = Parallel(LerpColorInterval(self.locatorList[val0], 0.3, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5)), LerpColorInterval(self.locatorList[val1], 0.3, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5)), LerpColorInterval(self.locatorList[val2], 0.3, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5)), LerpColorInterval(self.locatorList[val3], 0.3, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5))) self.winningSequence.append(downBlinkerParallel) self.winningSequence.append(upBlinkerParallel) self.winningSequence.loop() def tie(self): self.tieSequence = Sequence(autoFinish=1) self.clockNode.stop() self.clockNode.hide() self.isMyTurn = False self.moveSequence.finish() if self.turnText: self.turnText.hide() for x in xrange(41): self.tieSequence.append(Parallel(LerpColorInterval(self.locatorList[x], 0.15, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[x], 0.15, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5)))) whisper = WhisperPopup('This Find Four game has resulted in a Tie!', OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) whisper.manage(base.marginManager) self.tieSequence.start() def hideChildren(self, nodeList): pass def animatePeice(self, tableState, moveCol, movePos, turn): messenger.send('wakeup') for x in xrange(6): for y in xrange(7): self.board[x][y] = tableState[x][y] pos = self.startingPositions[moveCol].getPos() if turn == 0: peice = self.startingPositions[moveCol].getChild(1).getChildren()[2] peice.show() elif turn == 1: peice = self.startingPositions[moveCol].getChild(1).getChildren()[3] peice.show() self.moveSequence = Sequence() startPos = self.startingPositions[moveCol].getPos() arrayLoc = movePos * 7 + moveCol self.moveSequence.append(LerpPosInterval(self.startingPositions[moveCol], 1.5, self.locatorList[arrayLoc].getPos(self), startPos)) self.moveSequence.append(Func(peice.hide)) self.moveSequence.append(Func(self.startingPositions[moveCol].setPos, startPos)) self.moveSequence.append(Func(self.updateGameState)) self.moveSequence.start() def announceWin(self, avId): self.fsm.request('gameOver') def doRandomMove(self): if self.isMyTurn: if self.moveCol != None: self.d_requestMove(self.moveCol) self.moveCol = None self.isMyTurn = False taskMgr.remove('playerTurnTask') else: hasfound = False while hasfound == False: from random import * x = randint(0, 6) if self.board[0][x] == 0: self.d_requestMove(x) self.moveCol = None self.isMyTurn = False taskMgr.remove('playerTurnTask') hasfound = True return def doNothing(self): pass def checkHorizontal(self, rVal, cVal, playerNum): if cVal == 3: for x in xrange(1, 4): if self.board[rVal][cVal - x] != playerNum: break if self.board[rVal][cVal - x] == playerNum and x == 3: return True for x in xrange(1, 4): if self.board[rVal][cVal + x] != playerNum: break if self.board[rVal][cVal + x] == playerNum and x == 3: return True return False elif cVal == 2: for x in xrange(1, 4): if self.board[rVal][cVal + x] != playerNum: break if self.board[rVal][cVal + x] == playerNum and x == 3: return True return False elif cVal == 4: for x in xrange(1, 4): if self.board[rVal][cVal - x] != playerNum: break if self.board[rVal][cVal - x] == playerNum and x == 3: return True return False else: return False def checkVertical(self, rVal, cVal, playerNum): if rVal == 2: for x in xrange(1, 4): if self.board[rVal + x][cVal] != playerNum: break if self.board[rVal + x][cVal] == playerNum and x == 3: return True return False elif rVal == 3: for x in xrange(1, 4): if self.board[rVal - x][cVal] != playerNum: break if self.board[rVal - x][cVal] == playerNum and x == 3: return True return False else: return False def checkDiagonal(self, rVal, cVal, playerNum): if cVal <= 2: if rVal == 2: for x in xrange(1, 4): if self.board[rVal + x][cVal + x] != playerNum: break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return True return False elif rVal == 3: for x in xrange(1, 4): if self.board[rVal - x][cVal + x] != playerNum: break if self.board[rVal - x][cVal + x] == playerNum and x == 3: return True return False elif cVal >= 4: if rVal == 2: for x in xrange(1, 4): if self.board[rVal + x][cVal - x] != playerNum: break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return True return False elif rVal == 3: for x in xrange(1, 4): if self.board[rVal - x][cVal - x] != playerNum: break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return True return False elif rVal == 3 or rVal == 4 or rVal == 5: for x in xrange(1, 4): if self.board[rVal - x][cVal - x] != playerNum: break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return True for x in xrange(1, 4): if self.board[rVal - x][cVal - x] != playerNum: break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return True return False elif rVal == 0 or rVal == 1 or rVal == 2: for x in xrange(1, 4): if self.board[rVal + x][cVal - x] != playerNum: break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return True for x in xrange(1, 4): if self.board[rVal + x][cVal + x] != playerNum: break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return True return False return False def findHorizontal(self, rVal, cVal, playerNum): if cVal == 3: retList = [] for x in xrange(1, 4): retList.append([rVal, cVal - x]) if self.board[rVal][cVal - x] != playerNum: retList = [] break if self.board[rVal][cVal - x] == playerNum and x == 3: return retList for x in xrange(1, 4): retList.append([rVal, cVal + x]) if self.board[rVal][cVal + x] != playerNum: retList = [] break if self.board[rVal][cVal + x] == playerNum and x == 3: return retList return [] elif cVal == 2: retList = [] for x in xrange(1, 4): retList.append([rVal, cVal + x]) if self.board[rVal][cVal + x] != playerNum: retList = [] break if self.board[rVal][cVal + x] == playerNum and x == 3: return retList return [] elif cVal == 4: retList = [] for x in xrange(1, 4): retList.append([rVal, cVal - x]) if self.board[rVal][cVal - x] != playerNum: retList = [] break if self.board[rVal][cVal - x] == playerNum and x == 3: return retList return [] else: return [] def findVertical(self, rVal, cVal, playerNum): if rVal == 2: retList = [] for x in xrange(1, 4): retList.append([rVal + x, cVal]) if self.board[rVal + x][cVal] != playerNum: retList = [] break if self.board[rVal + x][cVal] == playerNum and x == 3: return retList return [] elif rVal == 3: retList = [] for x in xrange(1, 4): retList.append([rVal - x, cVal]) if self.board[rVal - x][cVal] != playerNum: retList = [] break if self.board[rVal - x][cVal] == playerNum and x == 3: return retList return [] else: return [] def findDiagonal(self, rVal, cVal, playerNum): retList = [] if cVal <= 2: if rVal == 2: for x in xrange(1, 4): retList.append([rVal + x, cVal + x]) if self.board[rVal + x][cVal + x] != playerNum: retList = [] break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return retList return [] elif rVal == 3: for x in xrange(1, 4): retList.append([rVal - x, cVal + x]) if self.board[rVal - x][cVal + x] != playerNum: retList = [] break if self.board[rVal - x][cVal + x] == playerNum and x == 3: return retList return [] elif cVal >= 4: if rVal == 2: for x in xrange(1, 4): retList.append([rVal + x, cVal - x]) if self.board[rVal + x][cVal - x] != playerNum: retList = [] break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return retList return [] elif rVal == 3: for x in xrange(1, 4): retList.append([rVal - x, cVal - x]) if self.board[rVal - x][cVal - x] != playerNum: retList = [] break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return retList return [] elif rVal == 3 or rVal == 4 or rVal == 5: for x in xrange(1, 4): retList.append([rVal - x, cVal - x]) if self.board[rVal - x][cVal - x] != playerNum: retList = [] break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return retList for x in xrange(1, 4): retList.append([rVal + x, cVal - x]) if self.board[rVal + x][cVal - x] != playerNum: retList = [] break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return retList return [] elif rVal == 0 or rVal == 1 or rVal == 2: for x in xrange(1, 4): retList.append([rVal + x, cVal - x]) if self.board[rVal + x][cVal - x] != playerNum: retList = [] break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return retList for x in xrange(1, 4): retList.append([rVal + x, cVal + x]) if self.board[rVal + x][cVal + x] != playerNum: retList = [] break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return retList return [] return []
class DistributedPicnicBasket(DistributedObject.DistributedObject): seatState = Enum('Empty, Full, Eating') notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedPicnicBasket') def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.localToonOnBoard = 0 self.seed = 0 self.random = None self.picnicCountdownTime = base.config.GetFloat( 'picnic-countdown-time', ToontownGlobals.PICNIC_COUNTDOWN_TIME) self.picnicBasketTrack = None self.fsm = ClassicFSM.ClassicFSM('DistributedTrolley', [ State.State('off', self.enterOff, self.exitOff, ['waitEmpty', 'waitCountdown']), State.State('waitEmpty', self.enterWaitEmpty, self.exitWaitEmpty, ['waitCountdown']), State.State('waitCountdown', self.enterWaitCountdown, self.exitWaitCountdown, ['waitEmpty']) ], 'off', 'off') self.fsm.enterInitialState() self.__toonTracks = {} return def generate(self): DistributedObject.DistributedObject.generate(self) self.loader = self.cr.playGame.hood.loader self.foodLoader = [ 'phase_6/models/golf/picnic_sandwich.bam', 'phase_6/models/golf/picnic_apple.bam', 'phase_6/models/golf/picnic_cupcake.bam', 'phase_6/models/golf/picnic_chocolate_cake.bam' ] self.fullSeat = [] self.food = [] for i in range(4): self.food.append(None) self.fullSeat.append(self.seatState.Empty) self.picnicItem = 0 return def announceGenerate(self): self.picnicTable = self.loader.geom.find('**/*picnic_table_' + str(self.tableNumber)) self.picnicTableSphereNodes = [] self.numSeats = 4 self.seats = [] self.jumpOffsets = [] self.basket = None for i in range(self.numSeats): self.seats.append(self.picnicTable.find('**/*seat%d' % (i + 1))) self.jumpOffsets.append( self.picnicTable.find('**/*jumpOut%d' % (i + 1))) self.tablecloth = self.picnicTable.find('**/basket_locator') DistributedObject.DistributedObject.announceGenerate(self) for i in range(self.numSeats): self.picnicTableSphereNodes.append(self.seats[i].attachNewNode( CollisionNode('picnicTable_sphere_%d_%d' % (self.getDoId(), i)))) self.picnicTableSphereNodes[i].node().addSolid( CollisionSphere(0, 0, 0, 2)) self.tableclothSphereNode = self.tablecloth.attachNewNode( CollisionNode('tablecloth_sphere')) self.tableclothSphereNode.node().addSolid(CollisionSphere(0, 0, -1, 4)) angle = self.startingHpr[0] angle -= 90 radAngle = deg2Rad(angle) unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0) unitVec *= 30.0 self.endPos = self.startingPos + unitVec dist = Vec3(self.endPos - self.enteringPos).length() wheelAngle = dist / (0.5 * 1.4 * math.pi) * 360 self.seatNumber = 0 self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() return def disable(self): DistributedObject.DistributedObject.disable(self) self.fsm.request('off') self.clearToonTracks() for i in range(self.numSeats): del self.picnicTableSphereNodes[0] del self.picnicTableSphereNodes self.notify.debug('Deleted self loader ' + str(self.getDoId())) self.picnicTable.removeNode() self.picnicBasketTrack = None return def delete(self): self.notify.debug('Golf kart getting deleted: %s' % self.getDoId()) DistributedObject.DistributedObject.delete(self) del self.fsm def setState(self, state, seed, timestamp): self.seed = seed if not self.random: self.random = RandomNumGen.RandomNumGen(seed) self.fsm.request(state, [globalClockDelta.localElapsedTime(timestamp)]) def handleEnterPicnicTableSphere(self, i, collEntry): self.seatNumber = i self.notify.debug('Entering Picnic Table Sphere.... %s' % self.getDoId()) self.loader.place.detectedPicnicTableSphereCollision(self) def handleEnterPicnicTable(self, i): toon = base.localAvatar self.sendUpdate('requestBoard', [i]) def fillSlot0(self, avId): self.fillSlot(0, avId) def fillSlot1(self, avId): self.fillSlot(1, avId) def fillSlot2(self, avId): self.fillSlot(2, avId) def fillSlot3(self, avId): self.fillSlot(3, avId) def fillSlot(self, index, avId): self.notify.debug('fill Slot: %d for %d' % (index, avId)) if avId == 0: pass else: self.fullSeat[index] = self.seatState.Full if avId == base.localAvatar.getDoId(): self.clockNode.show() if index == 0 or index == 3: side = -1 else: side = 1 if hasattr(self.loader.place, 'trolley'): self.loader.place.trolley.fsm.request( 'boarding', [self.tablecloth, side]) else: self.notify.warning('fillSlot no trolley in place') self.localToonOnBoard = 1 if avId == base.localAvatar.getDoId(): if hasattr(self.loader.place, 'trolley'): self.loader.place.trolley.fsm.request('boarded') self.loader.place.trolley.exitButton.hide() if avId in self.cr.doId2do: toon = self.cr.doId2do[avId] toon.stopSmooth() toon.wrtReparentTo(self.tablecloth) sitStartDuration = toon.getDuration('sit-start') jumpTrack = self.generateToonJumpTrack(toon, index) track = Sequence(jumpTrack, Func(toon.setAnimState, 'Sit', 1.0)) self.notify.debug('### fillSlot: fullSeat = %s' % self.fullSeat) if self.fullSeat.count(0) == 3: self.notify.debug('### fillSlot: adding basketAppear') if self.picnicBasketTrack: self.picnicBasketTrack.finish() waitDuration = track.getDuration() self.picnicBasketTrack = Sequence( Wait(waitDuration), self.generateBasketAppearTrack()) self.picnicBasketTrack.start() track.append(self.generateFoodAppearTrack(index)) track.append( Sequence(Func(self.clearToonTrack, avId), name=toon.uniqueName('fillTrolley'), autoPause=1)) if avId == base.localAvatar.getDoId(): if hasattr(self.loader.place, 'trolley'): track.append( Func(self.loader.place.trolley.exitButton.show)) track.delayDelete = DelayDelete.DelayDelete( toon, 'PicnicBasket.fillSlot') self.storeToonTrack(avId, track) track.start() def emptySlot0(self, avId, timestamp): self.emptySlot(0, avId, timestamp) def emptySlot1(self, avId, timestamp): self.emptySlot(1, avId, timestamp) def emptySlot2(self, avId, timestamp): self.emptySlot(2, avId, timestamp) def emptySlot3(self, avId, timestamp): self.emptySlot(3, avId, timestamp) def notifyToonOffTrolley(self, toon): toon.setAnimState('neutral', 1.0) if hasattr(base, 'localAvatar') and toon == base.localAvatar: if hasattr(self.loader.place, 'trolley'): self.loader.place.trolley.handleOffTrolley() self.localToonOnBoard = 0 else: toon.startSmooth() def emptySlot(self, index, avId, timestamp): def emptySeat(index): self.notify.debug('### seat %s now empty' % index) self.fullSeat[index] = self.seatState.Empty if avId == 0: pass elif avId == 1: self.fullSeat[index] = self.seatState.Empty track = Sequence(self.generateFoodDisappearTrack(index)) self.notify.debug('### empty slot - unexpetected: fullSeat = %s' % self.fullSeat) if self.fullSeat.count(0) == 4: self.notify.debug('### empty slot - unexpected: losing basket') if self.picnicBasketTrack: self.picnicBasketTrack.finish() waitDuration = track.getDuration() self.picnicBasketTrack = Sequence( Wait(waitDuration), self.generateBasketDisappearTrack()) self.picnicBasketTrack.start() track.start() else: self.fullSeat[index] = self.seatState.Empty if avId in self.cr.doId2do: if avId == base.localAvatar.getDoId(): if self.clockNode: self.clockNode.hide() toon = self.cr.doId2do[avId] toon.stopSmooth() sitStartDuration = toon.getDuration('sit-start') jumpOutTrack = self.generateToonReverseJumpTrack(toon, index) track = Sequence(jumpOutTrack) track.append(self.generateFoodDisappearTrack(index)) self.notify.debug('### empty slot: fullSeat = %s' % self.fullSeat) if self.fullSeat.count(0) == 4: self.notify.debug('### empty slot: losing basket') if self.picnicBasketTrack: self.picnicBasketTrack.finish() waitDuration = track.getDuration() self.picnicBasketTrack = Sequence( Wait(waitDuration), self.generateBasketDisappearTrack()) self.picnicBasketTrack.start() track.append( Sequence(Func(self.notifyToonOffTrolley, toon), Func(self.clearToonTrack, avId), Func(self.doneExit, avId), Func(emptySeat, index), name=toon.uniqueName('emptyTrolley'), autoPause=1)) track.delayDelete = DelayDelete.DelayDelete( toon, 'PicnicBasket.emptySlot') self.storeToonTrack(avId, track) track.start() def rejectBoard(self, avId): self.loader.place.trolley.handleRejectBoard() def __enableCollisions(self): for i in range(self.numSeats): self.accept('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTableSphere, [i]) self.accept('enterPicnicTableOK_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTable, [i]) self.picnicTableSphereNodes[i].setCollideMask( ToontownGlobals.WallBitmask) def __disableCollisions(self): for i in range(self.numSeats): self.ignore('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i)) self.ignore('enterPicnicTableOK_%d_%d' % (self.getDoId(), i)) for i in range(self.numSeats): self.picnicTableSphereNodes[i].setCollideMask(BitMask32(0)) def enterOff(self): return None def exitOff(self): return None def enterWaitEmpty(self, ts): self.__enableCollisions() def exitWaitEmpty(self): self.__disableCollisions() def enterWaitCountdown(self, ts): self.__enableCollisions() self.accept('trolleyExitButton', self.handleExitButton) self.clockNode.countdown(self.picnicCountdownTime, self.handleExitButton) def handleExitButton(self): self.sendUpdate('requestExit') self.clockNode.hide() def exitWaitCountdown(self): self.__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def getStareAtNodeAndOffset(self): return (self.tablecloth, Point3(0, 0, 4)) def storeToonTrack(self, avId, track): self.clearToonTrack(avId) self.__toonTracks[avId] = track def clearToonTrack(self, avId): oldTrack = self.__toonTracks.get(avId) if oldTrack: oldTrack.pause() DelayDelete.cleanupDelayDeletes(oldTrack) del self.__toonTracks[avId] def clearToonTracks(self): keyList = [] for key in self.__toonTracks: keyList.append(key) for key in keyList: if key in self.__toonTracks: self.clearToonTrack(key) def doneExit(self, avId): if avId == base.localAvatar.getDoId(): self.sendUpdate('doneExit') def setPosHpr(self, x, y, z, h, p, r): self.startingPos = Vec3(x, y, z) self.enteringPos = Vec3(x, y, z - 10) self.startingHpr = Vec3(h, 0, 0) def setTableNumber(self, tn): self.tableNumber = tn def generateToonJumpTrack(self, av, seatIndex): av.pose('sit', 47) hipOffset = av.getHipsParts()[2].getPos(av) def getToonJumpTrack(av, seatIndex): def getJumpDest(av=av, node=self.tablecloth): dest = Vec3(self.tablecloth.getPos(av.getParent())) seatNode = self.picnicTable.find('**/seat' + str(seatIndex + 1)) dest += seatNode.getPos(self.tablecloth) dna = av.getStyle() dest -= hipOffset if seatIndex == 2 or seatIndex == 3: dest.setY(dest.getY() + 2 * hipOffset.getY()) dest.setZ(dest.getZ() + 0.2) return dest def getJumpHpr(av=av, node=self.tablecloth): hpr = self.seats[seatIndex].getHpr(av.getParent()) angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX()) hpr.setX(angle) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.43), Parallel( LerpHprInterval(av, hpr=getJumpHpr, duration=0.9), ProjectileInterval(av, endPos=getJumpDest, duration=0.9)))) return toonJumpTrack def getToonSitTrack(av): toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit')) return toonSitTrack toonJumpTrack = getToonJumpTrack(av, seatIndex) toonSitTrack = getToonSitTrack(av) jumpTrack = Sequence( Parallel(toonJumpTrack, Sequence(Wait(1), toonSitTrack)), Func(av.wrtReparentTo, self.tablecloth)) return jumpTrack def generateToonReverseJumpTrack(self, av, seatIndex): self.notify.debug('av.getH() = %s' % av.getH()) def getToonJumpTrack(av, destNode): def getJumpDest(av=av, node=destNode): dest = node.getPos(self.tablecloth) dest += self.jumpOffsets[seatIndex].getPos(self.tablecloth) return dest def getJumpHpr(av=av, node=destNode): hpr = node.getHpr(av.getParent()) hpr.setX(hpr.getX() + 180) angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX()) hpr.setX(angle) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.1), Parallel( ProjectileInterval(av, endPos=getJumpDest, duration=0.9)))) return toonJumpTrack toonJumpTrack = getToonJumpTrack(av, self.tablecloth) jumpTrack = Sequence(toonJumpTrack, Func(av.loop, 'neutral'), Func(av.wrtReparentTo, render)) return jumpTrack def generateBasketAppearTrack(self): if self.basket == None: self.basket = loader.loadModel( 'phase_6/models/golf/picnic_basket.bam') self.basket.setScale(0.1) basketTrack = Sequence( Func(self.basket.show), SoundInterval( globalBattleSoundCache.getSound('GUI_balloon_popup.ogg'), node=self.basket), Func(self.basket.reparentTo, self.tablecloth), Func(self.basket.setPos, 0, 0, 0.2), Func(self.basket.setHpr, 45, 0, 0), Func(self.basket.wrtReparentTo, render), Func(self.basket.setShear, 0, 0, 0), Sequence( LerpScaleInterval(self.basket, scale=Point3(1.1, 1.1, 0.1), duration=0.2), LerpScaleInterval(self.basket, scale=Point3(1.6, 1.6, 0.2), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(1.0, 1.0, 0.4), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(1.5, 1.5, 2.5), duration=0.2), LerpScaleInterval(self.basket, scale=Point3(2.5, 2.5, 1.5), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(2.0, 2.0, 2.0), duration=0.1), Func(self.basket.wrtReparentTo, self.tablecloth), Func(self.basket.setPos, 0, 0, 0))) return basketTrack def generateBasketDisappearTrack(self): if not self.basket: return Sequence() pos = self.basket.getPos() pos.addZ(-1) basketTrack = Sequence( LerpScaleInterval(self.basket, scale=Point3(2.0, 2.0, 1.8), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(1.0, 1.0, 2.5), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(2.0, 2.0, 0.5), duration=0.2), LerpScaleInterval(self.basket, scale=Point3(0.5, 0.5, 1.0), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(1.1, 1.1, 0.1), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(0.1, 0.1, 0.1), duration=0.2), SoundInterval( globalBattleSoundCache.getSound('GUI_balloon_popup.ogg'), node=self.basket), Wait(0.2), LerpPosInterval(self.basket, pos=pos, duration=0.2), Func(self.basket.hide)) return basketTrack def generateFoodAppearTrack(self, seat): if self.fullSeat[seat] == self.seatState.Full: self.notify.debug('### food appear: self.fullSeat = %s' % self.fullSeat) if not self.food[seat]: self.food[seat] = loader.loadModel( self.random.choice(self.foodLoader)) self.notify.debug('### food appear: self.food = %s' % self.food) self.food[seat].setScale(0.1) self.food[seat].reparentTo(self.tablecloth) self.food[seat].setPos( self.seats[seat].getPos(self.tablecloth)[0] / 2, self.seats[seat].getPos(self.tablecloth)[1] / 2, 0) foodTrack = Sequence( Func(self.food[seat].show), SoundInterval( globalBattleSoundCache.getSound('GUI_balloon_popup.ogg'), node=self.food[seat]), Func(self.food[seat].reparentTo, self.tablecloth), Func(self.food[seat].setHpr, 45, 0, 0), Func(self.food[seat].wrtReparentTo, render), Func(self.food[seat].setShear, 0, 0, 0), Sequence( LerpScaleInterval(self.food[seat], scale=Point3(1.1, 1.1, 0.1), duration=0.2), LerpScaleInterval(self.food[seat], scale=Point3(1.6, 1.6, 0.2), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(1.0, 1.0, 0.4), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(1.5, 1.5, 2.5), duration=0.2), LerpScaleInterval(self.food[seat], scale=Point3(2.5, 2.5, 1.5), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(2.0, 2.0, 2.0), duration=0.1), Func(self.food[seat].wrtReparentTo, self.tablecloth))) return foodTrack else: return Sequence() def generateFoodDisappearTrack(self, seat): if not self.food[seat]: return Sequence() pos = self.food[seat].getPos() pos.addZ(-1.0) foodTrack = Sequence( LerpScaleInterval(self.food[seat], scale=Point3(2.0, 2.0, 1.8), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(1.0, 1.0, 2.5), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(2.0, 2.0, 0.5), duration=0.2), LerpScaleInterval(self.food[seat], scale=Point3(0.5, 0.5, 1.0), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(1.1, 1.1, 0.1), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(0.1, 0.1, 0.1), duration=0.2), SoundInterval( globalBattleSoundCache.getSound('GUI_balloon_popup.ogg'), node=self.food[seat]), Wait(0.2), LerpPosInterval(self.food[seat], pos=pos, duration=0.2), Func(self.food[seat].hide)) return foodTrack def destroy(self, node): node.removeNode() node = None self.basket.removeNode() self.basket = None for food in self.food: food.removeNode() self.food = None self.clockNode.removeNode() del self.clockNode self.clockNode = None return def setPicnicDone(self): if self.localToonOnBoard: if hasattr(self.loader.place, 'trolley'): self.loader.place.trolley.fsm.request('final') self.loader.place.trolley.fsm.request('start') self.localToonOnBoard = 0 messenger.send('picnicDone')
class DistributedPicnicTable(DistributedNode.DistributedNode): def __init__(self, cr): self.cr = cr NodePath.__init__(self, "DistributedPicnicTable") DistributedNode.DistributedNode.__init__(self, cr) self.reparentTo(render) self.picnicTable = loader.loadModel( "phase_6/models/golf/game_table.bam") self.picnicTable.reparentTo(self) self.picnicTableSphereNodes = [] self.numSeats = 6 self.seats = [] self.jumpOffsets = [] self.inGame = False self.requestSeat = None self.gameState = None #self.mypos = self.getPos() self.cameraBoardTrack = Func(self.doNothing) self.seatBumpForObserve = 0 self.winTrack = Sequence() self.outTrack = Sequence() self.joinButton = None self.observeButton = None self.tutorialButton = None self.exitButton = None self.isPlaying = False self.gameMenu = None self.game = None self.gameZone = None self.tutorial = None self.timerFunc = None self.gameDoId = None #self.game = None self.gameWantTimer = False self.tableState = [None, None, None, None, None, None] self.haveAnimated = [] self.winSound = base.loadSfx("phase_6/audio/sfx/KART_Applause_1.mp3") self.happyDance = base.loadSfx( "phase_5/audio/sfx/AA_heal_happydance.mp3") #Seems like these functions BOTH are required #To intercept the sleep event. #Important to take action when GUI elements are up to turn #them off when the avatar goes to sleep otherwise the wakeup will allow #him to run around with the gui up. self.accept('stoppedAsleep', self.handleSleep) base.localAvatar.startSleepWatch(self.handleSleep) self.__toonTracks = {} self.fsm = ClassicFSM.ClassicFSM( 'PicnicTable', [ State.State('off', self.enterOff, self.exitOff, ['chooseMode', 'observing']), State.State('chooseMode', self.enterChooseMode, self.exitChooseMode, ['sitting', 'off', 'observing']), State.State('sitting', self.enterSitting, self.exitSitting, ['off']), State.State('observing', self.enterObserving, self.exitObserving, ['off']) ], #start state 'off', #final state` 'off', ) self.fsm.enterInitialState() #Go find all of the locators for seats and jumpout locators for i in range(self.numSeats): self.seats.append(self.picnicTable.find("**/*seat%d" % (i + 1))) self.jumpOffsets.append( self.picnicTable.find("**/*jumpOut%d" % (i + 1))) self.tableCloth = self.picnicTable.find("**/basket_locator") #Stops you from walking on the table self.tableclothSphereNode = self.tableCloth.attachNewNode( CollisionNode('tablecloth_sphere')) self.tableclothSphereNode.node().addSolid( CollisionSphere(0, 0, -2, 5.5)) self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) #Set up the collision spheres for the seats for i in range(self.numSeats): self.picnicTableSphereNodes.append(self.seats[i].attachNewNode( CollisionNode('picnicTable_sphere_%d_%d' % (self.getDoId(), i)))) self.picnicTableSphereNodes[i].node().addSolid( CollisionSphere(0, 0, 0, 2)) #sit everyone down self.tableState = [None, None, None, None, None, None] self.requestTableState() self.buttonModels = loader.loadModel( "phase_3.5/models/gui/inventory_gui") self.upButton = self.buttonModels.find("**//InventoryButtonUp") self.downButton = self.buttonModels.find("**/InventoryButtonDown") self.rolloverButton = self.buttonModels.find( "**/InventoryButtonRollover") #self.picnicTable.setScale(.030) #Preprocessing for Jump into seat Arcs (bad to do at runtime) angle = self.getH() angle -= 90 radAngle = deg2Rad(angle) unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0) unitVec *= 30.0 self.endPos = self.getPos() + unitVec dist = Vec3(self.endPos - self.getPos()).length() wheelAngle = dist / (0.5 * 1.4 * math.pi) * 360 self.__enableCollisions() def handleSleep(self, task=None): #print "GETTING TO SLEEP!!!" if self.fsm.getCurrentState().getName() == "chooseMode": self.cancelButtonPushed() elif self.fsm.getCurrentState().getName() == "sitting": self.sendUpdate("requestExit", []) if self.gameMenu != None: self.gameMenu.removeButtons() self.gameMenu.picnicFunction = None self.gameMenu = None if task != None: task.done #task.done def disable(self): DistributedNode.DistributedNode.disable(self) self.ignore('stoppedAsleep') self.clearToonTracks() self.__disableCollisions() self.disableChoiceButtons() #del self.picnicTableSphereNodes self.picnicTable.removeNode() self.cameraBoardTrack = None #self.fsm = None #self.winTrack.finish() #self.outTrack.finish() #self.outTrack = None def delete(self): self.__disableCollisions() self.ignore('stoppedAsleep') DistributedNode.DistributedNode.delete(self) self.disableChoiceButtons() self.cameraBoardTrack = None #self.winTrack.finish() #self.outTrack.finish() #self.winTrack = None #self.outTrack = None del self.winTrack del self.outTrack self.fsm = None self.gameZone = None self.clearToonTracks() self.cameraBoardTrack = None #self.clearToonTrack() #print " I AM DELETEING \n\n\n\n\n\n\n\n\n" #self.outTrack = None #del self def setName(self, name): self.name = name ################ ##SetGameDoID - # This function is called by the child game after it is generated, in order #to set up the cross references that are needed to handle certain events #IE (getting up, erroneous disconnects ect.) def setGameDoId(self, doId): self.gameDoId = doId self.game = self.cr.doId2do[doId] self.game.setHpr(self.getHpr()) self.gameWantTimer = self.game.wantTimer if self.gameState == 1: self.game.fsm.request('playing') ########## ##Timer Functions #setTimer (required broadcast ram) # #These are the timer functions that dictate movement and visual timer #feedback in the game table and chinese checkers. # ########## def setTimerFunc(self, function): self.timerFunc = function def setTimer(self, timerEnd): self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) self.timeLeft = int(time - globalClock.getRealTime()) if self.gameWantTimer and self.game != None: self.showTimer() def showTimer(self): #important to stop the timer before you reset it, otherwise it may still be running self.clockNode.stop() self.clockNode.countdown(self.timeLeft, self.timerFunc) self.clockNode.show() ########## #setTableState (required ram broadcast) # #This functions primary purpose is to handle asynchrinous joins of the zone #if an avatar teleports in, he needs to have a state of the table so he #can animate the toons to be sitting down in their corresponding seats ########## def requestTableState(self): self.sendUpdate("requestTableState", []) def setTableState(self, tableStateList, isplaying): y = 0 print("SET TABLE STATE") if isplaying == 0: self.isPlaying = False else: self.isPlaying = True for x in tableStateList: if x != 0: # If we are to sit him down, make sure that he has not already been animated by fillslot # (deltas are handled by that function) if not x in self.tableState and x in self.cr.doId2do and x not in self.haveAnimated: seatIndex = tableStateList.index(x) toon = self.cr.doId2do[x] toon.stopSmooth() toon.setAnimState("Sit", 1.0) dest = self.seats[seatIndex].getPos(self.tableCloth) hpr = self.seats[seatIndex].getHpr(render) toon.setHpr(hpr) if (seatIndex > 2): toon.setH(self.getH() + 180) toon.wrtReparentTo(self) toon.setPos(dest) toon.setZ(toon.getZ() + 1.35) if (seatIndex > 2): toon.setY(toon.getY() - 1.0) else: toon.setY(toon.getY() + 1.0) if x != 0: self.tableState[y] = x else: self.tableState[y] = None y = y + 1 ###Handle the game menu stuffs numPlayers = 0 for x in self.tableState: if x != None: numPlayers += 1 #check for a game menu up print(" GETTING 2", self.gameMenu, numPlayers) if self.gameMenu: if numPlayers > 2: print(" GETTING HERE!!") self.gameMenu.FindFour.setColor(.7, .7, .7, .7) self.gameMenu.FindFour['command'] = self.doNothing self.gameMenu.findFourText['fg'] = (.7, .7, .7, .7) self.gameMenu.Checkers.setColor(.7, .7, .7, .7) self.gameMenu.Checkers['command'] = self.doNothing self.gameMenu.checkersText['fg'] = (.7, .7, .7, .7) def setIsPlaying(self, isPlaying): if isPlaying == 0: self.isPlaying = False elif isPlaying == 1: self.isPlaying = True ########## ##announceWinner (broadcast) # #Obvious, simply just sets the whisper message ########## def announceWinner(self, winString, avId): if avId == base.localAvatar.getDoId(): sound = Sequence( Wait(2.0), Parallel(SoundInterval(self.winSound), SoundInterval(self.happyDance))) sound.start() base.cr.playGame.getPlace().setState( 'walk') #To stop Cohesion between EmptySlot and AnnounceWin if winString == "Chinese Checkers": whisper = WhisperPopup(TTLocalizer.ChineseCheckersYouWon, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == "Checkers": whisper = WhisperPopup(TTLocalizer.RegularCheckersYouWon, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == "Find Four": whisper = WhisperPopup("You won a game of Find Four!", OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) else: if avId in self.cr.doId2do: stateString = self.fsm.getCurrentState().getName() if stateString == "sitting" or stateString == "observing": base.cr.playGame.getPlace().setState( 'walk' ) #To stop Cohesion between EmptySlot and AnnounceWin av = self.cr.doId2do[avId] if winString == "Chinese Checkers": whisper = WhisperPopup( av.getName() + TTLocalizer.ChineseCheckersGameOf + TTLocalizer.ChineseCheckers, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == "Checkers": whisper = WhisperPopup( av.getName() + TTLocalizer.RegularCheckersGameOf + TTLocalizer.RegularCheckers, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == "Find Four": whisper = WhisperPopup( av.getName() + " has won a game of" + " Find Four!", OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) if avId in self.cr.doId2do: # If the toon exists, look it up toon = self.cr.doId2do[avId] #self.winTrack.finish() self.winTrack = Sequence(autoFinish=1) if self.outTrack.isPlaying(): #If toon is jumping out Wait a self.winTrack.append( Wait(2.0)) # duration till his anim is over to begin if avId == base.localAvatar.getDoId(): #stop him from walking locally #otherwise he will animate around while moving on other clients self.winTrack.append(Func(self.stopToWalk)) self.winTrack.append(ActorInterval(toon, 'happy-dance')) if avId == base.localAvatar.getDoId(): self.winTrack.append(Func(self.allowToWalk)) self.winTrack.start() #Display the whisper message whisper.manage(base.marginManager) ########## #handleEnterPicnicTableSphere # #This is the function that via the messenger, handles the collision #with one of the six collision spheres on a picnic table ########## def handleEnterPicnicTableSphere(self, i, collEntry): assert self.notify.debugStateCall(self) #print "COLLISION!!!" self.notify.debug("Entering Picnic Table Sphere.... %s" % self.getDoId()) #if self.requestSeat == None: self.requestSeat = i self.seatBumpForObserve = i self.fsm.request('chooseMode') ########## #Button Logic (handled by handleEnterPicnicTableSphere, and self.fsm ### def enableChoiceButtons(self): if self.tableState[ self.seatBumpForObserve] == None and self.isPlaying == False: self.joinButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableJoinButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, .8), scale=0.15, command=lambda self=self: self.joinButtonPushed(), ) if self.isPlaying == True: self.observeButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableObserveButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, 0.6), scale=0.15, command=lambda self=self: self.observeButtonPushed(), ) self.exitButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableCancelButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(1, 0, 0.6), scale=0.15, command=lambda self=self: self.cancelButtonPushed(), ) self.tutorialButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableTutorial, text_fg=(1, 1, 0.65, 1), text_pos=(-.05, -.13), text_scale=0.55, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-1, 0, 0.6), scale=0.15, command=lambda self=self: self.tutorialButtonPushed(), ) base.cr.playGame.getPlace().setState('stopped') def tutorialButtonPushed(self): #print "GETTING HERE!!!" self.disableChoiceButtons() #self.tutorial = ChineseTutorial(self.tutorialDone) self.gameMenu = GameMenu(self.tutorialFunction, 1) # 1 == Tutorial Num #self.tutorialFunction(1) self.tutorialButton.destroy() self.tutorialButton = None def tutorialFunction(self, tutVal): if tutVal == 1: self.tutorial = ChineseTutorial(self.tutorialDone) elif tutVal == 2: self.tutorial = CheckersTutorial(self.tutorialDone) self.gameMenu.picnicFunction = None self.gameMenu = None def tutorialDone(self): #del self.tutorial self.requestSeat = None self.fsm.request('off') self.tutorial = None #del self.tutorial def joinButtonPushed(self): toon = base.localAvatar self.sendUpdate("requestJoin", [ self.requestSeat, toon.getX(), toon.getY(), toon.getZ(), toon.getH(), toon.getP(), toon.getR() ]) self.requestSeat = None self.fsm.request('sitting') def rejectJoin(self): self.fsm.request('off') self.allowToWalk() def cancelButtonPushed(self): base.cr.playGame.getPlace().setState('walk') self.requestSeat = None self.fsm.request('off') def disableChoiceButtons(self): if self.joinButton: self.joinButton.destroy() if self.observeButton: self.observeButton.destroy() if self.exitButton: self.exitButton.destroy() if self.tutorialButton: self.tutorialButton.destroy() ########## #Distributed fillSlot Functions (broadcasT) # #These functions are the distributed functions that the ai sends to tell #the client if its ok for people to picnic table, and then animates them ########## def pickFunction(self, gameNum): #print "SENDING PICK!" if gameNum == 1: #Chinese Checkers self.sendUpdate('requestPickedGame', [gameNum]) elif gameNum == 2: self.sendUpdate('requestPickedGame', [gameNum]) elif gameNum == 3: self.sendUpdate('requestPickedGame', [gameNum]) def allowPick(self): self.gameMenu = GameMenu(self.pickFunction, 2) # 2 == pick Num for TTlocalizer #elf.pickFunction(1) def setZone(self, zoneId): #import pdb; pdb.set_trace() #print "ZONE iD == " , zoneId #print "CURRENT SATE?!?!? == ", self.fsm.getCurrentState().getName() #if self.fsm.getCurrentState().getName() == "chooseMode" or self.fsm.getCurrentState().getName() == "sitting": if self.fsm.getCurrentState().getName( ) == "sitting" or self.fsm.getCurrentState().getName() == "observing": if self.tutorial == None: self.gameZone = base.cr.addInterest( base.localAvatar.defaultShard, zoneId, 'gameBoard') if self.gameMenu != None: self.gameMenu.removeButtons() self.gameMenu.picnicFunction = None self.gameMenu = None def fillSlot(self, avId, index, x, y, z, h, p, r, timestamp, parentDoId): assert self.notify.debugStateCall(self) self.notify.debug("fill Slot: %d for %d" % (index, avId)) if not avId in self.haveAnimated: self.haveAnimated.append(avId) if avId == base.localAvatar.getDoId(): if self.inGame == True: return #in a game therefore we dont animate else: self.inGame = True self.seatPos = index pass #not in a game but need to animate into the game if avId in self.cr.doId2do: toon = self.cr.doId2do[avId] toon.stopSmooth() toon.wrtReparentTo(self.tableCloth) sitStartDuration = toon.getDuration("sit-start") jumpTrack = self.generateToonJumpTrack(toon, index) track = Sequence(autoFinish=1) if avId == base.localAvatar.getDoId(): if not base.cr.playGame.getPlace() == None: self.moveCamera(index) track.append(Func(self.__disableCollisions)) #self.gameZone = base.cr.addInterest(base.localAvatar.defaultShard, boardZoneId, 'chineseBoard') track.append(jumpTrack) track.append(Func(toon.setAnimState, "Sit", 1.0)) track.append(Func(self.clearToonTrack, avId)) self.storeToonTrack(avId, track) track.start() ########## #Empty Slot Distributed Functions (broadcast) # #Distributed functions that manage the toons getting off of the picnic #tables ########## def emptySlot(self, avId, index, timestamp): self.notify.debug("### seat %s now empty" % index) ##Player told to exit is an OBSERVER if index == 255 and self.game != None: self.stopObserveButtonPushed() return #self.fullSeat[index] = self.seatState.Empty if avId in self.haveAnimated: self.haveAnimated.remove(avId) # self.fullSeat[index] = self.seatState.Empty if avId in self.cr.doId2do: if avId == base.localAvatar.getDoId(): if self.gameZone: base.cr.removeInterest(self.gameZone) if self.inGame == True: #are in a game self.inGame = False else: return #dont animate because we are NOT in a game toon = self.cr.doId2do[avId] toon.stopSmooth() sitStartDuration = toon.getDuration("sit-start") jumpOutTrack = self.generateToonReverseJumpTrack(toon, index) #self.outTrack.finish() self.outTrack = Sequence(jumpOutTrack) if base.localAvatar.getDoId() == avId: self.outTrack.append(Func(self.__enableCollisions)) self.outTrack.append(Func( self.allowToWalk)) #temp until i can stop the #camera from jerking #self.outTrack.append(Func(self.fsm.request, 'off')) self.fsm.request('off') #self.outTrack.append(Func(self.tempCheckers.setHpr, 0, self.tempCheckers.getP(), self.tempCheckers.getR())) val = self.jumpOffsets[index].getPos(render) #self.storeToonTrack(avId, self.outTrack) self.outTrack.append(Func(toon.setPos, val)) self.outTrack.append(Func(toon.startSmooth)) self.outTrack.start() #self.outTrack = Sequence() def stopToWalk(self): base.cr.playGame.getPlace().setState("stopped") def allowToWalk(self): #if not self.winTrack.isPlaying(): base.cr.playGame.getPlace().setState("walk") #self.winTrack.finish() #self.winTrack = None ########## #Camera manipulations ########## def moveCamera(self, seatIndex): self.oldCameraPos = camera.getPos() self.oldCameraHpr = camera.getHpr() camera.wrtReparentTo(self.picnicTable) heading = PythonUtil.fitDestAngle2Src(camera.getH(), 90) #Need to check the seat index so the cameras *down #is towards the player so he is not facing his own character #rather he feels he is a bit above him if seatIndex < 3: self.cameraBoardTrack = LerpPosHprInterval(camera, 2.0, Point3(0, 0, 17), Point3(0, -90, 0)) else: #needed for camera orientation #If test is not here, the camera may often flip around #spinning ~340 degrees to the destination #instead of turning the 20 degrees towards the table if (camera.getH() < 0): #(turned left) self.cameraBoardTrack = LerpPosHprInterval( camera, 2.0, Point3(0, 0, 17), Point3(-180, -90, 0)) else: #(turned right) self.cameraBoardTrack = LerpPosHprInterval( camera, 2.0, Point3(0, 0, 17), Point3(180, -90, 0)) self.cameraBoardTrack.start() def moveCameraBack(self): self.cameraBoardTrack = LerpPosHprInterval(camera, 2.5, self.oldCameraPos, self.oldCameraHpr) self.cameraBoardTrack.start() ########## # Enable and Disable Collisions # #Turn on and off the collisions for the seat and table collision spheres for #boarding and unboarding, thus to actaully allow the toons to sit down, animate ect. ########## def __enableCollisions(self): # start listening for toons to enter. assert self.notify.debugStateCall(self) for i in range(self.numSeats): self.accept('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTableSphere, [i]) #self.accept('enterPicnicTableOK_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTable, [i]) self.picnicTableSphereNodes[i].setCollideMask( ToontownGlobals.WallBitmask) self.tableclothSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def __disableCollisions(self): assert self.notify.debugStateCall(self) #self.ignore('tableClothSphereNode') for i in range(self.numSeats): self.ignore('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i)) self.ignore('enterPicnicTableOK_%d_%d' % (self.getDoId(), i)) for i in range(self.numSeats): self.picnicTableSphereNodes[i].setCollideMask(BitMask32(0)) self.tableclothSphereNode.setCollideMask(BitMask32(0)) ########## #FSM stuff ########## def enterOff(self): base.setCellsAvailable(base.leftCells + base.bottomCells, 0) def exitOff(self): base.setCellsAvailable(base.bottomCells, 0) def enterChooseMode(self): #self.requestTableState() self.winTrack = Sequence(autoFinish=1) self.enableChoiceButtons() def exitChooseMode(self): self.disableChoiceButtons() def enterObserving(self): self.enableStopObserveButton() self.moveCamera(self.seatBumpForObserve) #track.append(Func(self.__disableCollisions)) self.sendUpdate('requestGameZone') #self.gameZone = base.cr.addInterest(base.localAvatar.defaultShard, boardZoneId, 'chineseBoard') def exitObserving(self): #self.__enableCollisions if self.cameraBoardTrack.isPlaying(): self.cameraBoardTrack.pause() self.allowToWalk() #temp until i can stop the #camera from jerking self.stopObserveButton.destroy() def enterSitting(self): pass #self.tempCheckers.hide() def exitSitting(self): self.gameMenu = None #self.winTrack = None #self.tempCheckers.show() #self.suxButton.destroy() #self.sendUpdate('requestExit', []) ########## #Observer Functions setGameZone (broadcast) # #Need these because you are not "filling" a slot by observing # #For this case - When it sends a 1 or a zero with the setGameZone, This is to account for the fact #an observer can (and will) come into games halfway through, somehow that client needs to know #about the current state of the game. # # #1 == Playing #0 == Not Playing ########## def setGameZone(self, zoneId, gamestate): self.gameZone = base.cr.addInterest(base.localAvatar.defaultShard, zoneId, 'gameBoard') self.gameState = gamestate def observeButtonPushed(self): #base.cr.playGame.getPlace().setState('walk') self.requestSeat = None self.fsm.request('observing') def enableStopObserveButton(self): self.stopObserveButton = DirectButton( relief=None, text="Stop Observing", text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.45, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.4), scale=0.15, command=lambda self=self: self.stopObserveButtonPushed(), ) def stopObserveButtonPushed(self): self.sendUpdate("leaveObserve", []) self.gameState = None if self.game: self.game.fsm.request('gameOver') base.cr.removeInterest(self.gameZone) self.fsm.request('off') ########## #Generators for jumps # #And the storage/deletion functions for #handling them. ########## def generateToonReverseJumpTrack(self, av, seatIndex): """Return an interval of the toon jumping out of the golf kart.""" self.notify.debug("av.getH() = %s" % av.getH()) def getToonJumpTrack(av, destNode): # using a local func allows the ProjectileInterval to # calculate this pos at run-time def getJumpDest(av=av, node=destNode): dest = node.getPos(self.tableCloth) dest += self.jumpOffsets[seatIndex].getPos(self.tableCloth) return dest def getJumpHpr(av=av, node=destNode): hpr = node.getHpr(av.getParent()) hpr.setX(hpr.getX() + 180) angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX()) hpr.setX(angle) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.1), #43 ), Parallel( #LerpHprInterval( av, # hpr = getJumpHpr, # duration = .9 ), ProjectileInterval(av, endPos=getJumpDest, duration=.9)))) return toonJumpTrack toonJumpTrack = getToonJumpTrack(av, self.tableCloth) #self.seats[seatIndex]) jumpTrack = Sequence( toonJumpTrack, Func(av.loop, 'neutral'), Func(av.wrtReparentTo, render), #Func( self.av.setPosHpr, self.exitMovieNode, 0,0,0,0,0,0 ), ) return jumpTrack def generateToonJumpTrack(self, av, seatIndex): """Return an interval of the toon jumping into the golf kart.""" # Maintain a reference to Parent and Scale of avatar in case they # exit from the kart. #base.sb = self av.pose('sit', 47) hipOffset = av.getHipsParts()[2].getPos(av) def getToonJumpTrack(av, seatIndex): # using a local func allows the ProjectileInterval to # calculate this pos at run-time def getJumpDest(av=av, node=self.tableCloth): dest = Vec3(self.tableCloth.getPos(av.getParent())) seatNode = self.picnicTable.find("**/seat" + str(seatIndex + 1)) dest += seatNode.getPos(self.tableCloth) dna = av.getStyle() dest -= hipOffset if (seatIndex > 2): dest.setY(dest.getY() - 2.0) if (seatIndex == 1): dest.setY(dest.getY() - .5) #dest.setY( dest.getY() + 2 * hipOffset.getY()) #dest.setY(dest.getY()) dest.setZ(dest.getZ() + 0.2) return dest def getJumpHpr(av=av, node=self.tableCloth): hpr = self.seats[seatIndex].getHpr(av.getParent()) if (seatIndex < 3): hpr.setX(hpr.getX()) else: if (av.getH() < 0): hpr.setX(hpr.getX() - 180) else: hpr.setX(hpr.getX() + 180) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.43), Parallel( LerpHprInterval(av, hpr=getJumpHpr, duration=1), ProjectileInterval(av, endPos=getJumpDest, duration=1)), )) return toonJumpTrack def getToonSitTrack(av): toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit')) return toonSitTrack toonJumpTrack = getToonJumpTrack(av, seatIndex) toonSitTrack = getToonSitTrack(av) jumpTrack = Sequence( Parallel( toonJumpTrack, Sequence( Wait(1), toonSitTrack, ), ), Func(av.wrtReparentTo, self.tableCloth), ) return jumpTrack def storeToonTrack(self, avId, track): # Clear out any currently playing tracks on this toon self.clearToonTrack(avId) # Store this new one self.__toonTracks[avId] = track def clearToonTrack(self, avId): # Clear out any currently playing tracks on this toon oldTrack = self.__toonTracks.get(avId) if oldTrack: oldTrack.pause() cleanupDelayDeletes(oldTrack) #del self.__toonTracks[avId] def clearToonTracks(self): #We can't use an iter because we are deleting keys keyList = [] for key in self.__toonTracks: keyList.append(key) for key in keyList: if key in self.__toonTracks: self.clearToonTrack(key) def doNothing(self): pass
class DistributedPicnicTable(DistributedNode.DistributedNode): def __init__(self, cr): self.cr = cr NodePath.__init__(self, 'DistributedPicnicTable') DistributedNode.DistributedNode.__init__(self, cr) self.reparentTo(render) self.picnicTable = loader.loadModel('phase_6/models/golf/game_table.bam') self.picnicTable.reparentTo(self) self.picnicTableSphereNodes = [] self.numSeats = 6 self.seats = [] self.jumpOffsets = [] self.inGame = False self.requestSeat = None self.gameState = None self.cameraBoardTrack = Func(self.doNothing) self.seatBumpForObserve = 0 self.winTrack = Sequence() self.outTrack = Sequence() self.joinButton = None self.observeButton = None self.tutorialButton = None self.exitButton = None self.isPlaying = False self.gameMenu = None self.game = None self.gameZone = None self.tutorial = None self.timerFunc = None self.gameDoId = None self.gameWantTimer = False self.tableState = [None, None, None, None, None, None] self.haveAnimated = [] self.winSound = base.loader.loadSfx('phase_6/audio/sfx/KART_Applause_1.ogg') self.happyDance = base.loader.loadSfx('phase_5/audio/sfx/AA_heal_happydance.ogg') self.accept('stoppedAsleep', self.handleSleep) base.localAvatar.startSleepWatch(self.handleSleep) self.__toonTracks = {} self.fsm = ClassicFSM.ClassicFSM('PicnicTable', [State.State('off', self.enterOff, self.exitOff, ['chooseMode', 'observing']), State.State('chooseMode', self.enterChooseMode, self.exitChooseMode, ['sitting', 'off', 'observing']), State.State('sitting', self.enterSitting, self.exitSitting, ['off']), State.State('observing', self.enterObserving, self.exitObserving, ['off'])], 'off', 'off') self.fsm.enterInitialState() for i in range(self.numSeats): self.seats.append(self.picnicTable.find('**/*seat%d' % (i + 1))) self.jumpOffsets.append(self.picnicTable.find('**/*jumpOut%d' % (i + 1))) self.tableCloth = self.picnicTable.find('**/basket_locator') self.tableclothSphereNode = self.tableCloth.attachNewNode(CollisionNode('tablecloth_sphere')) self.tableclothSphereNode.node().addSolid(CollisionSphere(0, 0, -2, 5.5)) self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() return def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) for i in range(self.numSeats): self.picnicTableSphereNodes.append(self.seats[i].attachNewNode(CollisionNode('picnicTable_sphere_%d_%d' % (self.getDoId(), i)))) self.picnicTableSphereNodes[i].node().addSolid(CollisionSphere(0, 0, 0, 2)) self.tableState = [None, None, None, None, None, None] self.requestTableState() self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') angle = self.getH() angle -= 90 radAngle = deg2Rad(angle) unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0) unitVec *= 30.0 self.endPos = self.getPos() + unitVec dist = Vec3(self.endPos - self.getPos()).length() wheelAngle = dist / (0.5 * 1.4 * math.pi) * 360 self.__enableCollisions() return def handleSleep(self, task = None): if self.fsm.getCurrentState().getName() == 'chooseMode': self.cancelButtonPushed() elif self.fsm.getCurrentState().getName() == 'sitting': self.sendUpdate('requestExit', []) if self.gameMenu != None: self.gameMenu.removeButtons() self.gameMenu.picnicFunction = None self.gameMenu = None if task != None: task.done return def disable(self): DistributedNode.DistributedNode.disable(self) self.ignore('stoppedAsleep') self.clearToonTracks() self.__disableCollisions() self.disableChoiceButtons() self.picnicTable.removeNode() self.cameraBoardTrack = None return def delete(self): self.__disableCollisions() self.ignore('stoppedAsleep') DistributedNode.DistributedNode.delete(self) self.disableChoiceButtons() self.cameraBoardTrack = None del self.winTrack del self.outTrack self.fsm = None self.gameZone = None self.clearToonTracks() self.cameraBoardTrack = None return def setName(self, name): self.name = name def setGameDoId(self, doId): self.gameDoId = doId self.game = self.cr.doId2do[doId] self.game.setHpr(self.getHpr()) self.gameWantTimer = self.game.wantTimer if self.gameState == 1: self.game.fsm.request('playing') def setTimerFunc(self, function): self.timerFunc = function def setTimer(self, timerEnd): self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) self.timeLeft = int(time - globalClock.getRealTime()) if self.gameWantTimer and self.game != None: self.showTimer() return def showTimer(self): self.clockNode.stop() self.clockNode.countdown(self.timeLeft, self.timerFunc) self.clockNode.show() def requestTableState(self): self.sendUpdate('requestTableState', []) def setTableState(self, tableStateList, isplaying): y = 0 print('SET TABLE STATE') if isplaying == 0: self.isPlaying = False else: self.isPlaying = True for x in tableStateList: if x != 0: if x not in self.tableState and x in self.cr.doId2do and x not in self.haveAnimated: seatIndex = tableStateList.index(x) toon = self.cr.doId2do[x] toon.stopSmooth() toon.setAnimState('Sit', 1.0) dest = self.seats[seatIndex].getPos(self.tableCloth) hpr = self.seats[seatIndex].getHpr(render) toon.setHpr(hpr) if seatIndex > 2: toon.setH(self.getH() + 180) toon.wrtReparentTo(self) toon.setPos(dest) toon.setZ(toon.getZ() + 1.35) if seatIndex > 2: toon.setY(toon.getY() - 1.0) else: toon.setY(toon.getY() + 1.0) if x != 0: self.tableState[y] = x else: self.tableState[y] = None y = y + 1 numPlayers = 0 for x in self.tableState: if x != None: numPlayers += 1 print(' GETTING 2', self.gameMenu, numPlayers) if self.gameMenu: if numPlayers > 2: print(' GETTING HERE!!') self.gameMenu.FindFour.setColor(0.7, 0.7, 0.7, 0.7) self.gameMenu.FindFour['command'] = self.doNothing self.gameMenu.findFourText['fg'] = (0.7, 0.7, 0.7, 0.7) self.gameMenu.Checkers.setColor(0.7, 0.7, 0.7, 0.7) self.gameMenu.Checkers['command'] = self.doNothing self.gameMenu.checkersText['fg'] = (0.7, 0.7, 0.7, 0.7) return def setIsPlaying(self, isPlaying): if isPlaying == 0: self.isPlaying = False elif isPlaying == 1: self.isPlaying = True def announceWinner(self, winString, avId): if avId == base.localAvatar.getDoId(): sound = Sequence(Wait(2.0), Parallel(SoundInterval(self.winSound), SoundInterval(self.happyDance))) sound.start() base.cr.playGame.getPlace().setState('walk') if winString == 'Chinese Checkers': whisper = WhisperPopup(TTLocalizer.ChineseCheckersYouWon, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == 'Checkers': whisper = WhisperPopup(TTLocalizer.RegularCheckersYouWon, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == 'Find Four': whisper = WhisperPopup('You won a game of Find Four!', OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif avId in self.cr.doId2do: stateString = self.fsm.getCurrentState().getName() if stateString == 'sitting' or stateString == 'observing': base.cr.playGame.getPlace().setState('walk') av = self.cr.doId2do[avId] if winString == 'Chinese Checkers': whisper = WhisperPopup(av.getName() + TTLocalizer.ChineseCheckersGameOf + TTLocalizer.ChineseCheckers, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == 'Checkers': whisper = WhisperPopup(av.getName() + TTLocalizer.RegularCheckersGameOf + TTLocalizer.RegularCheckers, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) elif winString == 'Find Four': whisper = WhisperPopup(av.getName() + ' has won a game of' + ' Find Four!', OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) if avId in self.cr.doId2do: toon = self.cr.doId2do[avId] self.winTrack = Sequence(autoFinish=1) if self.outTrack.isPlaying(): self.winTrack.append(Wait(2.0)) if avId == base.localAvatar.getDoId(): self.winTrack.append(Func(self.stopToWalk)) self.winTrack.append(ActorInterval(toon, 'happy-dance')) if avId == base.localAvatar.getDoId(): self.winTrack.append(Func(self.allowToWalk)) self.winTrack.start() whisper.manage(base.marginManager) def handleEnterPicnicTableSphere(self, i, collEntry): self.notify.debug('Entering Picnic Table Sphere.... %s' % self.getDoId()) self.requestSeat = i self.seatBumpForObserve = i self.fsm.request('chooseMode') def enableChoiceButtons(self): if self.tableState[self.seatBumpForObserve] == None and self.isPlaying == False: self.joinButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableJoinButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, 0.8), scale=0.15, command=lambda self = self: self.joinButtonPushed()) if self.isPlaying == True: self.observeButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableObserveButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0, 0, 0.6), scale=0.15, command=lambda self = self: self.observeButtonPushed()) self.exitButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableCancelButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(1, 0, 0.6), scale=0.15, command=lambda self = self: self.cancelButtonPushed()) self.tutorialButton = DirectButton( relief=None, text=TTLocalizer.PicnicTableTutorial, text_fg=(1, 1, 0.65, 1), text_pos=(-.05, -.13), text_scale=0.55, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-1, 0, 0.6), scale=0.15, command=lambda self = self: self.tutorialButtonPushed()) base.cr.playGame.getPlace().setState('stopped') return def tutorialButtonPushed(self): self.disableChoiceButtons() self.gameMenu = GameMenu(self.tutorialFunction, 1) self.tutorialButton.destroy() self.tutorialButton = None return def tutorialFunction(self, tutVal): if tutVal == 1: self.tutorial = ChineseTutorial(self.tutorialDone) elif tutVal == 2: self.tutorial = CheckersTutorial(self.tutorialDone) self.gameMenu.picnicFunction = None self.gameMenu = None return def tutorialDone(self): self.requestSeat = None self.fsm.request('off') self.tutorial = None return def joinButtonPushed(self): toon = base.localAvatar self.sendUpdate('requestJoin', [self.requestSeat, toon.getX(), toon.getY(), toon.getZ(), toon.getH(), toon.getP(), toon.getR()]) self.requestSeat = None self.fsm.request('sitting') return def rejectJoin(self): self.fsm.request('off') self.allowToWalk() def cancelButtonPushed(self): base.cr.playGame.getPlace().setState('walk') self.requestSeat = None self.fsm.request('off') return def disableChoiceButtons(self): if self.joinButton: self.joinButton.destroy() if self.observeButton: self.observeButton.destroy() if self.exitButton: self.exitButton.destroy() if self.tutorialButton: self.tutorialButton.destroy() def pickFunction(self, gameNum): if gameNum == 1: self.sendUpdate('requestPickedGame', [gameNum]) elif gameNum == 2: self.sendUpdate('requestPickedGame', [gameNum]) elif gameNum == 3: self.sendUpdate('requestPickedGame', [gameNum]) def allowPick(self): self.gameMenu = GameMenu(self.pickFunction, 2) def setZone(self, zoneId): if self.fsm.getCurrentState().getName() == 'sitting' or self.fsm.getCurrentState().getName() == 'observing': if self.tutorial == None: self.gameZone = base.cr.addInterest(base.localAvatar.defaultShard, zoneId, 'gameBoard') if self.gameMenu != None: self.gameMenu.removeButtons() self.gameMenu.picnicFunction = None self.gameMenu = None return def fillSlot(self, avId, index, x, y, z, h, p, r, timestamp, parentDoId): self.notify.debug('fill Slot: %d for %d' % (index, avId)) if avId not in self.haveAnimated: self.haveAnimated.append(avId) if avId == base.localAvatar.getDoId(): if self.inGame == True: return else: self.inGame = True self.seatPos = index if avId in self.cr.doId2do: toon = self.cr.doId2do[avId] toon.stopSmooth() toon.wrtReparentTo(self.tableCloth) sitStartDuration = toon.getDuration('sit-start') jumpTrack = self.generateToonJumpTrack(toon, index) track = Sequence(autoFinish=1) if avId == base.localAvatar.getDoId(): if not base.cr.playGame.getPlace() == None: self.moveCamera(index) track.append(Func(self.__disableCollisions)) track.append(jumpTrack) track.append(Func(toon.setAnimState, 'Sit', 1.0)) track.append(Func(self.clearToonTrack, avId)) self.storeToonTrack(avId, track) track.start() return def emptySlot(self, avId, index, timestamp): self.notify.debug('### seat %s now empty' % index) if index == 255 and self.game != None: self.stopObserveButtonPushed() return if avId in self.haveAnimated: self.haveAnimated.remove(avId) if avId in self.cr.doId2do: if avId == base.localAvatar.getDoId(): if self.gameZone: base.cr.removeInterest(self.gameZone) if self.inGame == True: self.inGame = False else: return toon = self.cr.doId2do[avId] toon.stopSmooth() sitStartDuration = toon.getDuration('sit-start') jumpOutTrack = self.generateToonReverseJumpTrack(toon, index) self.outTrack = Sequence(jumpOutTrack) if base.localAvatar.getDoId() == avId: self.outTrack.append(Func(self.__enableCollisions)) self.outTrack.append(Func(self.allowToWalk)) self.fsm.request('off') val = self.jumpOffsets[index].getPos(render) self.outTrack.append(Func(toon.setPos, val)) self.outTrack.append(Func(toon.startSmooth)) self.outTrack.start() return def stopToWalk(self): base.cr.playGame.getPlace().setState('stopped') def allowToWalk(self): base.cr.playGame.getPlace().setState('walk') def moveCamera(self, seatIndex): self.oldCameraPos = camera.getPos() self.oldCameraHpr = camera.getHpr() camera.wrtReparentTo(self.picnicTable) heading = PythonUtil.fitDestAngle2Src(camera.getH(), 90) if seatIndex < 3: self.cameraBoardTrack = LerpPosHprInterval(camera, 2.0, Point3(0, 0, 17), Point3(0, -90, 0)) elif camera.getH() < 0: self.cameraBoardTrack = LerpPosHprInterval(camera, 2.0, Point3(0, 0, 17), Point3(-180, -90, 0)) else: self.cameraBoardTrack = LerpPosHprInterval(camera, 2.0, Point3(0, 0, 17), Point3(180, -90, 0)) self.cameraBoardTrack.start() def moveCameraBack(self): self.cameraBoardTrack = LerpPosHprInterval(camera, 2.5, self.oldCameraPos, self.oldCameraHpr) self.cameraBoardTrack.start() def __enableCollisions(self): for i in range(self.numSeats): self.accept('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTableSphere, [i]) self.picnicTableSphereNodes[i].setCollideMask(ToontownGlobals.WallBitmask) self.tableclothSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def __disableCollisions(self): for i in range(self.numSeats): self.ignore('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i)) self.ignore('enterPicnicTableOK_%d_%d' % (self.getDoId(), i)) for i in range(self.numSeats): self.picnicTableSphereNodes[i].setCollideMask(BitMask32(0)) self.tableclothSphereNode.setCollideMask(BitMask32(0)) def enterOff(self): base.setCellsAvailable(base.leftCells + base.bottomCells, 0) def exitOff(self): base.setCellsAvailable(base.bottomCells, 0) def enterChooseMode(self): self.winTrack = Sequence(autoFinish=1) self.enableChoiceButtons() def exitChooseMode(self): self.disableChoiceButtons() def enterObserving(self): self.enableStopObserveButton() self.moveCamera(self.seatBumpForObserve) self.sendUpdate('requestGameZone') def exitObserving(self): if self.cameraBoardTrack.isPlaying(): self.cameraBoardTrack.pause() self.allowToWalk() self.stopObserveButton.destroy() def enterSitting(self): pass def exitSitting(self): self.gameMenu = None return def setGameZone(self, zoneId, gamestate): self.gameZone = base.cr.addInterest(base.localAvatar.defaultShard, zoneId, 'gameBoard') self.gameState = gamestate def observeButtonPushed(self): self.requestSeat = None self.fsm.request('observing') return def enableStopObserveButton(self): self.stopObserveButton = DirectButton( relief=None, text='Stop Observing', text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.45, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self = self: self.stopObserveButtonPushed()) return def stopObserveButtonPushed(self): self.sendUpdate('leaveObserve', []) self.gameState = None if self.game: self.game.fsm.request('gameOver') base.cr.removeInterest(self.gameZone) self.fsm.request('off') return def generateToonReverseJumpTrack(self, av, seatIndex): self.notify.debug('av.getH() = %s' % av.getH()) def getToonJumpTrack(av, destNode): def getJumpDest(av = av, node = destNode): dest = node.getPos(self.tableCloth) dest += self.jumpOffsets[seatIndex].getPos(self.tableCloth) return dest def getJumpHpr(av = av, node = destNode): hpr = node.getHpr(av.getParent()) hpr.setX(hpr.getX() + 180) angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX()) hpr.setX(angle) return hpr toonJumpTrack = Parallel(ActorInterval(av, 'jump'), Sequence(Wait(0.1), Parallel(ProjectileInterval(av, endPos=getJumpDest, duration=0.9)))) return toonJumpTrack toonJumpTrack = getToonJumpTrack(av, self.tableCloth) jumpTrack = Sequence(toonJumpTrack, Func(av.loop, 'neutral'), Func(av.wrtReparentTo, render)) return jumpTrack def generateToonJumpTrack(self, av, seatIndex): av.pose('sit', 47) hipOffset = av.getHipsParts()[2].getPos(av) def getToonJumpTrack(av, seatIndex): def getJumpDest(av = av, node = self.tableCloth): dest = Vec3(self.tableCloth.getPos(av.getParent())) seatNode = self.picnicTable.find('**/seat' + str(seatIndex + 1)) dest += seatNode.getPos(self.tableCloth) dna = av.getStyle() dest -= hipOffset if seatIndex > 2: dest.setY(dest.getY() - 2.0) if seatIndex == 1: dest.setY(dest.getY() - 0.5) dest.setZ(dest.getZ() + 0.2) return dest def getJumpHpr(av = av, node = self.tableCloth): hpr = self.seats[seatIndex].getHpr(av.getParent()) if seatIndex < 3: hpr.setX(hpr.getX()) elif av.getH() < 0: hpr.setX(hpr.getX() - 180) else: hpr.setX(hpr.getX() + 180) return hpr toonJumpTrack = Parallel(ActorInterval(av, 'jump'), Sequence(Wait(0.43), Parallel(LerpHprInterval(av, hpr=getJumpHpr, duration=1), ProjectileInterval(av, endPos=getJumpDest, duration=1)))) return toonJumpTrack def getToonSitTrack(av): toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit')) return toonSitTrack toonJumpTrack = getToonJumpTrack(av, seatIndex) toonSitTrack = getToonSitTrack(av) jumpTrack = Sequence(Parallel(toonJumpTrack, Sequence(Wait(1), toonSitTrack)), Func(av.wrtReparentTo, self.tableCloth)) return jumpTrack def storeToonTrack(self, avId, track): self.clearToonTrack(avId) self.__toonTracks[avId] = track def clearToonTrack(self, avId): oldTrack = self.__toonTracks.get(avId) if oldTrack: oldTrack.pause() cleanupDelayDeletes(oldTrack) def clearToonTracks(self): keyList = [] for key in self.__toonTracks: keyList.append(key) for key in keyList: if key in self.__toonTracks: self.clearToonTrack(key) def doNothing(self): pass
class DistributedChineseCheckers(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, 'DistributedChineseCheckers') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel('phase_6/models/golf/checker_game.bam') self.boardNode.reparentTo(self) self.board = ChineseCheckersBoard() self.playerTags = render.attachNewNode('playerTags') self.playerTagList = [] self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.playerColors = [Vec4(0, 0.9, 0, 1), Vec4(0.9, 0.9, 0, 1), Vec4(0.45, 0, 0.45, 1), Vec4(0.2, 0.4, 0.8, 1), Vec4(1, 0.45, 1, 1), Vec4(0.8, 0, 0, 1)] self.tintConstant = Vec4(0.25, 0.25, 0.25, 0) self.ghostConstant = Vec4(0, 0, 0, 0.5) self.startingPositions = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 23, 24, 25, 35, 36, 46], [65, 75, 76, 86, 87, 88, 98, 99, 100, 101], [111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [74, 84, 85, 95, 96, 97, 107, 108, 109, 110], [19, 20, 21, 22, 32, 33, 34, 44, 45, 55]] self.nonOpposingPositions = [] self.knockSound = base.loadSfx('phase_5/audio/sfx/GUI_knock_1.ogg') self.clickSound = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.ogg') self.moveSound = base.loadSfx('phase_6/audio/sfx/CC_move.ogg') self.accept('stoppedAsleep', self.handleSleep) from direct.fsm import ClassicFSM, State self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin'])], 'waitingToBegin', 'waitingToBegin') x = self.boardNode.find('**/locators') self.locatorList = x.getChildren() tempList = [] for x in xrange(0, 121): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) tempList.append(self.locatorList[x].attachNewNode(CollisionNode('picker%d' % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.115)) for z in self.locatorList: y = loader.loadModel('phase_6/models/golf/checker_marble.bam') z.setColor(0, 0, 0, 0) y.reparentTo(z) return def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: self.seatPos = self.table.tableState.index(base.localAvatar.doId) self.playerTags.setPos(self.getPos()) def handleSleep(self, task = None): if self.fsm.getCurrentState().getName() == 'waitingToBegin': self.exitButtonPushed() if task != None: task.done return def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.cleanPlayerTags() return def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None self.cleanPlayerTags() del self.playerTags del self.playerTagList self.playerSeats = None self.yourTurnBlinker.finish() return def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState().getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0 and timerEnd != 0: if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() return def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(-.74, 0, -0.2) if self.isMyTurn: self.clockNode.countdown(timeLeft, self.doRandomMove) else: self.clockNode.countdown(timeLeft, self.doNothing) self.clockNode.show() return def gameStart(self, playerNum): if playerNum != 255: self.playerNum = playerNum self.playerColor = self.playerColors[playerNum - 1] self.moveCameraForGame() playerPos = playerNum - 1 import copy self.nonOpposingPositions = copy.deepcopy(self.startingPositions) if playerPos == 0: self.nonOpposingPositions.pop(0) self.opposingPositions = self.nonOpposingPositions.pop(2) elif playerPos == 1: self.nonOpposingPositions.pop(1) self.opposingPositions = self.nonOpposingPositions.pop(3) elif playerPos == 2: self.nonOpposingPositions.pop(2) self.opposingPositions = self.nonOpposingPositions.pop(4) elif playerPos == 3: self.nonOpposingPositions.pop(3) self.opposingPositions = self.nonOpposingPositions.pop(0) elif playerPos == 4: self.nonOpposingPositions.pop(4) self.opposingPositions = self.nonOpposingPositions.pop(1) elif playerPos == 5: self.nonOpposingPositions.pop(5) self.opposingPositions = self.nonOpposingPositions.pop(2) self.fsm.request('playing') def sendTurn(self, playersTurn): self.playersTurnBlinker.finish() if self.fsm.getCurrentState().getName() == 'playing': if self.playerSeats == None: self.sendUpdate('requestSeatPositions', []) else: if playersTurn == self.playerNum: self.isMyTurn = True self.enableTurnScreenText(playersTurn) self.playersTurnBlinker = Sequence() origColor = self.playerColors[playersTurn - 1] self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], 0.4, origColor - self.tintConstant - self.ghostConstant, origColor)) self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], 0.4, origColor, origColor - self.tintConstant - self.ghostConstant)) self.playersTurnBlinker.loop() return def announceSeatPositions(self, playerPos): self.playerSeats = playerPos for x in xrange(6): pos = self.table.seats[x].getPos(render) renderedPeice = loader.loadModel('phase_6/models/golf/checker_marble.bam') renderedPeice.reparentTo(self.playerTags) renderedPeice.setPos(pos) renderedPeice.setScale(1.5) if x == 1: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.setScale(1.3) elif x == 4: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.setScale(1.45) else: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.hide() self.playerTagList = self.playerTags.getChildren() for x in playerPos: if x != 0: self.playerTagList[playerPos.index(x)].setColor(self.playerColors[x - 1]) self.playerTagList[playerPos.index(x)].show() def cleanPlayerTags(self): for x in self.playerTagList: x.removeNode() self.playerTagList = [] self.playerTags.removeNode() def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.finish() rotation = 0 if self.seatPos > 2: if self.playerNum == 1: rotation = 180 elif self.playerNum == 2: rotation = -120 elif self.playerNum == 3: rotation = -60 elif self.playerNum == 4: rotation = 0 elif self.playerNum == 5: rotation = 60 elif self.playerNum == 6: rotation = 120 elif self.playerNum == 1: rotation = 0 elif self.playerNum == 2: rotation = 60 elif self.playerNum == 3: rotation = 120 elif self.playerNum == 4: rotation = 180 elif self.playerNum == 5: rotation = -120 elif self.playerNum == 6: rotation = -60 if rotation == 60 or rotation == -60: int = LerpHprInterval(self.boardNode, 2.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) elif rotation == 120 or rotation == -120: int = LerpHprInterval(self.boardNode, 3.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) else: int = LerpHprInterval(self.boardNode, 4.2, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) int.start() def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() return def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.cleanPlayerTags() return def enterGameOver(self): pass def exitGameOver(self): pass def exitWaitCountdown(self): self.__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersGetUpButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self = self: self.exitButtonPushed()) return def enableScreenText(self): defaultPos = (-.8, -0.4) if self.playerNum == 1: message = TTLocalizer.ChineseCheckersColorG color = self.playerColors[0] elif self.playerNum == 2: message = TTLocalizer.ChineseCheckersColorY color = self.playerColors[1] elif self.playerNum == 3: message = TTLocalizer.ChineseCheckersColorP color = self.playerColors[2] elif self.playerNum == 4: message = TTLocalizer.ChineseCheckersColorB color = self.playerColors[3] elif self.playerNum == 5: message = TTLocalizer.ChineseCheckersColorPink color = self.playerColors[4] elif self.playerNum == 6: message = TTLocalizer.ChineseCheckersColorR color = self.playerColors[5] else: message = TTLocalizer.ChineseCheckersColorO color = Vec4(0.0, 0.0, 0.0, 1.0) defaultPos = (-.8, -0.4) self.screenText = OnscreenText(text=message, pos=defaultPos, scale=0.1, fg=color, align=TextNode.ACenter, mayChange=1) def enableStartButton(self): self.startButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersStartButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.6, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.1), scale=0.15, command=lambda self = self: self.startButtonPushed()) return def enableLeaveButton(self): self.leaveButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersQuitButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.13), text_scale=0.5, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self = self: self.exitButtonPushed()) return def enableTurnScreenText(self, player): self.yourTurnBlinker.finish() playerOrder = [1, 4, 2, 5, 3, 6] message1 = TTLocalizer.ChineseCheckersIts if self.turnText != None: self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) elif player == 1: message2 = TTLocalizer.ChineseCheckersGreenTurn color = self.playerColors[0] elif player == 2: message2 = TTLocalizer.ChineseCheckersYellowTurn color = self.playerColors[1] elif player == 3: message2 = TTLocalizer.ChineseCheckersPurpleTurn color = self.playerColors[2] elif player == 4: message2 = TTLocalizer.ChineseCheckersBlueTurn color = self.playerColors[3] elif player == 5: message2 = TTLocalizer.ChineseCheckersPinkTurn color = self.playerColors[4] elif player == 6: message2 = TTLocalizer.ChineseCheckersRedTurn color = self.playerColors[5] self.turnText = OnscreenText(text=message1 + message2, pos=(-0.8, -0.5), scale=0.092, fg=color, align=TextNode.ACenter, mayChange=1) if player == self.playerNum: self.yourTurnBlinker = Sequence() self.yourTurnBlinker.append(LerpScaleInterval(self.turnText, 0.6, 1.045, 1)) self.yourTurnBlinker.append(LerpScaleInterval(self.turnText, 0.6, 1, 1.045)) self.yourTurnBlinker.loop() return def startButtonPushed(self): self.sendUpdate('requestBegin') self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate('requestExit') def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True: mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() pickedObj = self.myHandler.getEntry(0).getIntoNodePath() pickedObj = pickedObj.getNetTag('GamePeiceLocator') if pickedObj: self.handleClicked(int(pickedObj)) def handleClicked(self, index): self.sound = Sequence(SoundInterval(self.clickSound)) if self.moveList == []: if index not in self.mySquares: return self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False self.blinker = Sequence() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() elif self.board.squareList[index].getState() == self.playerNum: for x in self.moveList: self.locatorList[x].setColor(1, 1, 1, 1) self.locatorList[x].hide() self.blinker.finish() self.blinker = Sequence() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() self.locatorList[self.moveList[0]].setColor(self.playerColor) self.locatorList[self.moveList[0]].show() self.moveList = [] self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False elif self.board.squareList[index].getState() != 0: return else: if len(self.moveList) == 1 and self.board.squareList[index].getState() == 0: if index in self.board.squareList[self.moveList[0]].getAdjacent(): for x in self.nonOpposingPositions: if index in x: return self.moveList.append(index) self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() if len(self.moveList) >= 1: if index == self.moveList[len(self.moveList) - 1]: for x in self.nonOpposingPositions: if index in x: return if self.existsLegalJumpsFrom(index) == True: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() elif self.checkLegalMove(self.board.getSquare(self.moveList[len(self.moveList) - 1]), self.board.getSquare(index)) == True: if index not in self.board.squareList[self.moveList[len(self.moveList) - 1]].getAdjacent(): for x in self.nonOpposingPositions: if self.existsLegalJumpsFrom(index) == False: if index in x: return self.moveList.append(index) self.locatorList[index].setColor(self.playerColor - self.tintConstant - self.ghostConstant) self.locatorList[index].show() self.sound.start() if self.existsLegalJumpsFrom(index) == False: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False def existsLegalJumpsFrom(self, index): for x in self.board.squareList[index].getAdjacent(): if x == None: pass elif x in self.moveList: pass elif self.board.getState(x) == 0: pass elif self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)] == None: pass elif self.board.getState(self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)]) == 0 and self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)] not in self.moveList: return True return False def checkLegalMove(self, firstSquare, secondSquare): if secondSquare.getNum() in firstSquare.getAdjacent(): return True else: for x in firstSquare.getAdjacent(): if x == None: pass elif self.board.squareList[x].getState() == 0: pass elif self.board.squareList[x].getAdjacent()[firstSquare.getAdjacent().index(x)] == secondSquare.getNum(): return True return False return def d_requestMove(self, moveList): self.sendUpdate('requestMove', [moveList]) def setGameState(self, tableState, moveList): if moveList != []: self.animatePeice(tableState, moveList) else: self.updateGameState(tableState) def updateGameState(self, squares): self.board.setStates(squares) self.mySquares = [] messenger.send('wakeup') for x in xrange(121): self.locatorList[x].clearColor() owner = self.board.squareList[x].getState() if owner == self.playerNum: self.mySquares.append(x) if owner == 0: self.locatorList[x].hide() else: self.locatorList[x].show() if owner == 1: self.locatorList[x].setColor(self.playerColors[0]) elif owner == 2: self.locatorList[x].setColor(self.playerColors[1]) elif owner == 3: self.locatorList[x].setColor(self.playerColors[2]) elif owner == 4: self.locatorList[x].setColor(self.playerColors[3]) elif owner == 5: self.locatorList[x].setColor(self.playerColors[4]) elif owner == 6: self.locatorList[x].setColor(self.playerColors[5]) self.mySquares.sort() self.checkForWin() def animatePeice(self, tableState, moveList): messenger.send('wakeup') gamePeiceForAnimation = loader.loadModel('phase_6/models/golf/checker_marble.bam') gamePeiceForAnimation.setColor(self.locatorList[moveList[0]].getColor()) gamePeiceForAnimation.reparentTo(self.boardNode) gamePeiceForAnimation.setPos(self.locatorList[moveList[0]].getPos()) self.locatorList[moveList[0]].hide() checkersPeiceTrack = Sequence() length = len(moveList) for x in xrange(length - 1): checkersPeiceTrack.append(Parallel(SoundInterval(self.moveSound), ProjectileInterval(gamePeiceForAnimation, endPos=self.locatorList[moveList[x + 1]].getPos(), duration=0.5))) checkersPeiceTrack.append(Func(gamePeiceForAnimation.removeNode)) checkersPeiceTrack.append(Func(self.updateGameState, tableState)) checkersPeiceTrack.start() def checkForWin(self): if self.playerNum == 1: if self.mySquares == self.startingPositions[3]: self.sendUpdate('requestWin', []) elif self.playerNum == 2: if self.mySquares == self.startingPositions[4]: self.sendUpdate('requestWin', []) elif self.playerNum == 3: if self.mySquares == self.startingPositions[5]: self.sendUpdate('requestWin', []) elif self.playerNum == 4: if self.mySquares == self.startingPositions[0]: self.sendUpdate('requestWin', []) elif self.playerNum == 5: if self.mySquares == self.startingPositions[1]: self.sendUpdate('requestWin', []) elif self.playerNum == 6: if self.mySquares == self.startingPositions[2]: self.sendUpdate('requestWin', []) def announceWin(self, avId): self.fsm.request('gameOver') def doRandomMove(self): if len(self.moveList) >= 2: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.playSound = Sequence(SoundInterval(self.knockSound)) self.playSound.start() else: import random move = [] foundLegal = False self.blinker.pause() self.numRandomMoves += 1 while not foundLegal: x = random.randint(0, 9) for y in self.board.getAdjacent(self.mySquares[x]): if y != None and self.board.getState(y) == 0: for zz in self.nonOpposingPositions: if y not in zz: move.append(self.mySquares[x]) move.append(y) foundLegal = True break break if move == []: pass playSound = Sequence(SoundInterval(self.knockSound)) playSound.start() self.d_requestMove(move) self.moveList = [] self.isMyTurn = False if self.numRandomMoves >= 5: self.exitButtonPushed() return def doNothing(self): pass
class DistributedFindFour(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, 'DistributedFindFour') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel( 'phase_6/models/golf/findfour_game.bam') self.boardNode.reparentTo(self) self.board = [[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]] self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.winningSequence = Sequence() self.moveSequence = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None self.moveCol = None self.move = None self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(BitMask32(4096)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel( 'phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find( '**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.tintConstant = Vec4(0.25, 0.25, 0.25, 0) self.ghostConstant = Vec4(0, 0, 0, 0.5) self.knockSound = base.loadSfx('phase_5/audio/sfx/GUI_knock_1.mp3') self.clickSound = base.loadSfx( 'phase_3/audio/sfx/GUI_balloon_popup.mp3') self.moveSound = base.loadSfx('phase_6/audio/sfx/CC_move.mp3') self.accept('stoppedAsleep', self.handleSleep) from direct.fsm import ClassicFSM, State self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [ State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin']) ], 'waitingToBegin', 'waitingToBegin') startLoc = self.boardNode.find('**/locators') self.locatorList = startLoc.getChildren() self.startingPositions = self.locatorList.pop(0) self.startingPositions = self.startingPositions.getChildren() instancePiece = self.boardNode.find('**/pieces') tempList = [] for x in range(7): self.startingPositions[x].setTag('StartLocator', '%d' % x) collNode = CollisionNode('startpicker%d' % x) collNode.setIntoCollideMask(BitMask32(4096)) tempList.append(self.startingPositions[x].attachNewNode(collNode)) tempList[x].node().addSolid( CollisionTube(0, 0, 0.23, 0, 0, -.23, 0.2)) for z in self.startingPositions: y = instancePiece.copyTo(z) for val in y.getChildren(): val.hide() tempList = [] for x in range(42): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) collNode = CollisionNode('startpicker%d' % x) collNode.setIntoCollideMask(BitMask32(4096)) tempList.append(self.locatorList[x].attachNewNode(collNode)) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.2)) for z in self.locatorList: y = instancePiece.copyTo(z) for val in y.getChildren(): val.hide() dummyHide = instancePiece.getParent().attachNewNode('DummyHider') instancePiece.reparentTo(dummyHide) dummyHide.hide() return def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: self.seatPos = self.table.tableState.index( base.localAvatar.doId) if self.seatPos <= 2: for x in self.startingPositions: x.setH(0) for x in self.locatorList: x.setH(0) else: for x in self.startingPositions: x.setH(180) for x in self.locatorList: x.setH(180) self.moveCameraForGame() else: self.seatPos = self.table.seatBumpForObserve if self.seatPos > 2: for x in self.startingPositions: x.setH(180) for x in self.locatorList: x.setH(180) self.moveCameraForGame() def handleSleep(self, task=None): if self.fsm.getCurrentState().getName() == 'waitingToBegin': self.exitButtonPushed() if task != None: task.done return def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None taskMgr.remove('playerTurnTask') return def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None self.winningSequence.finish() taskMgr.remove('playerTurnTask') return def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState( ).getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0 and timerEnd != 0: if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() return def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(0.64, 0, -0.27) self.clockNode.countdown(timeLeft, self.doRandomMove) self.clockNode.show() return def gameStart(self, playerNum): if playerNum != 255: self.playerNum = playerNum if self.playerNum == 1: self.playerColorString = 'Red' else: self.playerColorString = 'Yellow' self.moveCameraForGame() self.fsm.request('playing') def sendTurn(self, playersTurn): if self.fsm.getCurrentState().getName() == 'playing': if playersTurn == self.playerNum: self.isMyTurn = True taskMgr.add(self.turnTask, 'playerTurnTask') self.enableTurnScreenText(playersTurn) def illegalMove(self): self.exitButtonPushed() def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.pause() rotation = 0 if self.seatPos <= 2: position = self.table.seats[1].getPos() position = position + Vec3(0, -8, 12.8) int = LerpPosHprInterval(camera, 2, position, Vec3(0, -38, 0), camera.getPos(), camera.getHpr()) else: position = self.table.seats[4].getPos() position = position + Vec3(0, -8, 12.8) if camera.getH() < 0: int = LerpPosHprInterval(camera, 2, position, Vec3(-180, -20, 0), camera.getPos(), camera.getHpr()) else: int = LerpPosHprInterval(camera, 2, position, Vec3(180, -20, 0), camera.getPos(), camera.getHpr()) int.start() def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() return def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() return def enterGameOver(self): pass def exitGameOver(self): pass def exitWaitCountdown(self): self.__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersGetUpButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.8), scale=0.15, command=lambda self=self: self.exitButtonPushed()) return def enableScreenText(self): defaultPos = (-.7, -0.29) if self.playerNum == 1: message = 'You are Red' color = Vec4(1, 0, 0, 1) elif self.playerNum == 2: message = 'You are Yellow' color = Vec4(1, 1, 0, 1) else: message = TTLocalizer.CheckersObserver color = Vec4(0, 0, 0, 1) self.screenText = OnscreenText(text=message, pos=defaultPos, scale=0.1, fg=color, align=TextNode.ACenter, mayChange=1) def enableStartButton(self): self.startButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersStartButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.6, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.57), scale=0.15, command=lambda self=self: self.startButtonPushed()) return def enableLeaveButton(self): self.leaveButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersQuitButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.13), text_scale=0.5, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.8), scale=0.15, command=lambda self=self: self.exitButtonPushed()) return def enableTurnScreenText(self, player): playerOrder = [1, 4, 2, 5, 3, 6] message1 = TTLocalizer.CheckersIts if self.turnText != None: self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) elif player == 1: message2 = "Red's Turn" color = (1, 0, 0, 1) elif player == 2: message2 = "Yellow's Turn" color = (1, 1, 0, 1) self.turnText = OnscreenText(text=message1 + message2, pos=(-0.7, -0.39), scale=0.092, fg=color, align=TextNode.ACenter, mayChange=1) return def startButtonPushed(self): self.sendUpdate('requestBegin') self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate('requestExit') def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True and not self.moveSequence.isPlaying( ): if self.moveCol != None: self.d_requestMove(self.moveCol) self.moveCol = None self.isMyTurn = False taskMgr.remove('playerTurnTask') return def handleClicked(self, index): pass def turnTask(self, task): if base.mouseWatcherNode.hasMouse() == False: return task.cont if self.isMyTurn == False: return task.cont if self.moveSequence.isPlaying(): return task.cont mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() pickedObj = self.myHandler.getEntry(0).getIntoNodePath() pickedObj = pickedObj.getNetTag('StartLocator') if pickedObj: colVal = int(pickedObj) if colVal == self.moveCol: return task.cont if self.board[0][colVal] == 0: if self.moveCol != None: for x in self.startingPositions[self.moveCol].getChild( 1).getChildren(): x.hide() self.moveCol = colVal if self.playerNum == 1: self.startingPositions[self.moveCol].getChild( 1).getChild(2).show() elif self.playerNum == 2: self.startingPositions[self.moveCol].getChild( 1).getChild(3).show() return task.cont def d_requestMove(self, moveCol): self.sendUpdate('requestMove', [moveCol]) def setGameState(self, tableState, moveCol, movePos, turn): messenger.send('wakeup') if self.table.fsm.getCurrentState().getName() == 'observing': isBlank = True for x in range(7): if self.board[5][x] != 0: isBlank = False break gameBlank = True for x in range(7): if tableState[5][x] != 0: gameBlank = False break if isBlank == True and gameBlank == False: for x in range(6): for y in range(7): self.board[x][y] = tableState[x][y] self.updateGameState() return if moveCol == 0 and movePos == 0 and turn == 0: for x in range(6): for y in range(7): self.board[x][y] = tableState[x][y] self.updateGameState() else: self.animatePeice(tableState, moveCol, movePos, turn) didIWin = self.checkForWin() if didIWin != None: self.sendUpdate('requestWin', [didIWin]) return def updateGameState(self): for x in range(6): for y in range(7): for z in self.locatorList[x * 7 + y].getChild(1).getChildren(): z.hide() for x in range(6): for y in range(7): state = self.board[x][y] if state == 1: self.locatorList[x * 7 + y].getChild(1).getChild(0).show() elif state == 2: self.locatorList[x * 7 + y].getChild(1).getChild(1).show() def checkForWin(self): for x in range(6): for y in range(7): if self.board[x][y] == self.playerNum: if self.checkHorizontal(x, y, self.playerNum) == True: return [x, y] elif self.checkVertical(x, y, self.playerNum) == True: return [x, y] elif self.checkDiagonal(x, y, self.playerNum) == True: return [x, y] return None def announceWinnerPosition(self, x, y, winDirection, playerNum): self.isMyturn = False if self.turnText: self.turnText.hide() self.clockNode.stop() self.clockNode.hide() if winDirection == 0: blinkList = self.findHorizontal(x, y, playerNum) elif winDirection == 1: blinkList = self.findVertical(x, y, playerNum) elif winDirection == 2: blinkList = self.findDiagonal(x, y, playerNum) if blinkList != []: print blinkList val0 = x * 7 + y x = blinkList[0][0] y = blinkList[0][1] val1 = x * 7 + y x = blinkList[1][0] y = blinkList[1][1] val2 = x * 7 + y x = blinkList[2][0] y = blinkList[2][1] val3 = x * 7 + y self.winningSequence = Sequence() downBlinkerParallel = Parallel( LerpColorInterval(self.locatorList[val0], 0.3, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[val1], 0.3, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[val2], 0.3, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[val3], 0.3, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1))) upBlinkerParallel = Parallel( LerpColorInterval(self.locatorList[val0], 0.3, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5)), LerpColorInterval(self.locatorList[val1], 0.3, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5)), LerpColorInterval(self.locatorList[val2], 0.3, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5)), LerpColorInterval(self.locatorList[val3], 0.3, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5))) self.winningSequence.append(downBlinkerParallel) self.winningSequence.append(upBlinkerParallel) self.winningSequence.loop() def tie(self): self.tieSequence = Sequence(autoFinish=1) self.clockNode.stop() self.clockNode.hide() self.isMyTurn = False self.moveSequence.finish() if self.turnText: self.turnText.hide() for x in range(41): self.tieSequence.append( Parallel( LerpColorInterval(self.locatorList[x], 0.15, Vec4(0.5, 0.5, 0.5, 0.5), Vec4(1, 1, 1, 1)), LerpColorInterval(self.locatorList[x], 0.15, Vec4(1, 1, 1, 1), Vec4(0.5, 0.5, 0.5, 0.5)))) whisper = WhisperPopup('This Find Four game has resulted in a Tie!', OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) whisper.manage(base.marginManager) self.tieSequence.start() def hideChildren(self, nodeList): pass def animatePeice(self, tableState, moveCol, movePos, turn): messenger.send('wakeup') for x in range(6): for y in range(7): self.board[x][y] = tableState[x][y] pos = self.startingPositions[moveCol].getPos() if turn == 0: peice = self.startingPositions[moveCol].getChild( 1).getChildren()[2] peice.show() elif turn == 1: peice = self.startingPositions[moveCol].getChild( 1).getChildren()[3] peice.show() self.moveSequence = Sequence() startPos = self.startingPositions[moveCol].getPos() arrayLoc = movePos * 7 + moveCol self.moveSequence.append( LerpPosInterval(self.startingPositions[moveCol], 1.5, self.locatorList[arrayLoc].getPos(self), startPos)) self.moveSequence.append(Func(peice.hide)) self.moveSequence.append( Func(self.startingPositions[moveCol].setPos, startPos)) self.moveSequence.append(Func(self.updateGameState)) self.moveSequence.start() def announceWin(self, avId): self.fsm.request('gameOver') def doRandomMove(self): if self.isMyTurn: if self.moveCol != None: self.d_requestMove(self.moveCol) self.moveCol = None self.isMyTurn = False taskMgr.remove('playerTurnTask') else: hasfound = False while hasfound == False: from random import * x = randint(0, 6) if self.board[0][x] == 0: self.d_requestMove(x) self.moveCol = None self.isMyTurn = False taskMgr.remove('playerTurnTask') hasfound = True return def doNothing(self): pass def checkHorizontal(self, rVal, cVal, playerNum): if cVal == 3: for x in range(1, 4): if self.board[rVal][cVal - x] != playerNum: break if self.board[rVal][cVal - x] == playerNum and x == 3: return True for x in range(1, 4): if self.board[rVal][cVal + x] != playerNum: break if self.board[rVal][cVal + x] == playerNum and x == 3: return True return False elif cVal == 2: for x in range(1, 4): if self.board[rVal][cVal + x] != playerNum: break if self.board[rVal][cVal + x] == playerNum and x == 3: return True return False elif cVal == 4: for x in range(1, 4): if self.board[rVal][cVal - x] != playerNum: break if self.board[rVal][cVal - x] == playerNum and x == 3: return True return False else: return False def checkVertical(self, rVal, cVal, playerNum): if rVal == 2: for x in range(1, 4): if self.board[rVal + x][cVal] != playerNum: break if self.board[rVal + x][cVal] == playerNum and x == 3: return True return False elif rVal == 3: for x in range(1, 4): if self.board[rVal - x][cVal] != playerNum: break if self.board[rVal - x][cVal] == playerNum and x == 3: return True return False else: return False def checkDiagonal(self, rVal, cVal, playerNum): if cVal <= 2: if rVal == 2: for x in range(1, 4): if self.board[rVal + x][cVal + x] != playerNum: break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return True return False elif rVal == 3: for x in range(1, 4): if self.board[rVal - x][cVal + x] != playerNum: break if self.board[rVal - x][cVal + x] == playerNum and x == 3: return True return False elif cVal >= 4: if rVal == 2: for x in range(1, 4): if self.board[rVal + x][cVal - x] != playerNum: break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return True return False elif rVal == 3: for x in range(1, 4): if self.board[rVal - x][cVal - x] != playerNum: break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return True return False elif rVal == 3 or rVal == 4 or rVal == 5: for x in range(1, 4): if self.board[rVal - x][cVal - x] != playerNum: break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return True for x in range(1, 4): if self.board[rVal - x][cVal - x] != playerNum: break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return True return False elif rVal == 0 or rVal == 1 or rVal == 2: for x in range(1, 4): if self.board[rVal + x][cVal - x] != playerNum: break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return True for x in range(1, 4): if self.board[rVal + x][cVal + x] != playerNum: break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return True return False return False def findHorizontal(self, rVal, cVal, playerNum): if cVal == 3: retList = [] for x in range(1, 4): retList.append([rVal, cVal - x]) if self.board[rVal][cVal - x] != playerNum: retList = [] break if self.board[rVal][cVal - x] == playerNum and x == 3: return retList for x in range(1, 4): retList.append([rVal, cVal + x]) if self.board[rVal][cVal + x] != playerNum: retList = [] break if self.board[rVal][cVal + x] == playerNum and x == 3: return retList return [] elif cVal == 2: retList = [] for x in range(1, 4): retList.append([rVal, cVal + x]) if self.board[rVal][cVal + x] != playerNum: retList = [] break if self.board[rVal][cVal + x] == playerNum and x == 3: return retList return [] elif cVal == 4: retList = [] for x in range(1, 4): retList.append([rVal, cVal - x]) if self.board[rVal][cVal - x] != playerNum: retList = [] break if self.board[rVal][cVal - x] == playerNum and x == 3: return retList return [] else: return [] def findVertical(self, rVal, cVal, playerNum): if rVal == 2: retList = [] for x in range(1, 4): retList.append([rVal + x, cVal]) if self.board[rVal + x][cVal] != playerNum: retList = [] break if self.board[rVal + x][cVal] == playerNum and x == 3: return retList return [] elif rVal == 3: retList = [] for x in range(1, 4): retList.append([rVal - x, cVal]) if self.board[rVal - x][cVal] != playerNum: retList = [] break if self.board[rVal - x][cVal] == playerNum and x == 3: return retList return [] else: return [] def findDiagonal(self, rVal, cVal, playerNum): retList = [] if cVal <= 2: if rVal == 2: for x in range(1, 4): retList.append([rVal + x, cVal + x]) if self.board[rVal + x][cVal + x] != playerNum: retList = [] break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return retList return [] elif rVal == 3: for x in range(1, 4): retList.append([rVal - x, cVal + x]) if self.board[rVal - x][cVal + x] != playerNum: retList = [] break if self.board[rVal - x][cVal + x] == playerNum and x == 3: return retList return [] elif cVal >= 4: if rVal == 2: for x in range(1, 4): retList.append([rVal + x, cVal - x]) if self.board[rVal + x][cVal - x] != playerNum: retList = [] break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return retList return [] elif rVal == 3: for x in range(1, 4): retList.append([rVal - x, cVal - x]) if self.board[rVal - x][cVal - x] != playerNum: retList = [] break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return retList return [] elif rVal == 3 or rVal == 4 or rVal == 5: for x in range(1, 4): retList.append([rVal - x, cVal - x]) if self.board[rVal - x][cVal - x] != playerNum: retList = [] break if self.board[rVal - x][cVal - x] == playerNum and x == 3: return retList for x in range(1, 4): retList.append([rVal + x, cVal - x]) if self.board[rVal + x][cVal - x] != playerNum: retList = [] break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return retList return [] elif rVal == 0 or rVal == 1 or rVal == 2: for x in range(1, 4): retList.append([rVal + x, cVal - x]) if self.board[rVal + x][cVal - x] != playerNum: retList = [] break if self.board[rVal + x][cVal - x] == playerNum and x == 3: return retList for x in range(1, 4): retList.append([rVal + x, cVal + x]) if self.board[rVal + x][cVal + x] != playerNum: retList = [] break if self.board[rVal + x][cVal + x] == playerNum and x == 3: return retList return [] return []
class DistributedPicnicBasket(DistributedObject.DistributedObject): seatState = Enum("Empty, Full, Eating") notify = DirectNotifyGlobal.directNotify.newCategory( "DistributedPicnicBasket") def __init__(self, cr): """__init__(cr) """ DistributedObject.DistributedObject.__init__(self, cr) self.localToonOnBoard = 0 self.seed = 0 self.random = None self.picnicCountdownTime = \ ConfigVariableDouble("picnic-countdown-time", ToontownGlobals.PICNIC_COUNTDOWN_TIME).getValue() self.picnicBasketTrack = None # only one track contains the picnic basket shrink/grow self.fsm = ClassicFSM.ClassicFSM( 'DistributedTrolley', [ State.State('off', self.enterOff, self.exitOff, ['waitEmpty', 'waitCountdown']), State.State('waitEmpty', self.enterWaitEmpty, self.exitWaitEmpty, ['waitCountdown']), State.State('waitCountdown', self.enterWaitCountdown, self.exitWaitCountdown, ['waitEmpty']) ], # Initial State 'off', # Final State 'off', ) self.fsm.enterInitialState() # Tracks on toons, for starting and stopping # stored by avId : track. There is only a need for one at a time, # in fact the point of the dict is to ensure only one is playing at a time self.__toonTracks = {} def generate(self): """generate(self) This method is called when the DistributedObject is reintroduced to the world, either for the first time or from the cache. """ DistributedObject.DistributedObject.generate(self) # Get the state machine stuff for playGame self.loader = self.cr.playGame.hood.loader self.foodLoader = [ 'phase_6/models/golf/picnic_sandwich.bam', 'phase_6/models/golf/picnic_apple.bam', 'phase_6/models/golf/picnic_cupcake.bam', 'phase_6/models/golf/picnic_chocolate_cake.bam' ] self.fullSeat = [] self.food = [] for i in range(4): self.food.append(None) self.fullSeat.append(self.seatState.Empty) self.picnicItem = 0 def announceGenerate(self): """Setup other fields dependent on the required fields.""" self.picnicTable = self.loader.geom.find("**/*picnic_table_" + str(self.tableNumber)) self.picnicTableSphereNodes = [] self.numSeats = 4 self.seats = [] self.jumpOffsets = [] self.basket = None for i in range(self.numSeats): self.seats.append(self.picnicTable.find("**/*seat%d" % (i + 1))) self.jumpOffsets.append( self.picnicTable.find("**/*jumpOut%d" % (i + 1))) #debugAxis = loader.loadModel('models/misc/xyzAxis') #debugAxis.setColorScale(1.0, 1.0, 1.0, 0.25) #debugAxis.setTransparency(True) #debugAxis.reparentTo(self.seats[i]) self.tablecloth = self.picnicTable.find("**/basket_locator") DistributedObject.DistributedObject.announceGenerate(self) for i in range(self.numSeats): self.picnicTableSphereNodes.append(self.seats[i].attachNewNode( CollisionNode('picnicTable_sphere_%d_%d' % (self.getDoId(), i)))) self.picnicTableSphereNodes[i].node().addSolid( CollisionSphere(0, 0, 0, 2)) self.tableclothSphereNode = self.tablecloth.attachNewNode( CollisionNode('tablecloth_sphere')) self.tableclothSphereNode.node().addSolid(CollisionSphere(0, 0, -1, 4)) angle = self.startingHpr[0] angle -= 90 radAngle = deg2Rad(angle) unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0) unitVec *= 30.0 self.endPos = self.startingPos + unitVec dist = Vec3(self.endPos - self.enteringPos).length() wheelAngle = dist / (0.5 * 1.4 * math.pi) * 360 self.seatNumber = 0 self.clockNode = ToontownTimer() self.clockNode.reparentTo(base.a2dBottomRight) self.clockNode.setPos(-0.173, 0, 0.17) self.clockNode.setScale(0.3) self.clockNode.hide() def disable(self): DistributedObject.DistributedObject.disable(self) # Go to the off state when the object is put in the cache self.fsm.request("off") # No more toon animating self.clearToonTracks() for i in range(self.numSeats): del self.picnicTableSphereNodes[0] del self.picnicTableSphereNodes self.notify.debug("Deleted self loader " + str(self.getDoId())) self.picnicTable.removeNode() self.picnicBasketTrack = None #self.kart.removeNode() #del self.kart #import pdb; #pdb.set_trace() def delete(self): self.notify.debug("Golf kart getting deleted: %s" % self.getDoId()) DistributedObject.DistributedObject.delete(self) del self.fsm def setState(self, state, seed, timestamp): self.seed = seed if not self.random: self.random = RandomNumGen.RandomNumGen(seed) self.fsm.request(state, [globalClockDelta.localElapsedTime(timestamp)]) def handleEnterPicnicTableSphere(self, i, collEntry): # collEntry): assert self.notify.debugStateCall(self) self.seatNumber = i self.notify.debug("Entering Picnic Table Sphere.... %s" % self.getDoId()) # Put localToon into requestBoard mode. #import pdb; pdb.set_trace() self.loader.place.detectedPicnicTableSphereCollision(self) def handleEnterPicnicTable(self, i): # Tell the server that this avatar wants to board. assert self.notify.debugStateCall(self) toon = base.localAvatar self.sendUpdate("requestBoard", [i]) def fillSlot0(self, avId): self.fillSlot(0, avId) def fillSlot1(self, avId): self.fillSlot(1, avId) def fillSlot2(self, avId): self.fillSlot(2, avId) def fillSlot3(self, avId): self.fillSlot(3, avId) def fillSlot(self, index, avId): assert self.notify.debugStateCall(self) self.notify.debug("fill Slot: %d for %d" % (index, avId)) if avId == 0: # This means that the slot is now empty, and no action should # be taken. pass else: self.fullSeat[index] = self.seatState.Full # If localToon is boarding, he needs to change state if avId == base.localAvatar.getDoId(): # Start the countdown clock... self.clockNode.show() if index == 0 or index == 3: side = -1 else: side = 1 if hasattr(self.loader.place, "trolley"): self.loader.place.trolley.fsm.request( "boarding", [self.tablecloth, side]) else: self.notify.warning('fillSlot no trolley in place') self.localToonOnBoard = 1 # Put that toon on the table # If it's localToon, tell him he's on the trolley now if avId == base.localAvatar.getDoId(): if hasattr(self.loader.place, "trolley"): self.loader.place.trolley.fsm.request("boarded") # hide the exit button until basket interval is over self.loader.place.trolley.exitButton.hide() if avId in self.cr.doId2do: # If the toon exists, look it up toon = self.cr.doId2do[avId] # Parent it to the trolley toon.stopSmooth() toon.wrtReparentTo(self.tablecloth) sitStartDuration = toon.getDuration("sit-start") jumpTrack = self.generateToonJumpTrack(toon, index) track = Sequence(jumpTrack, Func(toon.setAnimState, "Sit", 1.0)) # only add basket appear if there is no toons are already sitting self.notify.debug("### fillSlot: fullSeat = %s" % self.fullSeat) if self.fullSeat.count(0) == 3: self.notify.debug("### fillSlot: adding basketAppear") #track.append(self.generateBasketAppearTrack()) if self.picnicBasketTrack: self.picnicBasketTrack.finish() waitDuration = track.getDuration() self.picnicBasketTrack = Sequence( Wait(waitDuration), self.generateBasketAppearTrack()) self.picnicBasketTrack.start() # make a random food appear track.append(self.generateFoodAppearTrack(index)) # finish the rest of the staging track.append( Sequence(Func(self.clearToonTrack, avId), name=toon.uniqueName("fillTrolley"), autoPause=1)) if avId == base.localAvatar.getDoId(): if hasattr(self.loader.place, "trolley"): track.append( Func(self.loader.place.trolley.exitButton.show)) track.delayDelete = DelayDelete.DelayDelete( toon, 'PicnicBasket.fillSlot') self.storeToonTrack(avId, track) track.start() def emptySlot0(self, avId, timestamp): self.emptySlot(0, avId, timestamp) def emptySlot1(self, avId, timestamp): self.emptySlot(1, avId, timestamp) def emptySlot2(self, avId, timestamp): self.emptySlot(2, avId, timestamp) def emptySlot3(self, avId, timestamp): self.emptySlot(3, avId, timestamp) def notifyToonOffTrolley(self, toon): toon.setAnimState("neutral", 1.0) if hasattr(base, 'localAvatar') and toon == base.localAvatar: if hasattr(self.loader.place, "trolley"): self.loader.place.trolley.handleOffTrolley() self.localToonOnBoard = 0 else: toon.startSmooth() return def emptySlot(self, index, avId, timestamp): def emptySeat(index): # If localToon is exiting, he needs to change state self.notify.debug("### seat %s now empty" % index) self.fullSeat[index] = self.seatState.Empty if avId == 0: # This means that the slot is now empty, and no action should # be taken. pass elif avId == 1: # Special cardinal value for unexpected exit. # The toon is gone, but we may still need to clean up his food self.fullSeat[index] = self.seatState.Empty track = Sequence(self.generateFoodDisappearTrack(index)) # if no toons left, make the basket go away self.notify.debug("### empty slot - unexpetected: fullSeat = %s" % self.fullSeat) if self.fullSeat.count(0) == 4: self.notify.debug("### empty slot - unexpected: losing basket") if self.picnicBasketTrack: self.picnicBasketTrack.finish() #track.append(self.generateBasketDisappearTrack()) waitDuration = track.getDuration() self.picnicBasketTrack = Sequence( Wait(waitDuration), self.generateBasketDisappearTrack()) self.picnicBasketTrack.start() track.start() else: self.fullSeat[index] = self.seatState.Empty if avId in self.cr.doId2do: if avId == base.localAvatar.getDoId(): # Stop the countdown clock.. if (self.clockNode): self.clockNode.hide() # If the toon exists, look it up toon = self.cr.doId2do[avId] toon.stopSmooth() sitStartDuration = toon.getDuration("sit-start") jumpOutTrack = self.generateToonReverseJumpTrack(toon, index) track = Sequence(jumpOutTrack) # make the food go away track.append(self.generateFoodDisappearTrack(index)) # if no toons left, make the basket go away self.notify.debug("### empty slot: fullSeat = %s" % self.fullSeat) if self.fullSeat.count(0) == 4: self.notify.debug("### empty slot: losing basket") if self.picnicBasketTrack: self.picnicBasketTrack.finish() #track.append(self.generateBasketDisappearTrack()) waitDuration = track.getDuration() self.picnicBasketTrack = Sequence( Wait(waitDuration), self.generateBasketDisappearTrack()) self.picnicBasketTrack.start() # let the toon loose track.append( Sequence( # Tell the toon he is free to roam now Func(self.notifyToonOffTrolley, toon), Func(self.clearToonTrack, avId), Func(self.doneExit, avId), Func(emptySeat, index), name=toon.uniqueName("emptyTrolley"), autoPause=1)) track.delayDelete = DelayDelete.DelayDelete( toon, 'PicnicBasket.emptySlot') self.storeToonTrack(avId, track) track.start() def rejectBoard(self, avId): # This should only be sent to us if our localToon requested # permission to board the trolley. assert (base.localAvatar.getDoId() == avId) self.loader.place.trolley.handleRejectBoard() def __enableCollisions(self): # start listening for toons to enter. assert self.notify.debugStateCall(self) for i in range(self.numSeats): self.accept('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTableSphere, [i]) self.accept('enterPicnicTableOK_%d_%d' % (self.getDoId(), i), self.handleEnterPicnicTable, [i]) self.picnicTableSphereNodes[i].setCollideMask( ToontownGlobals.WallBitmask) def __disableCollisions(self): assert self.notify.debugStateCall(self) for i in range(self.numSeats): self.ignore('enterpicnicTable_sphere_%d_%d' % (self.getDoId(), i)) self.ignore('enterPicnicTableOK_%d_%d' % (self.getDoId(), i)) for i in range(self.numSeats): self.picnicTableSphereNodes[i].setCollideMask(BitMask32(0)) ##### Off state ##### def enterOff(self): return None def exitOff(self): return None ##### WaitEmpty state ##### def enterWaitEmpty(self, ts): # Toons may now try to board the trolley self.__enableCollisions() def exitWaitEmpty(self): # Toons may not attempt to board the trolley if it isn't waiting self.__disableCollisions() ##### WaitCountdown state ##### def enterWaitCountdown(self, ts): # Toons may now try to board the trolley self.__enableCollisions() self.accept("trolleyExitButton", self.handleExitButton) #self.clockNode.countdown(self.picnicCountdownTime - ts, self.handleExitButton) self.clockNode.countdown(self.picnicCountdownTime, self.handleExitButton) def handleExitButton(self): # This gets called when the exit button gets pushed. self.sendUpdate("requestExit") self.clockNode.hide() #import pdb; pdb.set_trace() def exitWaitCountdown(self): # Toons may not attempt to board the trolley if it isn't waiting self.__disableCollisions() self.ignore("trolleyExitButton") self.clockNode.reset() def getStareAtNodeAndOffset(self): return self.tablecloth, Point3(0, 0, 4) def storeToonTrack(self, avId, track): # Clear out any currently playing tracks on this toon self.clearToonTrack(avId) # Store this new one self.__toonTracks[avId] = track def clearToonTrack(self, avId): # Clear out any currently playing tracks on this toon oldTrack = self.__toonTracks.get(avId) if oldTrack: oldTrack.pause() DelayDelete.cleanupDelayDeletes(oldTrack) del self.__toonTracks[avId] def clearToonTracks(self): #We can't use an iter because we are deleting keys keyList = [] for key in self.__toonTracks: keyList.append(key) for key in keyList: if key in self.__toonTracks: self.clearToonTrack(key) def doneExit(self, avId): if (avId == base.localAvatar.getDoId()): self.sendUpdate("doneExit") def setPosHpr(self, x, y, z, h, p, r): """Set the pos hpr as dictated by the AI.""" self.startingPos = Vec3(x, y, z) self.enteringPos = Vec3(x, y, z - 10) self.startingHpr = Vec3(h, 0, 0) #self.golfKart.setPosHpr( x, y, z, h, 0, 0 ) def setTableNumber(self, tn): self.tableNumber = tn def generateToonJumpTrack(self, av, seatIndex): """Return an interval of the toon jumping into the golf kart.""" # Maintain a reference to Parent and Scale of avatar in case they # exit from the kart. #base.sb = self av.pose('sit', 47) hipOffset = av.getHipsParts()[2].getPos(av) def getToonJumpTrack(av, seatIndex): # using a local func allows the ProjectileInterval to # calculate this pos at run-time def getJumpDest(av=av, node=self.tablecloth): dest = Vec3(self.tablecloth.getPos(av.getParent())) seatNode = self.picnicTable.find("**/seat" + str(seatIndex + 1)) dest += seatNode.getPos(self.tablecloth) dna = av.getStyle() dest -= hipOffset if (seatIndex == 2 or seatIndex == 3): dest.setY(dest.getY() + 2 * hipOffset.getY()) dest.setZ(dest.getZ() + 0.2) return dest def getJumpHpr(av=av, node=self.tablecloth): hpr = self.seats[seatIndex].getHpr(av.getParent()) #if(seatIndex < 2): #hpr.setX( hpr.getX() + 180) #else: # hpr.setX( hpr.getX() ) angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX()) hpr.setX(angle) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.43), Parallel( LerpHprInterval(av, hpr=getJumpHpr, duration=.9), ProjectileInterval(av, endPos=getJumpDest, duration=.9)), )) return toonJumpTrack def getToonSitTrack(av): toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit')) return toonSitTrack toonJumpTrack = getToonJumpTrack(av, seatIndex) toonSitTrack = getToonSitTrack(av) jumpTrack = Sequence( Parallel( toonJumpTrack, Sequence( Wait(1), toonSitTrack, ), ), Func(av.wrtReparentTo, self.tablecloth), ) return jumpTrack def generateToonReverseJumpTrack(self, av, seatIndex): """Return an interval of the toon jumping out of the golf kart.""" self.notify.debug("av.getH() = %s" % av.getH()) def getToonJumpTrack(av, destNode): # using a local func allows the ProjectileInterval to # calculate this pos at run-time def getJumpDest(av=av, node=destNode): dest = node.getPos(self.tablecloth) dest += self.jumpOffsets[seatIndex].getPos(self.tablecloth) return dest def getJumpHpr(av=av, node=destNode): hpr = node.getHpr(av.getParent()) hpr.setX(hpr.getX() + 180) angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX()) hpr.setX(angle) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.1), #43 ), Parallel( #LerpHprInterval( av, # hpr = getJumpHpr, # duration = .9 ), ProjectileInterval(av, endPos=getJumpDest, duration=.9)))) return toonJumpTrack toonJumpTrack = getToonJumpTrack(av, self.tablecloth) #self.seats[seatIndex]) jumpTrack = Sequence( toonJumpTrack, Func(av.loop, 'neutral'), Func(av.wrtReparentTo, render), #Func( self.av.setPosHpr, self.exitMovieNode, 0,0,0,0,0,0 ), ) return jumpTrack def generateBasketAppearTrack(self): """ """ if (self.basket == None): self.basket = loader.loadModel( 'phase_6/models/golf/picnic_basket.bam') self.basket.setScale(0.1) basketTrack = Sequence( Func(self.basket.show), SoundInterval( globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node=self.basket), Func(self.basket.reparentTo, self.tablecloth), Func(self.basket.setPos, 0, 0, .2), Func(self.basket.setHpr, 45, 0, 0), Func(self.basket.wrtReparentTo, render), Func(self.basket.setShear, 0, 0, 0), #Func( self.basket.setActiveShadow, True ), # Must be a cleaner way to do this. Sequence( LerpScaleInterval(self.basket, scale=Point3(1.1, 1.1, .1), duration=0.2), LerpScaleInterval(self.basket, scale=Point3(1.6, 1.6, 0.2), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(1., 1., 0.4), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(1.5, 1.5, 2.5), duration=0.2), LerpScaleInterval(self.basket, scale=Point3(2.5, 2.5, 1.5), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(2., 2., 2.), duration=0.1), Func(self.basket.wrtReparentTo, self.tablecloth), Func(self.basket.setPos, 0, 0, 0)), ) return basketTrack def generateBasketDisappearTrack(self): if not self.basket: return Sequence() pos = self.basket.getPos() pos.addZ(-1) basketTrack = Sequence( LerpScaleInterval(self.basket, scale=Point3(2., 2., 1.8), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(1., 1., 2.5), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(2., 2., 0.5), duration=0.2), LerpScaleInterval(self.basket, scale=Point3(0.5, 0.5, 1.0), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(1.1, 1.1, .1), duration=0.1), LerpScaleInterval(self.basket, scale=Point3(.1, .1, .1), duration=0.2), SoundInterval( globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node=self.basket), Wait(0.2), LerpPosInterval(self.basket, pos=pos, duration=0.2), Func(self.basket.hide), ) return basketTrack def generateFoodAppearTrack(self, seat): """ """ if (self.fullSeat[seat] == self.seatState.Full): self.notify.debug("### food appear: self.fullSeat = %s" % self.fullSeat) if not self.food[seat]: self.food[seat] = loader.loadModel( self.random.choice(self.foodLoader)) self.notify.debug("### food appear: self.food = %s" % self.food) self.food[seat].setScale(0.1) self.food[seat].reparentTo(self.tablecloth) self.food[seat].setPos( self.seats[seat].getPos(self.tablecloth)[0] / 2, self.seats[seat].getPos(self.tablecloth)[1] / 2, 0) # Func( self.food[seat].setActiveShadow, False ), foodTrack = Sequence( Func(self.food[seat].show), SoundInterval( globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node=self.food[seat]), Func(self.food[seat].reparentTo, self.tablecloth), Func(self.food[seat].setHpr, 45, 0, 0), Func(self.food[seat].wrtReparentTo, render), Func(self.food[seat].setShear, 0, 0, 0), #Func( self.food[seat].setActiveShadow, True ), # Must be a cleaner way to do this. Sequence( LerpScaleInterval(self.food[seat], scale=Point3(1.1, 1.1, .1), duration=0.2), LerpScaleInterval(self.food[seat], scale=Point3(1.6, 1.6, 0.2), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(1., 1., 0.4), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(1.5, 1.5, 2.5), duration=0.2), LerpScaleInterval(self.food[seat], scale=Point3(2.5, 2.5, 1.5), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(2., 2., 2.), duration=0.1), Func(self.food[seat].wrtReparentTo, self.tablecloth)), ) return foodTrack else: return Sequence() def generateFoodDisappearTrack(self, seat): if not self.food[seat]: return Sequence() pos = self.food[seat].getPos() pos.addZ(-1.) foodTrack = Sequence( LerpScaleInterval(self.food[seat], scale=Point3(2., 2., 1.8), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(1., 1., 2.5), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(2., 2., 0.5), duration=0.2), LerpScaleInterval(self.food[seat], scale=Point3(0.5, 0.5, 1.0), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(1.1, 1.1, .1), duration=0.1), LerpScaleInterval(self.food[seat], scale=Point3(.1, .1, .1), duration=0.2), SoundInterval( globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node=self.food[seat]), Wait(0.2), LerpPosInterval(self.food[seat], pos=pos, duration=0.2), Func(self.food[seat].hide), ) return foodTrack def destroy(self, node): node.removeNode() node = None self.basket.removeNode() self.basket = None for food in self.food: food.removeNode() self.food = None self.clockNode.removeNode() del self.clockNode self.clockNode = None def setPicnicDone(self): if self.localToonOnBoard: if hasattr(self.loader.place, "trolley"): self.loader.place.trolley.fsm.request("final") self.loader.place.trolley.fsm.request("start") self.localToonOnBoard = 0 messenger.send("picnicDone")