from otp.level.BasicEntities import DistributedNodePathEntity from panda3d.core import * from direct.interval.IntervalGlobal import * from toontown.toonbase.ToontownGlobals import * import random from direct.directnotify import DirectNotifyGlobal from direct.distributed.ClockDelta import globalClockDelta from . import DistributedBarrelBase from otp.level.BasicEntities import DistributedNodePathEntity from toontown.toonbase import ToontownGlobals from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownTimer from direct.task import Task from direct.gui.DirectGui import DGG, DirectFrame, DirectLabel class DistributedMaze(DistributedNodePathEntity): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedMaze') ScheduleTaskName = 'mazeScheduler' RemoveBlocksDict = {2: ('HedgeBlock_0_1',), 4: (('HedgeBlock_0_1', 'HedgeBlock_1_3', 'HedgeBlock_2_3'), ('HedgeBlock_0_2', 'HedgeBlock_2_3', 'HedgeBlock_1_3'), ('HedgeBlock_0_1', 'HedgeBlock_0_2', 'HedgeBlock_1_3', 'HedgeBlock_2_3'))} def __init__(self, cr): DistributedNodePathEntity.__init__(self, cr) self.numSections = 0 self.GameDuration = 35.0 + self.numSections * 15.0 self.timer = None self.frame2D = None self.gameLabel = None self.gameStarted = 0 self.finished = 0 self.timedOut = 0 self.toonFinishedText = TTLocalizer.toonFinishedHedgeMaze self.toonEnteredText = TTLocalizer.enterHedgeMaze return def announceGenerate(self): DistributedNodePathEntity.announceGenerate(self) self.addHints(self.roomHold) self.loadGui() def disable(self): DistributedNodePathEntity.disable(self) self.unloadGui() self.cleanupTimer() self.ignoreAll() def delete(self): self.cleanupTimer() DistributedNodePathEntity.delete(self) def setRoomDoId(self, roomDoId): self.roomDoId = roomDoId room = self.cr.doId2do.get(roomDoId) if room: self.gotRoom([room]) else: self.roomRequest = self.cr.relatedObjectMgr.requestObjects([roomDoId], allCallback=self.gotRoom, timeout=5) def gotRoom(self, rooms): self.roomRequest = None room = rooms[0] self.roomHold = room rotations = [0, 0, 90, 90, 180, 180, 270, 270] self.getRng().shuffle(rotations) self.numSections = 0 for i in range(0, 4): maze = room.getGeom().find('**/Maze_Inside_%d' % i) if not maze.isEmpty(): self.numSections += 1 if rotations: maze.setH(rotations.pop()) self.GameDuration = 35.0 + self.numSections * 15.0 self.removeHedgeBlocks(room) return def addHints(self, room): self.focusPoint = self.attachNewNode('GolfGreenGameFrame') hintList = room.getGeom().findAllMatches('**/dead*') for hint in hintList: self.actSphere = CollisionSphere(0, 0, 0, 7.0) self.actSphereNode = CollisionNode('mazegame_hint-%s-%s' % (self.level.getLevelId(), self.entId)) self.actSphereNode.addSolid(self.actSphere) self.actSphereNodePath = hint.attachNewNode(self.actSphereNode) self.actSphereNode.setCollideMask(WallBitmask) self.actSphere.setTangible(0) self.enterEvent = 'enter' + self.actSphereNode.getName() self.accept(self.enterEvent, self.__handleToonEnterHint) self.exitEvent = 'exit' + self.actSphereNode.getName() self.accept(self.exitEvent, self.__handleToonExitHint) enterance = room.getGeom().find('**/ENTRANCE') self.enterSphere = CollisionSphere(0, 0, 0, 8.0) self.enterSphereNode = CollisionNode('mazegame_enter-%s-%s' % (self.level.getLevelId(), self.entId)) self.enterSphereNode.addSolid(self.enterSphere) self.enterSphereNodePath = enterance.attachNewNode(self.enterSphereNode) self.enterSphereNode.setCollideMask(WallBitmask) self.enterSphere.setTangible(0) self.enteranceEvent = 'enter' + self.enterSphereNode.getName() self.accept(self.enteranceEvent, self.__handleToonEnterance) finish = room.getGeom().find('**/finish') self.finishSphere = CollisionSphere(0, 0, 0, 15.0) self.finishSphereNode = CollisionNode('mazegame_finish-%s-%s' % (self.level.getLevelId(), self.entId)) self.finishSphereNode.addSolid(self.finishSphere) self.finishSphereNodePath = finish.attachNewNode(self.finishSphereNode) self.finishSphereNode.setCollideMask(WallBitmask) self.finishSphere.setTangible(0) self.finishEvent = 'enter' + self.finishSphereNode.getName() self.accept(self.finishEvent, self.__handleToonFinish) def __handleToonEnterance(self, collEntry): if not self.gameStarted: self.notify.debug('sending clientTriggered for %d' % self.doId) self.sendUpdate('setClientTriggered', []) self.level.countryClub.showInfoText(self.toonEnteredText) def __handleToonFinish(self, collEntry): self.sendUpdate('setFinishedMaze', []) self.finished = 1 def __handleToonEnterHint(self, collEntry): camHeight = base.localAvatar.getClampedAvatarHeight() heightScaleFactor = camHeight * 0.3333333333 defLookAt = Point3(0.0, 1.5, camHeight) cameraPoint = Point3(0.0, -22.0 * heightScaleFactor, camHeight + 54.0) base.localAvatar.stopUpdateSmartCamera() base.localAvatar.startUpdateSmartCamera(push=0) base.localAvatar.setIdealCameraPos(cameraPoint) def __handleToonExitHint(self, collEntry): base.localAvatar.stopUpdateSmartCamera() base.localAvatar.startUpdateSmartCamera() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) self.cameraHold = None return def getRng(self): return random.Random(self.entId * self.doId) def removeHedgeBlocks(self, room): if self.numSections in self.RemoveBlocksDict: blocksToRemove = self.getRng().choice(self.RemoveBlocksDict[self.numSections]) for blockName in blocksToRemove: block = room.getGeom().find('**/%s' % blockName) if not block.isEmpty(): block.removeNode() def setGameStart(self, timestamp): self.notify.debug('%d setGameStart: Starting game' % self.doId) self.gameStartTime = globalClockDelta.networkToLocalTime(timestamp) self.gameStarted = True curGameTime = self.getCurrentGameTime() timeLeft = self.GameDuration - curGameTime self.cleanupTimer() self.timer = ToontownTimer.ToontownTimer() self.timer.posBelowTopRightCorner() self.timer.setTime(timeLeft) self.timer.countdown(timeLeft, self.timerExpired) self.startScheduleTask() self.frame2D.show() def setGameOver(self): self.timedOut = 1 if not self.finished: self.sendUpdate('damageMe', []) roomNum = self.level.roomNum club = self.level.countryClub self.gameOverTrack = Sequence() self.gameOverTrack.append(localAvatar.getTeleportOutTrack()) self.gameOverTrack.append(Func(localAvatar.setPos, self.finishSphereNodePath.getPos(render))) self.gameOverTrack.append(Func(localAvatar.play, 'jump')) self.gameOverTrack.append(Func(self.level.countryClub.camEnterRoom, roomNum)) self.gameOverTrack.start() self.timerExpired() def local2GameTime(self, timestamp): return timestamp - self.gameStartTime def game2LocalTime(self, timestamp): return timestamp + self.gameStartTime def getCurrentGameTime(self): return self.local2GameTime(globalClock.getFrameTime()) def startScheduleTask(self): taskMgr.add(self.scheduleTask, self.ScheduleTaskName) def stopScheduleTask(self): taskMgr.remove(self.ScheduleTaskName) def scheduleTask(self, task): curTime = self.getCurrentGameTime() def cleanupTimer(self): if self.timer: self.timer.stop() self.timer.destroy() self.timer = None return def timerExpired(self): self.cleanupTimer() self.unloadGui() def loadGui(self): self.frame2D = DirectFrame(scale=1.0, pos=(0.0, 0, 0.9), relief=DGG.FLAT, parent=aspect2d, frameSize=(-0.3, 0.3, -0.05, 0.05), frameColor=(0.737, 0.573, 0.345, 0.3)) self.frame2D.hide() self.gameLabel = DirectLabel(parent=self.frame2D, relief=None, pos=(0, 0, 0), scale=1.0, text=TTLocalizer.mazeLabel, text_font=ToontownGlobals.getSignFont(), text0_fg=(1, 1, 1, 1), text_scale=0.075, text_pos=(0, -0.02)) return def unloadGui(self): if self.frame2D: self.frame2D.destroy() self.frame2D = None if self.gameLabel: self.gameLabel.destroy() self.gameLabel = None return def toonFinished(self, avId, place, lastToon): toon = base.cr.doId2do.get(avId) if toon and not self.timedOut: self.level.countryClub.showInfoText(self.toonFinishedText % (toon.getName(), TTLocalizer.hedgeMazePlaces[place])) if lastToon: self.setGameOver()