2022-12-16 18:40:57 -06:00
|
|
|
from panda3d.core import Point3, CollisionSphere, CollisionNode
|
2019-11-02 17:27:54 -05:00
|
|
|
from direct.showbase.DirectObject import DirectObject
|
|
|
|
from direct.showbase.PythonUtil import Functor
|
|
|
|
from direct.showbase.RandomNumGen import RandomNumGen
|
|
|
|
from direct.task.Task import Task
|
|
|
|
from toontown.minigame.MazeSuit import MazeSuit
|
2019-12-30 00:07:56 -06:00
|
|
|
from .CogdoGameGatherable import CogdoMemo
|
|
|
|
from .CogdoMazePlayer import CogdoMazePlayer
|
|
|
|
from .CogdoMazeLocalPlayer import CogdoMazeLocalPlayer
|
|
|
|
from .CogdoMazeGuiManager import CogdoMazeGuiManager
|
|
|
|
from .CogdoGameAudioManager import CogdoGameAudioManager
|
|
|
|
from .CogdoMazeGameObjects import CogdoMazeExit, CogdoMazeDrop
|
|
|
|
from .CogdoMazeSuits import CogdoMazeSuit, CogdoMazeSlowMinionSuit, CogdoMazeFastMinionSuit, CogdoMazeBossSuit
|
|
|
|
from .CogdoMazeGameMovies import CogdoMazeGameIntro, CogdoMazeGameFinish
|
|
|
|
from . import CogdoMazeGameGlobals as Globals
|
|
|
|
from . import CogdoUtil
|
2019-11-02 17:27:54 -05:00
|
|
|
import math
|
|
|
|
import random
|
|
|
|
|
|
|
|
class CogdoMazeGame(DirectObject):
|
|
|
|
notify = directNotify.newCategory('CogdoMazeGame')
|
|
|
|
UpdateTaskName = 'CogdoMazeGameUpdateTask'
|
|
|
|
RemoveGagTaskName = 'CogdoMazeGameRemoveGag'
|
|
|
|
PlayerCoolerCollision = '%s-into-%s' % (Globals.LocalPlayerCollisionName, Globals.WaterCoolerCollisionName)
|
|
|
|
PlayerDropCollision = '%s-into-%s' % (Globals.LocalPlayerCollisionName, Globals.DropCollisionName)
|
|
|
|
|
|
|
|
def __init__(self, distGame):
|
|
|
|
self.distGame = distGame
|
|
|
|
self._allowSuitsHitToons = base.config.GetBool('cogdomaze-suits-hit-toons', True)
|
|
|
|
|
|
|
|
def load(self, cogdoMazeFactory, numSuits, bossCode):
|
|
|
|
self._initAudio()
|
|
|
|
self.maze = cogdoMazeFactory.createCogdoMaze()
|
|
|
|
suitSpawnSpot = self.maze.createRandomSpotsList(numSuits, self.distGame.randomNumGen)
|
|
|
|
self.guiMgr = CogdoMazeGuiManager(self.maze, bossCode)
|
|
|
|
self.suits = []
|
|
|
|
self.suitsById = {}
|
|
|
|
self.shakers = []
|
|
|
|
self.toonsThatRevealedDoor = []
|
|
|
|
self.quake = 0
|
|
|
|
self.dropCounter = 0
|
|
|
|
self.drops = {}
|
|
|
|
self.gagCounter = 0
|
|
|
|
self.gags = []
|
|
|
|
self.hackTemp = False
|
|
|
|
self.dropGen = RandomNumGen(self.distGame.doId)
|
|
|
|
self.gagTimeoutTasks = []
|
|
|
|
self.finished = False
|
|
|
|
self.lastBalloonTimestamp = None
|
|
|
|
difficulty = self.distGame.getDifficulty()
|
|
|
|
serialNum = 0
|
|
|
|
for i in range(numSuits[0]):
|
|
|
|
suitRng = RandomNumGen(self.distGame.doId + serialNum * 10)
|
|
|
|
suit = CogdoMazeBossSuit(serialNum, self.maze, suitRng, difficulty, startTile=suitSpawnSpot[0][i])
|
|
|
|
self.addSuit(suit)
|
|
|
|
self.guiMgr.mazeMapGui.addSuit(suit.suit)
|
|
|
|
serialNum += 1
|
|
|
|
|
|
|
|
for i in range(numSuits[1]):
|
|
|
|
suitRng = RandomNumGen(self.distGame.doId + serialNum * 10)
|
|
|
|
suit = CogdoMazeFastMinionSuit(serialNum, self.maze, suitRng, difficulty, startTile=suitSpawnSpot[1][i])
|
|
|
|
self.addSuit(suit)
|
|
|
|
serialNum += 1
|
|
|
|
|
|
|
|
for i in range(numSuits[2]):
|
|
|
|
suitRng = RandomNumGen(self.distGame.doId + serialNum * 10)
|
|
|
|
suit = CogdoMazeSlowMinionSuit(serialNum, self.maze, suitRng, difficulty, startTile=suitSpawnSpot[2][i])
|
|
|
|
self.addSuit(suit)
|
|
|
|
serialNum += 1
|
|
|
|
|
|
|
|
self.toonId2Door = {}
|
|
|
|
self.keyIdToKey = {}
|
|
|
|
self.players = []
|
|
|
|
self.toonId2Player = {}
|
|
|
|
cellPos = (int(self.maze.width / 2), self.maze.height - 1)
|
|
|
|
pos = self.maze.tile2world(*cellPos)
|
|
|
|
self._exit = CogdoMazeExit()
|
|
|
|
self._exit.reparentTo(render)
|
|
|
|
self._exit.setPos(self.maze.exitPos)
|
|
|
|
self._exit.stash()
|
|
|
|
self.guiMgr.mazeMapGui.placeExit(*cellPos)
|
|
|
|
self._collNode2waterCooler = {}
|
|
|
|
for waterCooler in self.maze.getWaterCoolers():
|
|
|
|
pos = waterCooler.getPos(render)
|
|
|
|
tpos = self.maze.world2tile(pos[0], pos[1])
|
|
|
|
self.guiMgr.mazeMapGui.addWaterCooler(*tpos)
|
|
|
|
self._collNode2waterCooler[waterCooler.collNode] = waterCooler
|
|
|
|
|
|
|
|
self.pickups = []
|
|
|
|
self.gagModel = CogdoUtil.loadMazeModel('waterBalloon')
|
|
|
|
self._movie = CogdoMazeGameIntro(self.maze, self._exit, self.distGame.randomNumGen)
|
|
|
|
self._movie.load()
|
|
|
|
return
|
|
|
|
|
|
|
|
def _initAudio(self):
|
|
|
|
self._audioMgr = CogdoGameAudioManager(Globals.MusicFiles, Globals.SfxFiles, camera, cutoff=Globals.AudioCutoff)
|
|
|
|
self._quakeSfx1 = self._audioMgr.createSfx('quake')
|
|
|
|
self._quakeSfx2 = self._audioMgr.createSfx('quake')
|
|
|
|
|
|
|
|
def _destroyAudio(self):
|
|
|
|
self._quakeSfx1.destroy()
|
|
|
|
self._quakeSfx2.destroy()
|
|
|
|
del self._quakeSfx1
|
|
|
|
del self._quakeSfx2
|
|
|
|
self._audioMgr.destroy()
|
|
|
|
del self._audioMgr
|
|
|
|
|
|
|
|
def addSuit(self, suit):
|
|
|
|
id = suit.serialNum
|
|
|
|
self.suits.append(suit)
|
|
|
|
if suit.type == Globals.SuitTypes.Boss:
|
|
|
|
self.shakers.append(suit)
|
|
|
|
self.suitsById[id] = suit
|
|
|
|
|
|
|
|
def removeSuit(self, suit):
|
|
|
|
id = suit.serialNum
|
|
|
|
del self.suitsById[id]
|
|
|
|
if suit.type == Globals.SuitTypes.Boss:
|
|
|
|
self.shakers.remove(suit)
|
|
|
|
self.guiMgr.showBossCode(id)
|
|
|
|
self.guiMgr.mazeMapGui.removeSuit(suit.suit)
|
|
|
|
self.suits.remove(suit)
|
|
|
|
suit.destroy()
|
|
|
|
|
|
|
|
def unload(self):
|
|
|
|
self.toonsThatRevealedDoor = []
|
|
|
|
for suit in self.suits:
|
|
|
|
suit.destroy()
|
|
|
|
|
|
|
|
del self.suits
|
2019-12-30 00:07:56 -06:00
|
|
|
for id in list(self.drops.keys()):
|
2019-11-02 17:27:54 -05:00
|
|
|
self.cleanupDrop(id)
|
|
|
|
|
|
|
|
self.__stopUpdateTask()
|
|
|
|
self.ignoreAll()
|
|
|
|
self.maze.destroy()
|
|
|
|
del self.maze
|
|
|
|
self._exit.destroy()
|
|
|
|
del self._exit
|
|
|
|
self.guiMgr.destroy()
|
|
|
|
del self.guiMgr
|
|
|
|
for player in self.players:
|
|
|
|
player.destroy()
|
|
|
|
|
|
|
|
del self.players
|
|
|
|
del self.toonId2Player
|
|
|
|
del self.localPlayer
|
|
|
|
for pickup in self.pickups:
|
|
|
|
pickup.destroy()
|
|
|
|
|
|
|
|
self._destroyAudio()
|
|
|
|
del self.distGame
|
|
|
|
|
|
|
|
def onstage(self):
|
|
|
|
self._exit.onstage()
|
|
|
|
self.maze.onstage()
|
|
|
|
|
|
|
|
def offstage(self):
|
|
|
|
self.maze.offstage()
|
|
|
|
self._exit.offstage()
|
|
|
|
for suit in self.suits:
|
|
|
|
suit.offstage()
|
|
|
|
|
|
|
|
def startIntro(self):
|
|
|
|
self._movie.play()
|
|
|
|
self._audioMgr.playMusic('normal')
|
|
|
|
|
|
|
|
def endIntro(self):
|
|
|
|
self._movie.end()
|
|
|
|
self._movie.unload()
|
|
|
|
del self._movie
|
|
|
|
for player in self.players:
|
|
|
|
self.placePlayer(player)
|
|
|
|
if player.toon is localAvatar:
|
|
|
|
localAvatar.sendCurrentPosition()
|
|
|
|
player.request('Ready')
|
|
|
|
|
|
|
|
def startFinish(self):
|
|
|
|
self._movie = CogdoMazeGameFinish(self.localPlayer, self._exit)
|
|
|
|
self._movie.load()
|
|
|
|
self._movie.play()
|
|
|
|
|
|
|
|
def endFinish(self):
|
|
|
|
self._movie.end()
|
|
|
|
self._movie.unload()
|
|
|
|
del self._movie
|
|
|
|
|
|
|
|
def placeEntranceElevator(self, elevator):
|
|
|
|
pos = self.maze.elevatorPos
|
|
|
|
elevator.setPos(pos)
|
|
|
|
tpos = self.maze.world2tile(pos[0], pos[1])
|
|
|
|
self.guiMgr.mazeMapGui.placeEntrance(*tpos)
|
|
|
|
|
|
|
|
def initPlayers(self):
|
|
|
|
for toonId in self.distGame.getToonIds():
|
|
|
|
toon = self.distGame.getToon(toonId)
|
|
|
|
if toon is not None:
|
|
|
|
if toon.isLocal():
|
|
|
|
player = CogdoMazeLocalPlayer(len(self.players), base.localAvatar, self, self.guiMgr)
|
|
|
|
self.localPlayer = player
|
|
|
|
else:
|
|
|
|
player = CogdoMazePlayer(len(self.players), toon)
|
|
|
|
self._addPlayer(player)
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
def start(self):
|
|
|
|
self.accept(self.PlayerDropCollision, self.handleLocalToonMeetsDrop)
|
|
|
|
self.accept(self.PlayerCoolerCollision, self.handleLocalToonMeetsWaterCooler)
|
|
|
|
self.accept(CogdoMazeExit.EnterEventName, self.handleLocalToonEntersDoor)
|
|
|
|
self.accept(CogdoMemo.EnterEventName, self.handleLocalToonMeetsPickup)
|
|
|
|
if self._allowSuitsHitToons:
|
|
|
|
self.accept(CogdoMazeSuit.COLLISION_EVENT_NAME, self.handleLocalToonMeetsSuit)
|
|
|
|
self.accept(CogdoMazePlayer.GagHitEventName, self.handleToonMeetsGag)
|
|
|
|
self.accept(CogdoMazeSuit.GagHitEventName, self.handleLocalSuitMeetsGag)
|
|
|
|
self.accept(CogdoMazeSuit.DeathEventName, self.handleSuitDeath)
|
|
|
|
self.accept(CogdoMazeSuit.ThinkEventName, self.handleSuitThink)
|
|
|
|
self.accept(CogdoMazeBossSuit.ShakeEventName, self.handleBossShake)
|
|
|
|
self.accept(CogdoMazePlayer.RemovedEventName, self._removePlayer)
|
|
|
|
self.__startUpdateTask()
|
|
|
|
for player in self.players:
|
|
|
|
player.handleGameStart()
|
|
|
|
player.request('Normal')
|
|
|
|
|
|
|
|
for suit in self.suits:
|
|
|
|
suit.onstage()
|
|
|
|
suit.gameStart(self.distGame.getStartTime())
|
|
|
|
|
|
|
|
def exit(self):
|
|
|
|
self._quakeSfx1.stop()
|
|
|
|
self._quakeSfx2.stop()
|
|
|
|
for suit in self.suits:
|
|
|
|
suit.gameEnd()
|
|
|
|
|
|
|
|
self.ignore(self.PlayerDropCollision)
|
|
|
|
self.ignore(self.PlayerCoolerCollision)
|
|
|
|
self.ignore(CogdoMazeExit.EnterEventName)
|
|
|
|
self.ignore(CogdoMemo.EnterEventName)
|
|
|
|
self.ignore(CogdoMazeSuit.COLLISION_EVENT_NAME)
|
|
|
|
self.ignore(CogdoMazePlayer.GagHitEventName)
|
|
|
|
self.ignore(CogdoMazeSuit.GagHitEventName)
|
|
|
|
self.ignore(CogdoMazeSuit.DeathEventName)
|
|
|
|
self.ignore(CogdoMazeSuit.ThinkEventName)
|
|
|
|
self.ignore(CogdoMazeBossSuit.ShakeEventName)
|
|
|
|
self.ignore(CogdoMazePlayer.RemovedEventName)
|
|
|
|
self.__stopUpdateTask()
|
|
|
|
for timeoutTask in self.gagTimeoutTasks:
|
|
|
|
taskMgr.remove(timeoutTask)
|
|
|
|
|
|
|
|
self.finished = True
|
|
|
|
self.localPlayer.handleGameExit()
|
|
|
|
for player in self.players:
|
|
|
|
player.request('Done')
|
|
|
|
|
|
|
|
self.guiMgr.hideTimer()
|
|
|
|
self.guiMgr.hideMazeMap()
|
|
|
|
self.guiMgr.hideBossGui()
|
|
|
|
|
|
|
|
def _addPlayer(self, player):
|
|
|
|
self.players.append(player)
|
|
|
|
self.toonId2Player[player.toon.doId] = player
|
|
|
|
|
|
|
|
def _removePlayer(self, player):
|
|
|
|
if player in self.players:
|
|
|
|
self.players.remove(player)
|
|
|
|
else:
|
|
|
|
for cPlayer in self.players:
|
|
|
|
if cPlayer.toon == player.toon:
|
|
|
|
self.players.remove(cPlayer)
|
|
|
|
break
|
|
|
|
|
2019-12-30 00:07:56 -06:00
|
|
|
if player.toon.doId in self.toonId2Player:
|
2019-11-02 17:27:54 -05:00
|
|
|
del self.toonId2Player[player.toon.doId]
|
|
|
|
self.guiMgr.mazeMapGui.removeToon(player.toon)
|
|
|
|
|
|
|
|
def handleToonLeft(self, toonId):
|
|
|
|
self._removePlayer(self.toonId2Player[toonId])
|
|
|
|
|
|
|
|
def __startUpdateTask(self):
|
|
|
|
self.__stopUpdateTask()
|
|
|
|
taskMgr.add(self.__updateTask, CogdoMazeGame.UpdateTaskName, 45)
|
|
|
|
|
|
|
|
def __stopUpdateTask(self):
|
|
|
|
taskMgr.remove(CogdoMazeGame.UpdateTaskName)
|
|
|
|
taskMgr.remove('loopSecondQuakeSound')
|
|
|
|
|
|
|
|
def __updateTask(self, task):
|
|
|
|
dt = globalClock.getDt()
|
|
|
|
self.localPlayer.update(dt)
|
|
|
|
for player in self.players:
|
|
|
|
curTX, curTY = self.maze.world2tileClipped(player.toon.getX(), player.toon.getY())
|
|
|
|
self.guiMgr.mazeMapGui.updateToon(player.toon, curTX, curTY)
|
|
|
|
|
|
|
|
self.__updateGags()
|
|
|
|
if Globals.QuakeSfxEnabled:
|
|
|
|
self.__updateQuakeSound()
|
|
|
|
for pickup in self.pickups:
|
|
|
|
pickup.update(dt)
|
|
|
|
|
|
|
|
MazeSuit.thinkSuits(self.suits, self.distGame.getStartTime())
|
|
|
|
return Task.cont
|
|
|
|
|
|
|
|
def __updateGags(self):
|
|
|
|
remove = []
|
|
|
|
for i in range(len(self.gags)):
|
|
|
|
balloon = self.gags[i]
|
|
|
|
if balloon.isSingleton():
|
|
|
|
remove.append(i)
|
|
|
|
elif balloon.getParent() == render:
|
|
|
|
loc = self.maze.world2tile(balloon.getX(), balloon.getY())
|
|
|
|
if not self.maze.isAccessible(loc[0], loc[1]):
|
|
|
|
self.removeGag(balloon)
|
|
|
|
|
|
|
|
remove.reverse()
|
|
|
|
for i in remove:
|
|
|
|
self.gags.pop(i)
|
|
|
|
|
|
|
|
def __updateQuakeSound(self):
|
|
|
|
shake = self.localPlayer.getCameraShake()
|
|
|
|
if shake < 1.0:
|
|
|
|
shake = 1.0
|
|
|
|
volume = 3.0 * shake / Globals.CameraShakeMax
|
|
|
|
if volume > 3.0:
|
|
|
|
volume = 3.0
|
|
|
|
if self._quakeSfx1.getAudioSound().status() != self._quakeSfx1.getAudioSound().PLAYING:
|
|
|
|
self._quakeSfx1.loop(volume=volume)
|
|
|
|
else:
|
|
|
|
self._quakeSfx1.getAudioSound().setVolume(volume)
|
|
|
|
volume = shake * shake / Globals.CameraShakeMax
|
|
|
|
if not self.hackTemp and self._quakeSfx2.getAudioSound().status() != self._quakeSfx2.getAudioSound().PLAYING:
|
|
|
|
taskMgr.doMethodLater(1.5, self._quakeSfx2.loop, 'loopSecondQuakeSound', extraArgs=[])
|
|
|
|
self.hackTemp = True
|
|
|
|
else:
|
|
|
|
self._quakeSfx2.getAudioSound().setVolume(volume)
|
|
|
|
|
|
|
|
def handleLocalToonMeetsSuit(self, suitType, suitNum):
|
|
|
|
if self.localPlayer.state == 'Normal' and not self.localPlayer.invulnerable:
|
|
|
|
self.distGame.b_toonHitBySuit(suitType, suitNum)
|
|
|
|
|
|
|
|
def toonHitBySuit(self, toonId, suitType, suitNum, elapsedTime = 0.0):
|
|
|
|
player = self.toonId2Player[toonId]
|
|
|
|
if player.state == 'Normal':
|
|
|
|
player.request('Hit', elapsedTime)
|
|
|
|
|
|
|
|
def handleSuitDeath(self, suitType, suitNum):
|
|
|
|
suit = self.suitsById[suitNum]
|
|
|
|
self.dropMemos(suit)
|
|
|
|
self.removeSuit(suit)
|
|
|
|
|
|
|
|
def dropMemos(self, suit):
|
|
|
|
numDrops = suit.memos
|
|
|
|
if numDrops > 0:
|
|
|
|
start = math.radians(random.randint(0, 360))
|
|
|
|
step = math.radians(360.0 / numDrops)
|
|
|
|
radius = 2.0
|
|
|
|
for i in range(numDrops):
|
|
|
|
angle = start + i * step
|
|
|
|
x = radius * math.cos(angle) + suit.suit.getX()
|
|
|
|
y = radius * math.sin(angle) + suit.suit.getY()
|
|
|
|
self.generatePickup(x, y)
|
|
|
|
|
|
|
|
def handleSuitThink(self, suit, TX, TY):
|
|
|
|
if suit in self.shakers:
|
|
|
|
self.guiMgr.mazeMapGui.updateSuit(suit.suit, TX, TY)
|
|
|
|
suit.dropTimer += 1
|
|
|
|
if suit.dropTimer >= Globals.DropFrequency:
|
|
|
|
self.doDrop(suit)
|
|
|
|
suit.dropTimer = 0
|
|
|
|
|
|
|
|
def doDrop(self, boss):
|
|
|
|
dropLoc = boss.pickRandomValidSpot()
|
|
|
|
self.generateDrop(dropLoc[0], dropLoc[1])
|
|
|
|
|
|
|
|
def handleBossShake(self, suit, strength):
|
|
|
|
if Globals.BossShakeEnabled:
|
|
|
|
self.shakeCamera(suit.suit, strength, Globals.BossMaxDistance)
|
|
|
|
|
|
|
|
def randomDrop(self, centerTX, centerTY, radius):
|
|
|
|
dropArray = []
|
2019-12-30 00:07:56 -06:00
|
|
|
for i in range(1, distance):
|
2019-11-02 17:27:54 -05:00
|
|
|
dropArray.append(i)
|
|
|
|
dropArray.append(-1 * i)
|
|
|
|
|
|
|
|
offsetTX = self.distGame.randomNumGen.choice(dropArray)
|
|
|
|
offsetTY = self.distGame.randomNumGen.choice(dropArray)
|
|
|
|
dropTX = sourceTX + offsetTX
|
|
|
|
dropTY = sourceTY + offsetTY
|
|
|
|
if self.maze.isWalkable(dropTX, dropTY):
|
|
|
|
self.generateDrop(dropTX, dropTY)
|
|
|
|
|
|
|
|
def generateDrop(self, TX, TY):
|
|
|
|
drop = self.maze.tile2world(TX, TY)
|
|
|
|
ival = self.createDrop(drop[0], drop[1])
|
|
|
|
ival.start()
|
|
|
|
|
|
|
|
def createDrop(self, x, y):
|
|
|
|
self.dropCounter = self.dropCounter + 1
|
|
|
|
id = self.dropCounter
|
|
|
|
drop = CogdoMazeDrop(self, id, x, y)
|
|
|
|
self.drops[id] = drop
|
|
|
|
return drop.getDropIval()
|
|
|
|
|
|
|
|
def cleanupDrop(self, id):
|
2019-12-30 00:07:56 -06:00
|
|
|
if id in list(self.drops.keys()):
|
2019-11-02 17:27:54 -05:00
|
|
|
drop = self.drops[id]
|
|
|
|
drop.destroy()
|
|
|
|
del self.drops[id]
|
|
|
|
|
|
|
|
def dropHit(self, node, id):
|
|
|
|
if self.finished:
|
|
|
|
return
|
|
|
|
if Globals.DropShakeEnabled:
|
|
|
|
self.shakeCamera(node, Globals.DropShakeStrength, Globals.DropMaxDistance)
|
|
|
|
|
|
|
|
def shakeCamera(self, node, strength, distanceCutoff = 60.0):
|
|
|
|
distance = self.localPlayer.toon.getDistance(node)
|
|
|
|
shake = strength * (1 - distance / distanceCutoff)
|
|
|
|
if shake > 0:
|
|
|
|
self.localPlayer.shakeCamera(shake)
|
|
|
|
|
|
|
|
def handleLocalToonMeetsDrop(self, collEntry):
|
|
|
|
fcabinet = collEntry.getIntoNodePath()
|
|
|
|
if fcabinet.getTag('isFalling') == str('False'):
|
|
|
|
return
|
|
|
|
if self.localPlayer.state == 'Normal' and not self.localPlayer.invulnerable:
|
|
|
|
self.distGame.b_toonHitByDrop()
|
|
|
|
|
|
|
|
def toonHitByDrop(self, toonId):
|
|
|
|
player = self.toonId2Player[toonId]
|
|
|
|
player.hitByDrop()
|
|
|
|
|
|
|
|
def handleLocalToonMeetsGagPickup(self, collEntry):
|
|
|
|
if self.localPlayer.equippedGag != None:
|
|
|
|
return
|
|
|
|
into = collEntry.getIntoNodePath()
|
|
|
|
if into.hasPythonTag('id'):
|
|
|
|
id = into.getPythonTag('id')
|
|
|
|
self.distGame.d_sendRequestGagPickUp(id)
|
|
|
|
return
|
|
|
|
|
|
|
|
def hasGag(self, toonId, elapsedTime = 0.0):
|
|
|
|
player = self.toonId2Player[toonId]
|
|
|
|
player.equipGag()
|
|
|
|
|
|
|
|
def handleLocalToonMeetsWaterCooler(self, collEntry):
|
|
|
|
if self.localPlayer.equippedGag != None:
|
|
|
|
return
|
|
|
|
if self.lastBalloonTimestamp and globalClock.getFrameTime() - self.lastBalloonTimestamp < Globals.BalloonDelay:
|
|
|
|
return
|
|
|
|
collNode = collEntry.getIntoNode()
|
|
|
|
waterCooler = self._collNode2waterCooler[collNode]
|
|
|
|
self.lastBalloonTimestamp = globalClock.getFrameTime()
|
|
|
|
self.distGame.d_sendRequestGag(waterCooler.serialNum)
|
|
|
|
return
|
|
|
|
|
|
|
|
def requestUseGag(self, x, y, h):
|
|
|
|
self.distGame.b_toonUsedGag(x, y, h)
|
|
|
|
|
|
|
|
def toonUsedGag(self, toonId, x, y, h, elapsedTime = 0.0):
|
|
|
|
player = self.toonId2Player[toonId]
|
|
|
|
heading = h
|
|
|
|
pos = Point3(x, y, 0)
|
|
|
|
gag = player.showToonThrowingGag(heading, pos)
|
|
|
|
if gag is not None:
|
|
|
|
self.gags.append(gag)
|
|
|
|
return
|
|
|
|
|
|
|
|
def handleToonMeetsGag(self, playerId, gag):
|
|
|
|
self.removeGag(gag)
|
|
|
|
self.distGame.b_toonHitByGag(playerId)
|
|
|
|
|
|
|
|
def toonHitByGag(self, toonId, hitToon, elapsedTime = 0.0):
|
2019-12-30 00:07:56 -06:00
|
|
|
if toonId not in list(self.toonId2Player.keys()) or hitToon not in list(self.toonId2Player.keys()):
|
2019-11-02 17:27:54 -05:00
|
|
|
return
|
|
|
|
player = self.toonId2Player[hitToon]
|
|
|
|
player.hitByGag()
|
|
|
|
|
|
|
|
def handleLocalSuitMeetsGag(self, suitType, suitNum, gag):
|
|
|
|
self.removeGag(gag)
|
|
|
|
self.localPlayer.hitSuit(suitType)
|
|
|
|
self.distGame.b_suitHitByGag(suitType, suitNum)
|
|
|
|
|
|
|
|
def suitHitByGag(self, toonId, suitType, suitNum, elapsedTime = 0.0):
|
|
|
|
if suitType == Globals.SuitTypes.Boss:
|
|
|
|
self.guiMgr.showBossHit(suitNum)
|
2019-12-30 00:07:56 -06:00
|
|
|
if suitNum in list(self.suitsById.keys()):
|
2019-11-02 17:27:54 -05:00
|
|
|
suit = self.suitsById[suitNum]
|
|
|
|
suit.hitByGag()
|
|
|
|
|
|
|
|
def removeGag(self, gag):
|
|
|
|
gag.detachNode()
|
|
|
|
|
|
|
|
def toonRevealsDoor(self, toonId):
|
|
|
|
self._exit.revealed = True
|
|
|
|
|
|
|
|
def openDoor(self, timeLeft):
|
|
|
|
self._audioMgr.playMusic('timeRunningOut')
|
|
|
|
if not self._exit.isOpen():
|
|
|
|
self._exit.open()
|
|
|
|
self.localPlayer.handleOpenDoor(self._exit)
|
|
|
|
self.guiMgr.showTimer(timeLeft, self._handleTimerExpired)
|
|
|
|
self.guiMgr.mazeMapGui.showExit()
|
|
|
|
self.guiMgr.mazeMapGui.revealAll()
|
|
|
|
|
|
|
|
def countdown(self, timeLeft):
|
|
|
|
self.guiMgr.showTimer(timeLeft, self._handleTimerExpired)
|
|
|
|
|
|
|
|
def timeAlert(self):
|
|
|
|
self._audioMgr.playMusic('timeRunningOut')
|
|
|
|
|
|
|
|
def _handleTimerExpired(self):
|
|
|
|
self.localPlayer.request('Done')
|
|
|
|
|
|
|
|
def toonEntersDoor(self, toonId):
|
|
|
|
player = self.toonId2Player[toonId]
|
|
|
|
self.guiMgr.mazeMapGui.removeToon(player.toon)
|
|
|
|
self._exit.playerEntersDoor(player)
|
|
|
|
self.localPlayer.handleToonEntersDoor(toonId, self._exit)
|
|
|
|
player.request('Done')
|
|
|
|
|
|
|
|
def generatePickup(self, x, y):
|
|
|
|
pickup = CogdoMemo(len(self.pickups), pitch=-90)
|
|
|
|
self.pickups.append(pickup)
|
|
|
|
pickup.reparentTo(self.maze.maze)
|
|
|
|
pickup.setPos(x, y, 1)
|
|
|
|
pickup.enable()
|
|
|
|
|
|
|
|
def handleLocalToonMeetsPickup(self, pickup):
|
|
|
|
pickup.disable()
|
|
|
|
self.distGame.d_sendRequestPickUp(pickup.serialNum)
|
|
|
|
|
|
|
|
def pickUp(self, toonId, pickupNum, elapsedTime = 0.0):
|
|
|
|
self.notify.debugCall()
|
|
|
|
player = self.toonId2Player[toonId]
|
|
|
|
pickup = self.pickups[pickupNum]
|
|
|
|
if not pickup.wasPickedUp():
|
|
|
|
pickup.pickUp(player.toon, elapsedTime)
|
|
|
|
self.localPlayer.handlePickUp(toonId)
|
|
|
|
|
|
|
|
def placePlayer(self, player):
|
|
|
|
toonIds = self.distGame.getToonIds()
|
|
|
|
if player.toon.doId not in toonIds:
|
|
|
|
return
|
|
|
|
i = toonIds.index(player.toon.doId)
|
|
|
|
x = int(self.maze.width / 2.0) - int(len(toonIds) / 2.0) + i
|
|
|
|
y = 2
|
|
|
|
while not self.maze.isAccessible(x, y):
|
|
|
|
y += 1
|
|
|
|
|
|
|
|
pos = self.maze.tile2world(x, y)
|
|
|
|
player.toon.setPos(pos[0], pos[1], 0)
|
|
|
|
self.guiMgr.mazeMapGui.addToon(player.toon, x, y)
|
|
|
|
|
|
|
|
def handleLocalToonEntersDoor(self, door):
|
|
|
|
localToonId = self.localPlayer.toon.doId
|
|
|
|
if self._exit.isOpen():
|
|
|
|
self.distGame.d_sendRequestAction(Globals.GameActions.EnterDoor, 0)
|
|
|
|
else:
|
|
|
|
if localToonId not in self.toonsThatRevealedDoor:
|
|
|
|
self.toonsThatRevealedDoor.append(localToonId)
|
|
|
|
self.localPlayer.handleToonRevealsDoor(localToonId, self._exit)
|
|
|
|
if not self._exit.revealed:
|
|
|
|
self.toonRevealsDoor(localToonId)
|
|
|
|
self.distGame.d_sendRequestAction(Globals.GameActions.RevealDoor, 0)
|
|
|
|
|
|
|
|
def handleToonWentSad(self, toonId):
|
|
|
|
if toonId == self.localPlayer.toon.doId:
|
|
|
|
for player in self.players:
|
|
|
|
player.removeGag()
|
|
|
|
|
2019-12-30 00:07:56 -06:00
|
|
|
elif toonId in list(self.toonId2Player.keys()):
|
2019-11-02 17:27:54 -05:00
|
|
|
player = self.toonId2Player[toonId]
|
|
|
|
player.removeGag()
|
|
|
|
|
|
|
|
def handleToonDisconnected(self, toonId):
|
|
|
|
if toonId == self.localPlayer.toon.doId:
|
|
|
|
pass
|
2019-12-30 00:07:56 -06:00
|
|
|
elif toonId in list(self.toonId2Player.keys()):
|
2019-11-02 17:27:54 -05:00
|
|
|
player = self.toonId2Player[toonId]
|
|
|
|
self._removePlayer(player)
|