235 lines
9.3 KiB
Python
235 lines
9.3 KiB
Python
from otp.level.BasicEntities import DistributedNodePathEntity
|
|
from pandac.PandaModules 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()
|