def createCatchCollisions(self): radius = 0.7 handler = CollisionHandlerEvent() handler.setInPattern('ltCatch%in') self.ltLegsCollNode = CollisionNode('catchLegsCollNode') self.ltLegsCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) self.ltHeadCollNode = CollisionNode('catchHeadCollNode') self.ltHeadCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) self.ltLHandCollNode = CollisionNode('catchLHandCollNode') self.ltLHandCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) self.ltRHandCollNode = CollisionNode('catchRHandCollNode') self.ltRHandCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) legsCollNodepath = base.localAvatar.attachNewNode(self.ltLegsCollNode) legsCollNodepath.hide() head = base.localAvatar.getHeadParts().getPath(2) headCollNodepath = head.attachNewNode(self.ltHeadCollNode) headCollNodepath.hide() lHand = base.localAvatar.getLeftHands()[0] lHandCollNodepath = lHand.attachNewNode(self.ltLHandCollNode) lHandCollNodepath.hide() rHand = base.localAvatar.getRightHands()[0] rHandCollNodepath = rHand.attachNewNode(self.ltRHandCollNode) rHandCollNodepath.hide() base.localAvatar.cTrav.addCollider(legsCollNodepath, handler) base.localAvatar.cTrav.addCollider(headCollNodepath, handler) base.localAvatar.cTrav.addCollider(lHandCollNodepath, handler) base.localAvatar.cTrav.addCollider(lHandCollNodepath, handler) if self.ShowToonSpheres: legsCollNodepath.show() headCollNodepath.show() lHandCollNodepath.show() rHandCollNodepath.show() self.ltLegsCollNode.addSolid(CollisionSphere(0, 0, radius, radius)) self.ltHeadCollNode.addSolid(CollisionSphere(0, 0, 0, radius)) self.ltLHandCollNode.addSolid( CollisionSphere(0, 0, 0, 2 * radius / 3.0)) self.ltRHandCollNode.addSolid( CollisionSphere(0, 0, 0, 2 * radius / 3.0)) self.toonCollNodes = [ legsCollNodepath, headCollNodepath, lHandCollNodepath, rHandCollNodepath ]
def createCatchCollisions(self): radius = 0.7 handler = CollisionHandlerEvent() handler.setInPattern('ltCatch%in') self.ltLegsCollNode = CollisionNode('catchLegsCollNode') self.ltLegsCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) self.ltHeadCollNode = CollisionNode('catchHeadCollNode') self.ltHeadCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) self.ltLHandCollNode = CollisionNode('catchLHandCollNode') self.ltLHandCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) self.ltRHandCollNode = CollisionNode('catchRHandCollNode') self.ltRHandCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask) legsCollNodepath = base.localAvatar.attachNewNode(self.ltLegsCollNode) legsCollNodepath.hide() head = base.localAvatar.getHeadParts().getPath(2) headCollNodepath = head.attachNewNode(self.ltHeadCollNode) headCollNodepath.hide() lHand = base.localAvatar.getLeftHands()[0] lHandCollNodepath = lHand.attachNewNode(self.ltLHandCollNode) lHandCollNodepath.hide() rHand = base.localAvatar.getRightHands()[0] rHandCollNodepath = rHand.attachNewNode(self.ltRHandCollNode) rHandCollNodepath.hide() base.localAvatar.cTrav.addCollider(legsCollNodepath, handler) base.localAvatar.cTrav.addCollider(headCollNodepath, handler) base.localAvatar.cTrav.addCollider(lHandCollNodepath, handler) base.localAvatar.cTrav.addCollider(lHandCollNodepath, handler) if self.ShowToonSpheres: legsCollNodepath.show() headCollNodepath.show() lHandCollNodepath.show() rHandCollNodepath.show() self.ltLegsCollNode.addSolid(CollisionSphere(0, 0, radius, radius)) self.ltHeadCollNode.addSolid(CollisionSphere(0, 0, 0, radius)) self.ltLHandCollNode.addSolid(CollisionSphere(0, 0, 0, 2 * radius / 3.0)) self.ltRHandCollNode.addSolid(CollisionSphere(0, 0, 0, 2 * radius / 3.0)) self.toonCollNodes = [legsCollNodepath, headCollNodepath, lHandCollNodepath, rHandCollNodepath]
def load(self): self.notify.debug('load') DistributedMinigame.load(self) self.music = base.loadMusic('phase_4/audio/bgm/MG_CogThief.ogg') self.initCogInfo() for barrelIndex in xrange(CTGG.NumBarrels): barrel = loader.loadModel( 'phase_4/models/minigames/cogthief_game_gagTank') barrel.setPos(CTGG.BarrelStartingPositions[barrelIndex]) barrel.setScale(self.BarrelScale) barrel.reparentTo(render) barrel.setTag('barrelIndex', str(barrelIndex)) collSphere = CollisionSphere(0, 0, 0, 4) collSphere.setTangible(0) name = 'BarrelSphere-%d' % barrelIndex collSphereName = self.uniqueName(name) collNode = CollisionNode(collSphereName) collNode.setFromCollideMask(CTGG.BarrelBitmask) collNode.addSolid(collSphere) colNp = barrel.attachNewNode(collNode) handler = CollisionHandlerEvent() handler.setInPattern('barrelHit-%fn') base.cTrav.addCollider(colNp, handler) self.accept('barrelHit-' + collSphereName, self.handleEnterBarrel) nodeToHide = '**/gagMoneyTen' if barrelIndex % 2: nodeToHide = '**/gagMoneyFive' iconToHide = barrel.find(nodeToHide) if not iconToHide.isEmpty(): iconToHide.hide() self.barrels.append(barrel) self.gameBoard = loader.loadModel( 'phase_4/models/minigames/cogthief_game') self.gameBoard.find('**/floor_TT').hide() self.gameBoard.find('**/floor_DD').hide() self.gameBoard.find('**/floor_DG').hide() self.gameBoard.find('**/floor_MM').hide() self.gameBoard.find('**/floor_BR').hide() self.gameBoard.find('**/floor_DL').hide() zone = self.getSafezoneId() if zone == ToontownGlobals.ToontownCentral: self.gameBoard.find('**/floor_TT').show() elif zone == ToontownGlobals.DonaldsDock: self.gameBoard.find('**/floor_DD').show() elif zone == ToontownGlobals.DaisyGardens: self.gameBoard.find('**/floor_DG').show() elif zone == ToontownGlobals.MinniesMelodyland: self.gameBoard.find('**/floor_MM').show() elif zone == ToontownGlobals.TheBrrrgh: self.gameBoard.find('**/floor_BR').show() elif zone == ToontownGlobals.DonaldsDreamland: self.gameBoard.find('**/floor_DL').show() else: self.gameBoard.find('**/floor_TT').show() self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) self.toonSDs = {} avId = self.localAvId toonSD = CogThiefGameToonSD.CogThiefGameToonSD(avId, self) self.toonSDs[avId] = toonSD toonSD.load() self.loadCogs() self.toonHitTracks = {} self.toonPieTracks = {} self.sndOof = base.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') self.sndRewardTick = base.loadSfx( 'phase_3.5/audio/sfx/tick_counter.ogg') self.sndPerfect = base.loadSfx('phase_4/audio/sfx/ring_perfect.ogg') self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.hide() purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui') self.jarImage = purchaseModels.find('**/Jar') self.jarImage.reparentTo(hidden) self.rewardPanel = DirectLabel(parent=hidden, relief=None, pos=(-0.173, 0.0, -0.55), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage) self.rewardPanelTitle = DirectLabel(parent=self.rewardPanel, relief=None, pos=(0, 0, 0.06), scale=0.08, text=TTLocalizer.CannonGameReward, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1)) return
class DistributedCogThiefGame(DistributedMinigame): notify = directNotify.newCategory('DistributedCogThiefGame') ToonSpeed = CTGG.ToonSpeed StageHalfWidth = 200.0 StageHalfHeight = 100.0 BarrelScale = 0.25 TOON_Z = 0 UPDATE_SUITS_TASK = 'CogThiefGameUpdateSuitsTask' REWARD_COUNTDOWN_TASK = 'cogThiefGameRewardCountdown' ControlKeyLimitTime = 1.0 def __init__(self, cr): DistributedMinigame.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedCogThiefGame', [ State.State('off', self.enterOff, self.exitOff, ['play']), State.State('play', self.enterPlay, self.exitPlay, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, []) ], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.cameraTopView = (0, 0, 55, 0, -90.0, 0) self.barrels = [] self.cogInfo = {} self.lastTimeControlPressed = 0 self.stolenBarrels = [] self.useOrthoWalk = base.config.GetBool('cog-thief-ortho', 1) self.resultIval = None self.gameIsEnding = False self.__textGen = TextNode('cogThiefGame') self.__textGen.setFont(ToontownGlobals.getSignFont()) self.__textGen.setAlign(TextNode.ACenter) return def getTitle(self): return TTLocalizer.CogThiefGameTitle def getInstructions(self): return TTLocalizer.CogThiefGameInstructions def getMaxDuration(self): return 0 def load(self): self.notify.debug('load') DistributedMinigame.load(self) self.music = base.loadMusic('phase_4/audio/bgm/MG_CogThief.ogg') self.initCogInfo() for barrelIndex in xrange(CTGG.NumBarrels): barrel = loader.loadModel( 'phase_4/models/minigames/cogthief_game_gagTank') barrel.setPos(CTGG.BarrelStartingPositions[barrelIndex]) barrel.setScale(self.BarrelScale) barrel.reparentTo(render) barrel.setTag('barrelIndex', str(barrelIndex)) collSphere = CollisionSphere(0, 0, 0, 4) collSphere.setTangible(0) name = 'BarrelSphere-%d' % barrelIndex collSphereName = self.uniqueName(name) collNode = CollisionNode(collSphereName) collNode.setFromCollideMask(CTGG.BarrelBitmask) collNode.addSolid(collSphere) colNp = barrel.attachNewNode(collNode) handler = CollisionHandlerEvent() handler.setInPattern('barrelHit-%fn') base.cTrav.addCollider(colNp, handler) self.accept('barrelHit-' + collSphereName, self.handleEnterBarrel) nodeToHide = '**/gagMoneyTen' if barrelIndex % 2: nodeToHide = '**/gagMoneyFive' iconToHide = barrel.find(nodeToHide) if not iconToHide.isEmpty(): iconToHide.hide() self.barrels.append(barrel) self.gameBoard = loader.loadModel( 'phase_4/models/minigames/cogthief_game') self.gameBoard.find('**/floor_TT').hide() self.gameBoard.find('**/floor_DD').hide() self.gameBoard.find('**/floor_DG').hide() self.gameBoard.find('**/floor_MM').hide() self.gameBoard.find('**/floor_BR').hide() self.gameBoard.find('**/floor_DL').hide() zone = self.getSafezoneId() if zone == ToontownGlobals.ToontownCentral: self.gameBoard.find('**/floor_TT').show() elif zone == ToontownGlobals.DonaldsDock: self.gameBoard.find('**/floor_DD').show() elif zone == ToontownGlobals.DaisyGardens: self.gameBoard.find('**/floor_DG').show() elif zone == ToontownGlobals.MinniesMelodyland: self.gameBoard.find('**/floor_MM').show() elif zone == ToontownGlobals.TheBrrrgh: self.gameBoard.find('**/floor_BR').show() elif zone == ToontownGlobals.DonaldsDreamland: self.gameBoard.find('**/floor_DL').show() else: self.gameBoard.find('**/floor_TT').show() self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) self.toonSDs = {} avId = self.localAvId toonSD = CogThiefGameToonSD.CogThiefGameToonSD(avId, self) self.toonSDs[avId] = toonSD toonSD.load() self.loadCogs() self.toonHitTracks = {} self.toonPieTracks = {} self.sndOof = base.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') self.sndRewardTick = base.loadSfx( 'phase_3.5/audio/sfx/tick_counter.ogg') self.sndPerfect = base.loadSfx('phase_4/audio/sfx/ring_perfect.ogg') self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.hide() purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui') self.jarImage = purchaseModels.find('**/Jar') self.jarImage.reparentTo(hidden) self.rewardPanel = DirectLabel(parent=hidden, relief=None, pos=(-0.173, 0.0, -0.55), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage) self.rewardPanelTitle = DirectLabel(parent=self.rewardPanel, relief=None, pos=(0, 0, 0.06), scale=0.08, text=TTLocalizer.CannonGameReward, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1)) return def unload(self): self.notify.debug('unload') DistributedMinigame.unload(self) del self.music self.removeChildGameFSM(self.gameFSM) del self.gameFSM self.gameBoard.removeNode() del self.gameBoard for barrel in self.barrels: barrel.removeNode() del self.barrels for avId in self.toonSDs.keys(): toonSD = self.toonSDs[avId] toonSD.unload() del self.toonSDs self.timer.destroy() del self.timer self.rewardPanel.destroy() del self.rewardPanel self.jarImage.removeNode() del self.jarImage del self.sndRewardTick def onstage(self): self.notify.debug('onstage') DistributedMinigame.onstage(self) self.gameBoard.reparentTo(render) lt = base.localAvatar lt.reparentTo(render) self.__placeToon(self.localAvId) lt.setSpeed(0, 0) self.moveCameraToTop() toonSD = self.toonSDs[self.localAvId] toonSD.enter() toonSD.fsm.request('normal') self.stopGameWalk() for cogIndex in xrange(self.getNumCogs()): suit = self.cogInfo[cogIndex]['suit'].suit pos = self.cogInfo[cogIndex]['pos'] suit.reparentTo(self.gameBoard) suit.setPos(pos) suit.nametag3d.stash() suit.nametag.destroy() for avId in self.avIdList: self.toonHitTracks[avId] = Wait(0.1) self.toonRNGs = [] for i in xrange(self.numPlayers): self.toonRNGs.append(RandomNumGen.RandomNumGen(self.randomNumGen)) self.sndTable = { 'hitBySuit': [None] * self.numPlayers, 'falling': [None] * self.numPlayers } for i in xrange(self.numPlayers): self.sndTable['hitBySuit'][i] = base.loadSfx( 'phase_4/audio/sfx/MG_Tag_C.ogg') self.sndTable['falling'][i] = base.loadSfx( 'phase_4/audio/sfx/MG_cannon_whizz.ogg') base.playMusic(self.music, looping=1, volume=0.8) self.introTrack = self.getIntroTrack() self.introTrack.start() return def offstage(self): self.notify.debug('offstage') self.gameBoard.hide() self.music.stop() for barrel in self.barrels: barrel.hide() for avId in self.toonSDs.keys(): self.toonSDs[avId].exit() for avId in self.avIdList: av = self.getAvatar(avId) if av: av.resetLOD() self.timer.reparentTo(hidden) self.rewardPanel.reparentTo(hidden) if self.introTrack.isPlaying(): self.introTrack.finish() del self.introTrack DistributedMinigame.offstage(self) def handleDisabledAvatar(self, avId): self.notify.debug('handleDisabledAvatar') self.notify.debug('avatar ' + str(avId) + ' disabled') self.toonSDs[avId].exit(unexpectedExit=True) del self.toonSDs[avId] DistributedMinigame.handleDisabledAvatar(self, avId) def setGameReady(self): if not self.hasLocalToon: return self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.reparentTo(render) self.__placeToon(avId) toon.useLOD(1000) toonSD = CogThiefGameToonSD.CogThiefGameToonSD(avId, self) self.toonSDs[avId] = toonSD toonSD.load() toonSD.enter() toonSD.fsm.request('normal') toon.startSmooth() def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug('setGameStart') DistributedMinigame.setGameStart(self, timestamp) if not base.config.GetBool('cog-thief-endless', 0): self.timer.show() self.timer.countdown(CTGG.GameTime, self.__gameTimerExpired) self.clockStopTime = None self.rewardPanel.reparentTo(base.a2dTopRight) self.scoreMult = MinigameGlobals.getScoreMult(self.cr.playGame.hood.id) self.__startRewardCountdown() if self.introTrack.isPlaying(): self.introTrack.finish() self.gameFSM.request('play') return def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterPlay(self): self.notify.debug('enterPlay') self.startGameWalk() self.spawnUpdateSuitsTask() self.accept('control', self.controlKeyPressed) self.pieHandler = CollisionHandlerEvent() self.pieHandler.setInPattern('pieHit-%fn') def exitPlay(self): self.ignore('control') if self.resultIval and self.resultIval.isPlaying(): self.resultIval.finish() self.resultIval = None return def enterCleanup(self): self.__killRewardCountdown() if hasattr(self, 'jarIval'): self.jarIval.finish() del self.jarIval for key in self.toonHitTracks: ival = self.toonHitTracks[key] if ival.isPlaying(): ival.finish() self.toonHitTracks = {} for key in self.toonPieTracks: ival = self.toonPieTracks[key] if ival.isPlaying(): ival.finish() self.toonPieTracks = {} for key in self.cogInfo: cogThief = self.cogInfo[key]['suit'] cogThief.cleanup() self.removeUpdateSuitsTask() self.notify.debug('enterCleanup') def exitCleanup(self): pass def __placeToon(self, avId): toon = self.getAvatar(avId) if toon: index = self.avIdList.index(avId) toon.setPos(CTGG.ToonStartingPositions[index]) toon.setHpr(0, 0, 0) def moveCameraToTop(self): camera.reparentTo(render) p = self.cameraTopView camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5]) base.camLens.setMinFov(46 / (4. / 3.)) camera.setZ(camera.getZ() + base.config.GetFloat('cog-thief-z-camera-adjust', 0.0)) def destroyGameWalk(self): self.notify.debug('destroyOrthoWalk') if self.useOrthoWalk: self.gameWalk.destroy() del self.gameWalk else: self.notify.debug('TODO destroyGameWalk') def initGameWalk(self): self.notify.debug('startOrthoWalk') if self.useOrthoWalk: def doCollisions(oldPos, newPos, self=self): x = bound(newPos[0], CTGG.StageHalfWidth, -CTGG.StageHalfWidth) y = bound(newPos[1], CTGG.StageHalfHeight, -CTGG.StageHalfHeight) newPos.setX(x) newPos.setY(y) return newPos orthoDrive = OrthoDrive(self.ToonSpeed, customCollisionCallback=doCollisions, instantTurn=True) self.gameWalk = OrthoWalk(orthoDrive, broadcast=not self.isSinglePlayer()) else: self.gameWalk = CogThiefWalk.CogThiefWalk('walkDone') forwardSpeed = self.ToonSpeed / 2.0 base.mouseInterfaceNode.setForwardSpeed(forwardSpeed) multiplier = forwardSpeed / ToontownGlobals.ToonForwardSpeed base.mouseInterfaceNode.setRotateSpeed( ToontownGlobals.ToonRotateSpeed * 4) def initCogInfo(self): for cogIndex in xrange(self.getNumCogs()): self.cogInfo[cogIndex] = { 'pos': Point3(CTGG.CogStartingPositions[cogIndex]), 'goal': CTGG.NoGoal, 'goalId': CTGG.InvalidGoalId, 'suit': None } return def loadCogs(self): suitTypes = ['ds', 'ac', 'bc', 'ms'] for suitIndex in xrange(self.getNumCogs()): st = self.randomNumGen.choice(suitTypes) suit = CogThief.CogThief(suitIndex, st, self, self.getCogSpeed()) self.cogInfo[suitIndex]['suit'] = suit def handleEnterSphere(self, colEntry): if self.gameIsEnding: return intoName = colEntry.getIntoNodePath().getName() fromName = colEntry.getFromNodePath().getName() debugInto = intoName.split('/') debugFrom = fromName.split('/') self.notify.debug( 'handleEnterSphere gametime=%s %s into %s' % (self.getCurrentGameTime(), debugFrom[-1], debugInto[-1])) intoName = colEntry.getIntoNodePath().getName() if 'CogThiefSphere' in intoName: parts = intoName.split('-') suitNum = int(parts[1]) self.localToonHitBySuit(suitNum) def localToonHitBySuit(self, suitNum): self.notify.debug('localToonHitBySuit %d' % suitNum) timestamp = globalClockDelta.localToNetworkTime( globalClock.getFrameTime(), bits=32) pos = self.cogInfo[suitNum]['suit'].suit.getPos() self.sendUpdate( 'hitBySuit', [self.localAvId, timestamp, suitNum, pos[0], pos[1], pos[2]]) self.showToonHitBySuit(self.localAvId, timestamp) self.makeSuitRespondToToonHit(timestamp, suitNum) def hitBySuit(self, avId, timestamp, suitNum, x, y, z): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() not in ['play']: self.notify.warning('ignoring msg: av %s hit by suit' % avId) return if self.gameIsEnding: return self.notify.debug('avatar ' + ` avId ` + ' hit by a suit') if avId != self.localAvId: self.showToonHitBySuit(avId, timestamp) self.makeSuitRespondToToonHit(timestamp, suitNum) def showToonHitBySuit(self, avId, timestamp): toon = self.getAvatar(avId) if toon == None: return rng = self.toonRNGs[self.avIdList.index(avId)] curPos = toon.getPos(render) oldTrack = self.toonHitTracks[avId] if oldTrack.isPlaying(): oldTrack.finish() toon.setPos(curPos) toon.setZ(self.TOON_Z) parentNode = render.attachNewNode('mazeFlyToonParent-' + ` avId `) parentNode.setPos(toon.getPos()) toon.reparentTo(parentNode) toon.setPos(0, 0, 0) startPos = parentNode.getPos() dropShadow = toon.dropShadow.copyTo(parentNode) dropShadow.setScale(toon.dropShadow.getScale(render)) trajectory = Trajectory.Trajectory(0, Point3(0, 0, 0), Point3(0, 0, 50), gravMult=1.0) oldFlyDur = trajectory.calcTimeOfImpactOnPlane(0.0) trajectory = Trajectory.Trajectory(0, Point3(0, 0, 0), Point3(0, 0, 50), gravMult=0.55) flyDur = trajectory.calcTimeOfImpactOnPlane(0.0) avIndex = self.avIdList.index(avId) endPos = CTGG.ToonStartingPositions[avIndex] def flyFunc(t, trajectory, startPos=startPos, endPos=endPos, dur=flyDur, moveNode=parentNode, flyNode=toon): u = t / dur moveNode.setX(startPos[0] + u * (endPos[0] - startPos[0])) moveNode.setY(startPos[1] + u * (endPos[1] - startPos[1])) flyNode.setPos(trajectory.getPos(t)) flyTrack = Sequence(LerpFunctionInterval(flyFunc, fromData=0.0, toData=flyDur, duration=flyDur, extraArgs=[trajectory]), name=toon.uniqueName('hitBySuit-fly')) geomNode = toon.getGeomNode() startHpr = geomNode.getHpr() destHpr = Point3(startHpr) hRot = rng.randrange(1, 8) if rng.choice([0, 1]): hRot = -hRot destHpr.setX(destHpr[0] + hRot * 360) spinHTrack = Sequence(LerpHprInterval(geomNode, flyDur, destHpr, startHpr=startHpr), Func(geomNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinH')) parent = geomNode.getParent() rotNode = parent.attachNewNode('rotNode') geomNode.reparentTo(rotNode) rotNode.setZ(toon.getHeight() / 2.0) oldGeomNodeZ = geomNode.getZ() geomNode.setZ(-toon.getHeight() / 2.0) startHpr = rotNode.getHpr() destHpr = Point3(startHpr) pRot = rng.randrange(1, 3) if rng.choice([0, 1]): pRot = -pRot destHpr.setY(destHpr[1] + pRot * 360) spinPTrack = Sequence(LerpHprInterval(rotNode, flyDur, destHpr, startHpr=startHpr), Func(rotNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinP')) i = self.avIdList.index(avId) soundTrack = Sequence(Func(base.playSfx, self.sndTable['hitBySuit'][i]), Wait(flyDur * (2.0 / 3.0)), SoundInterval(self.sndTable['falling'][i], duration=flyDur * (1.0 / 3.0)), name=toon.uniqueName('hitBySuit-soundTrack')) def preFunc(self=self, avId=avId, toon=toon, dropShadow=dropShadow): forwardSpeed = toon.forwardSpeed rotateSpeed = toon.rotateSpeed if avId == self.localAvId: self.stopGameWalk() else: toon.stopSmooth() if forwardSpeed or rotateSpeed: toon.setSpeed(forwardSpeed, rotateSpeed) toon.dropShadow.hide() def postFunc(self=self, avId=avId, oldGeomNodeZ=oldGeomNodeZ, dropShadow=dropShadow, parentNode=parentNode): if avId == self.localAvId: base.localAvatar.setPos(endPos) if hasattr(self, 'gameWalk'): toon = base.localAvatar toon.setSpeed(0, 0) self.startGameWalk() dropShadow.removeNode() del dropShadow toon = self.getAvatar(avId) if toon: toon.dropShadow.show() geomNode = toon.getGeomNode() rotNode = geomNode.getParent() baseNode = rotNode.getParent() geomNode.reparentTo(baseNode) rotNode.removeNode() del rotNode geomNode.setZ(oldGeomNodeZ) if toon: toon.reparentTo(render) toon.setPos(endPos) parentNode.removeNode() del parentNode if avId != self.localAvId: if toon: toon.startSmooth() preFunc() slipBack = Parallel( Sequence(ActorInterval(toon, 'slip-backward', endFrame=24), Wait(CTGG.LyingDownDuration - (flyDur - oldFlyDur)), ActorInterval(toon, 'slip-backward', startFrame=24))) if toon.doId == self.localAvId: slipBack.append(SoundInterval(self.sndOof)) hitTrack = Sequence(Parallel(flyTrack, spinHTrack, spinPTrack, soundTrack), slipBack, Func(postFunc), name=toon.uniqueName('hitBySuit')) self.notify.debug('hitTrack duration = %s' % hitTrack.getDuration()) self.toonHitTracks[avId] = hitTrack hitTrack.start(globalClockDelta.localElapsedTime(timestamp)) return def updateSuitGoal(self, timestamp, inResponseToClientStamp, suitNum, goalType, goalId, x, y, z): if not self.hasLocalToon: return self.notify.debug( 'updateSuitGoal gameTime=%s timeStamp=%s cog=%s goal=%s goalId=%s (%.1f, %.1f,%.1f)' % (self.getCurrentGameTime(), timestamp, suitNum, CTGG.GoalStr[goalType], goalId, x, y, z)) cog = self.cogInfo[suitNum] cog['goal'] = goalType cog['goalId'] = goalId newPos = Point3(x, y, z) cog['pos'] = newPos suit = cog['suit'] suit.updateGoal(timestamp, inResponseToClientStamp, goalType, goalId, newPos) def spawnUpdateSuitsTask(self): self.notify.debug('spawnUpdateSuitsTask') for cogIndex in self.cogInfo: suit = self.cogInfo[cogIndex]['suit'] suit.gameStart(self.gameStartTime) taskMgr.remove(self.UPDATE_SUITS_TASK) taskMgr.add(self.updateSuitsTask, self.UPDATE_SUITS_TASK) def removeUpdateSuitsTask(self): taskMgr.remove(self.UPDATE_SUITS_TASK) def updateSuitsTask(self, task): if self.gameIsEnding: return task.done for cogIndex in self.cogInfo: suit = self.cogInfo[cogIndex]['suit'] suit.think() return task.cont def makeSuitRespondToToonHit(self, timestamp, suitNum): cog = self.cogInfo[suitNum]['suit'] cog.respondToToonHit(timestamp) def handleEnterBarrel(self, colEntry): if self.gameIsEnding: return intoName = colEntry.getIntoNodePath().getName() fromName = colEntry.getFromNodePath().getName() debugInto = intoName.split('/') debugFrom = fromName.split('/') self.notify.debug( 'handleEnterBarrel gameTime=%s %s into %s' % (self.getCurrentGameTime(), debugFrom[-1], debugInto[-1])) if 'CogThiefSphere' in intoName: parts = intoName.split('-') cogIndex = int(parts[1]) barrelName = colEntry.getFromNodePath().getName() barrelParts = barrelName.split('-') barrelIndex = int(barrelParts[1]) cog = self.cogInfo[cogIndex]['suit'] if cog.barrel == CTGG.NoBarrelCarried and barrelIndex not in self.stolenBarrels: timestamp = globalClockDelta.localToNetworkTime( globalClock.getFrameTime(), bits=32) if cog.suit: cogPos = cog.suit.getPos() collisionPos = colEntry.getContactPos(render) self.sendUpdate('cogHitBarrel', [ timestamp, cogIndex, barrelIndex, cogPos[0], cogPos[1], cogPos[2] ]) def makeCogCarryBarrel(self, timestamp, inResponseToClientStamp, cogIndex, barrelIndex, x, y, z): if not self.hasLocalToon: return if self.gameIsEnding: return self.notify.debug( 'makeCogCarryBarrel gameTime=%s timeStamp=%s cog=%s barrel=%s (%.1f, %.1f,%.1f)' % (self.getCurrentGameTime(), timestamp, cogIndex, barrelIndex, x, y, z)) barrel = self.barrels[barrelIndex] self.notify.debug('barrelPos= %s' % barrel.getPos()) cog = self.cogInfo[cogIndex]['suit'] cogPos = Point3(x, y, z) cog.makeCogCarryBarrel(timestamp, inResponseToClientStamp, barrel, barrelIndex, cogPos) def makeCogDropBarrel(self, timestamp, inResponseToClientStamp, cogIndex, barrelIndex, x, y, z): if not self.hasLocalToon: return self.notify.debug( 'makeCogDropBarrel gameTime=%s timeStamp=%s cog=%s barrel=%s (%.1f, %.1f,%.1f)' % (self.getCurrentGameTime(), timestamp, cogIndex, barrelIndex, x, y, z)) barrel = self.barrels[barrelIndex] self.notify.debug('barrelPos= %s' % barrel.getPos()) cog = self.cogInfo[cogIndex]['suit'] cogPos = Point3(x, y, z) cog.makeCogDropBarrel(timestamp, inResponseToClientStamp, barrel, barrelIndex, cogPos) def controlKeyPressed(self): if self.isToonPlayingHitTrack(self.localAvId): return if self.gameIsEnding: return if self.getCurrentGameTime( ) - self.lastTimeControlPressed > self.ControlKeyLimitTime: self.lastTimeControlPressed = self.getCurrentGameTime() self.notify.debug('controlKeyPressed') toonSD = self.toonSDs[self.localAvId] curState = toonSD.fsm.getCurrentState().getName() toon = self.getAvatar(self.localAvId) timestamp = globalClockDelta.localToNetworkTime( globalClock.getFrameTime(), bits=32) pos = toon.getPos() heading = toon.getH() self.sendUpdate( 'throwingPie', [self.localAvId, timestamp, heading, pos[0], pos[1], pos[2]]) self.showToonThrowingPie(self.localAvId, timestamp, heading, pos) def throwingPie(self, avId, timestamp, heading, x, y, z): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() not in ['play']: self.notify.warning('ignoring msg: av %s hit by suit' % avId) return self.notify.debug('avatar ' + ` avId ` + ' throwing pie') if avId != self.localAvId: pos = Point3(x, y, z) self.showToonThrowingPie(avId, timestamp, heading, pos) def showToonThrowingPie(self, avId, timestamp, heading, pos): toon = self.getAvatar(avId) if toon: tossTrack, pieTrack, flyPie = self.getTossPieInterval( toon, pos[0], pos[1], pos[2], heading, 0, 0, 0) def removePieFromTraverser(flyPie=flyPie): if base.cTrav: if flyPie: base.cTrav.removeCollider(flyPie) if avId == self.localAvId: flyPie.setTag('throwerId', str(avId)) collSphere = CollisionSphere(0, 0, 0, 0.5) collSphere.setTangible(0) name = 'PieSphere-%d' % avId collSphereName = self.uniqueName(name) collNode = CollisionNode(collSphereName) collNode.setFromCollideMask(ToontownGlobals.PieBitmask) collNode.addSolid(collSphere) colNp = flyPie.attachNewNode(collNode) colNp.show() base.cTrav.addCollider(colNp, self.pieHandler) self.accept('pieHit-' + collSphereName, self.handlePieHitting) def matchRunningAnim(toon=toon): toon.playingAnim = None toon.setSpeed(toon.forwardSpeed, toon.rotateSpeed) return newTossTrack = Sequence(tossTrack, Func(matchRunningAnim)) pieTrack = Parallel(newTossTrack, pieTrack) elapsedTime = globalClockDelta.localElapsedTime(timestamp) if elapsedTime < 16.0 / 24.0: elapsedTime = 16.0 / 24.0 pieTrack.start(elapsedTime) self.toonPieTracks[avId] = pieTrack def getTossPieInterval(self, toon, x, y, z, h, p, r, power, beginFlyIval=Sequence()): from toontown.toonbase import ToontownBattleGlobals from toontown.battle import BattleProps pie = toon.getPieModel() pie.setScale(0.9) flyPie = pie.copyTo(NodePath('a')) pieName = ToontownBattleGlobals.pieNames[toon.pieType] pieType = BattleProps.globalPropPool.getPropType(pieName) animPie = Sequence() if pieType == 'actor': animPie = ActorInterval(pie, pieName, startFrame=48) sound = loader.loadSfx('phase_3.5/audio/sfx/AA_pie_throw_only.ogg') t = power / 100.0 dist = 100 - 70 * t time = 1 + 0.5 * t proj = ProjectileInterval(None, startPos=Point3(0, 0, 0), endPos=Point3(0, dist, 0), duration=time) relVel = proj.startVel def getVelocity(toon=toon, relVel=relVel): return render.getRelativeVector(toon, relVel) * 0.6 toss = Track( (0, Sequence( Func(toon.setPosHpr, x, y, z, h, p, r), Func(pie.reparentTo, toon.rightHand), Func(pie.setPosHpr, 0, 0, 0, 0, 0, 0), Parallel( ActorInterval( toon, 'throw', startFrame=48, partName='torso'), animPie), Func(toon.loop, 'neutral'))), (16.0 / 24.0, Func(pie.detachNode))) fly = Track( (14.0 / 24.0, SoundInterval(sound, node=toon)), (16.0 / 24.0, Sequence( Func(flyPie.reparentTo, render), Func(flyPie.setPosHpr, toon, 0.52, 0.97, 2.24, 0, -45, 0), beginFlyIval, ProjectileInterval(flyPie, startVel=getVelocity, duration=6), Func(flyPie.detachNode)))) return (toss, fly, flyPie) def handlePieHitting(self, colEntry): if self.gameIsEnding: return into = colEntry.getIntoNodePath() intoName = into.getName() if 'CogThiefPieSphere' in intoName: timestamp = globalClockDelta.localToNetworkTime( globalClock.getFrameTime(), bits=32) parts = intoName.split('-') suitNum = int(parts[1]) pos = self.cogInfo[suitNum]['suit'].suit.getPos() if pos in CTGG.CogStartingPositions: self.notify.debug('Cog %d hit at starting pos %s, ignoring' % (suitNum, pos)) else: self.sendUpdate('pieHitSuit', [ self.localAvId, timestamp, suitNum, pos[0], pos[1], pos[2] ]) self.makeSuitRespondToPieHit(timestamp, suitNum) def pieHitSuit(self, avId, timestamp, suitNum, x, y, z): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() not in ['play']: self.notify.warning('ignoring msg: av %s hit by suit' % avId) return if self.gameIsEnding: return self.notify.debug('avatar ' + ` avId ` + ' hit by a suit') if avId != self.localAvId: self.makeSuitRespondToPieHit(timestamp, suitNum) def makeSuitRespondToPieHit(self, timestamp, suitNum): cog = self.cogInfo[suitNum]['suit'] cog.respondToPieHit(timestamp) def sendCogAtReturnPos(self, cogIndex, barrelIndex): timestamp = globalClockDelta.localToNetworkTime( globalClock.getFrameTime(), bits=32) self.sendUpdate('cogAtReturnPos', [timestamp, cogIndex, barrelIndex]) def markBarrelStolen(self, timestamp, inResponseToClientStamp, barrelIndex): if not self.hasLocalToon: return if barrelIndex not in self.stolenBarrels: self.stolenBarrels.append(barrelIndex) barrel = self.barrels[barrelIndex] barrel.hide() if base.config.GetBool('cog-thief-check-barrels', 1): if not base.config.GetBool('cog-thief-endless', 0): if len(self.stolenBarrels) == len(self.barrels): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) gameTime = self.local2GameTime(localStamp) self.clockStopTime = gameTime self.notify.debug('clockStopTime = %s' % gameTime) score = int(self.scoreMult * CTGG.calcScore(gameTime) + 0.5) self.rewardPanel['text'] = str(score) self.showResults() def __gameTimerExpired(self): self.notify.debug('game timer expired') self.showResults() def __startRewardCountdown(self): taskMgr.remove(self.REWARD_COUNTDOWN_TASK) taskMgr.add(self.__updateRewardCountdown, self.REWARD_COUNTDOWN_TASK) def __killRewardCountdown(self): taskMgr.remove(self.REWARD_COUNTDOWN_TASK) def __updateRewardCountdown(self, task): curTime = self.getCurrentGameTime() if self.clockStopTime is not None: if self.clockStopTime < curTime: self.notify.debug('self.clockStopTime < curTime %s %s' % (self.clockStopTime, curTime)) self.__killRewardCountdown() curTime = self.clockStopTime if curTime > CTGG.GameTime: curTime = CTGG.GameTime score = int(self.scoreMult * CTGG.calcScore(curTime) + 0.5) if not hasattr(task, 'curScore'): task.curScore = score result = Task.cont if hasattr(self, 'rewardPanel'): self.rewardPanel['text'] = str(score) if task.curScore != score: if hasattr(self, 'jarIval'): self.jarIval.finish() s = self.rewardPanel.getScale() self.jarIval = Parallel(Sequence( self.rewardPanel.scaleInterval(0.15, s * 3.0 / 4.0, blendType='easeOut'), self.rewardPanel.scaleInterval(0.15, s, blendType='easeIn')), SoundInterval(self.sndRewardTick), name='cogThiefGameRewardJarThrob') self.jarIval.start() task.curScore = score else: result = Task.done return result def startGameWalk(self): if self.useOrthoWalk: self.gameWalk.start() else: self.gameWalk.enter() self.gameWalk.fsm.request('walking') def stopGameWalk(self): if self.useOrthoWalk: self.gameWalk.stop() else: self.gameWalk.exit() def getCogThief(self, cogIndex): return self.cogInfo[cogIndex]['suit'] def isToonPlayingHitTrack(self, avId): if avId in self.toonHitTracks: track = self.toonHitTracks[avId] if track.isPlaying(): return True return False def getNumCogs(self): result = base.config.GetInt('cog-thief-num-cogs', 0) if not result: safezone = self.getSafezoneId() result = CTGG.calculateCogs(self.numPlayers, safezone) return result def getCogSpeed(self): result = 6.0 safezone = self.getSafezoneId() result = CTGG.calculateCogSpeed(self.numPlayers, safezone) return result def showResults(self): if not self.gameIsEnding: self.gameIsEnding = True for barrel in self.barrels: barrel.wrtReparentTo(render) for key in self.cogInfo: thief = self.cogInfo[key]['suit'] thief.suit.setPos(100, 0, 0) thief.suit.hide() self.__killRewardCountdown() self.stopGameWalk() numBarrelsSaved = len(self.barrels) - len(self.stolenBarrels) resultStr = '' if numBarrelsSaved == len(self.barrels): resultStr = TTLocalizer.CogThiefPerfect elif numBarrelsSaved > 1: resultStr = TTLocalizer.CogThiefBarrelsSaved % { 'num': numBarrelsSaved } elif numBarrelsSaved == 1: resultStr = TTLocalizer.CogThiefBarrelSaved % { 'num': numBarrelsSaved } else: resultStr = TTLocalizer.CogThiefNoBarrelsSaved perfectTextSubnode = hidden.attachNewNode( self.__genText(resultStr)) perfectText = hidden.attachNewNode('perfectText') perfectTextSubnode.reparentTo(perfectText) frame = self.__textGen.getCardActual() offsetY = -abs(frame[2] + frame[3]) / 2.0 perfectTextSubnode.setPos(0, 0, offsetY) perfectText.setColor(1, 0.1, 0.1, 1) def fadeFunc(t, text=perfectText): text.setColorScale(1, 1, 1, t) def destroyText(text=perfectText): text.removeNode() def safeGameOver(self=self): if not self.frameworkFSM.isInternalStateInFlux(): self.gameOver() textTrack = Sequence( Func(perfectText.reparentTo, aspect2d), Parallel( LerpScaleInterval(perfectText, duration=0.5, scale=0.3, startScale=0.0), LerpFunctionInterval(fadeFunc, fromData=0.0, toData=1.0, duration=0.5)), Wait(2.0), Parallel( LerpScaleInterval(perfectText, duration=0.5, scale=1.0), LerpFunctionInterval(fadeFunc, fromData=1.0, toData=0.0, duration=0.5, blendType='easeIn')), Func(destroyText), WaitInterval(0.5), Func(safeGameOver)) if numBarrelsSaved == len(self.barrels): soundTrack = SoundInterval(self.sndPerfect) else: soundTrack = Sequence() self.resultIval = Parallel(textTrack, soundTrack) self.resultIval.start() def __genText(self, text): self.__textGen.setText(text) return self.__textGen.generate() def getIntroTrack(self): base.camera.setPosHpr(0, -13.66, 13.59, 0, -51.6, 0) result = Sequence( Wait(2), LerpPosHprInterval(base.camera, 13, Point3(self.cameraTopView[0], self.cameraTopView[1], self.cameraTopView[2]), Point3(self.cameraTopView[3], self.cameraTopView[4], self.cameraTopView[5]), blendType='easeIn')) return result
def load(self): self.notify.debug('load') DistributedMinigame.load(self) self.music = base.loadMusic('phase_4/audio/bgm/MG_CogThief.ogg') self.initCogInfo() for barrelIndex in range(CTGG.NumBarrels): barrel = loader.loadModel('phase_4/models/minigames/cogthief_game_gagTank') barrel.setPos(CTGG.BarrelStartingPositions[barrelIndex]) barrel.setScale(self.BarrelScale) barrel.reparentTo(render) barrel.setTag('barrelIndex', str(barrelIndex)) collSphere = CollisionSphere(0, 0, 0, 4) collSphere.setTangible(0) name = 'BarrelSphere-%d' % barrelIndex collSphereName = self.uniqueName(name) collNode = CollisionNode(collSphereName) collNode.setFromCollideMask(CTGG.BarrelBitmask) collNode.addSolid(collSphere) colNp = barrel.attachNewNode(collNode) handler = CollisionHandlerEvent() handler.setInPattern('barrelHit-%fn') base.cTrav.addCollider(colNp, handler) self.accept('barrelHit-' + collSphereName, self.handleEnterBarrel) nodeToHide = '**/gagMoneyTen' if barrelIndex % 2: nodeToHide = '**/gagMoneyFive' iconToHide = barrel.find(nodeToHide) if not iconToHide.isEmpty(): iconToHide.hide() self.barrels.append(barrel) self.gameBoard = loader.loadModel('phase_4/models/minigames/cogthief_game') self.gameBoard.find('**/floor_TT').hide() self.gameBoard.find('**/floor_DD').hide() self.gameBoard.find('**/floor_DG').hide() self.gameBoard.find('**/floor_MM').hide() self.gameBoard.find('**/floor_BR').hide() self.gameBoard.find('**/floor_DL').hide() zone = self.getSafezoneId() if zone == ToontownGlobals.ToontownCentral: self.gameBoard.find('**/floor_TT').show() elif zone == ToontownGlobals.DonaldsDock: self.gameBoard.find('**/floor_DD').show() elif zone == ToontownGlobals.DaisyGardens: self.gameBoard.find('**/floor_DG').show() elif zone == ToontownGlobals.MinniesMelodyland: self.gameBoard.find('**/floor_MM').show() elif zone == ToontownGlobals.TheBrrrgh: self.gameBoard.find('**/floor_BR').show() elif zone == ToontownGlobals.DonaldsDreamland: self.gameBoard.find('**/floor_DL').show() else: self.gameBoard.find('**/floor_TT').show() self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) self.toonSDs = {} avId = self.localAvId toonSD = CogThiefGameToonSD.CogThiefGameToonSD(avId, self) self.toonSDs[avId] = toonSD toonSD.load() self.loadCogs() self.toonHitTracks = {} self.toonPieTracks = {} self.sndOof = base.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') self.sndRewardTick = base.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg') self.sndPerfect = base.loadSfx('phase_4/audio/sfx/ring_perfect.ogg') self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.hide() purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui') self.jarImage = purchaseModels.find('**/Jar') self.jarImage.reparentTo(hidden) self.rewardPanel = DirectLabel(parent=hidden, relief=None, pos=(1.16, 0.0, 0.45), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -0.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage) self.rewardPanelTitle = DirectLabel(parent=self.rewardPanel, relief=None, pos=(0, 0, 0.06), scale=0.08, text=TTLocalizer.CannonGameReward, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1)) self.initGameWalk() return
class DistributedCogThiefGame(DistributedMinigame): notify = directNotify.newCategory('DistributedCogThiefGame') ToonSpeed = CTGG.ToonSpeed StageHalfWidth = 200.0 StageHalfHeight = 100.0 BarrelScale = 0.25 TOON_Z = 0 UPDATE_SUITS_TASK = 'CogThiefGameUpdateSuitsTask' REWARD_COUNTDOWN_TASK = 'cogThiefGameRewardCountdown' ControlKeyLimitTime = 1.0 def __init__(self, cr): DistributedMinigame.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedCogThiefGame', [State.State('off', self.enterOff, self.exitOff, ['play']), State.State('play', self.enterPlay, self.exitPlay, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.cameraTopView = (0, 0, 55, 0, -90.0, 0) self.barrels = [] self.cogInfo = {} self.lastTimeControlPressed = 0 self.stolenBarrels = [] self.resultIval = None self.gameIsEnding = False self.__textGen = TextNode('cogThiefGame') self.__textGen.setFont(ToontownGlobals.getSignFont()) self.__textGen.setAlign(TextNode.ACenter) return def getTitle(self): return TTLocalizer.CogThiefGameTitle def getInstructions(self): return TTLocalizer.CogThiefGameInstructions def getMaxDuration(self): return 0 def load(self): self.notify.debug('load') DistributedMinigame.load(self) self.music = base.loadMusic('phase_4/audio/bgm/MG_CogThief.ogg') self.initCogInfo() for barrelIndex in range(CTGG.NumBarrels): barrel = loader.loadModel('phase_4/models/minigames/cogthief_game_gagTank') barrel.setPos(CTGG.BarrelStartingPositions[barrelIndex]) barrel.setScale(self.BarrelScale) barrel.reparentTo(render) barrel.setTag('barrelIndex', str(barrelIndex)) collSphere = CollisionSphere(0, 0, 0, 4) collSphere.setTangible(0) name = 'BarrelSphere-%d' % barrelIndex collSphereName = self.uniqueName(name) collNode = CollisionNode(collSphereName) collNode.setFromCollideMask(CTGG.BarrelBitmask) collNode.addSolid(collSphere) colNp = barrel.attachNewNode(collNode) handler = CollisionHandlerEvent() handler.setInPattern('barrelHit-%fn') base.cTrav.addCollider(colNp, handler) self.accept('barrelHit-' + collSphereName, self.handleEnterBarrel) nodeToHide = '**/gagMoneyTen' if barrelIndex % 2: nodeToHide = '**/gagMoneyFive' iconToHide = barrel.find(nodeToHide) if not iconToHide.isEmpty(): iconToHide.hide() self.barrels.append(barrel) self.gameBoard = loader.loadModel('phase_4/models/minigames/cogthief_game') self.gameBoard.find('**/floor_TT').hide() self.gameBoard.find('**/floor_DD').hide() self.gameBoard.find('**/floor_DG').hide() self.gameBoard.find('**/floor_MM').hide() self.gameBoard.find('**/floor_BR').hide() self.gameBoard.find('**/floor_DL').hide() zone = self.getSafezoneId() if zone == ToontownGlobals.ToontownCentral: self.gameBoard.find('**/floor_TT').show() elif zone == ToontownGlobals.DonaldsDock: self.gameBoard.find('**/floor_DD').show() elif zone == ToontownGlobals.DaisyGardens: self.gameBoard.find('**/floor_DG').show() elif zone == ToontownGlobals.MinniesMelodyland: self.gameBoard.find('**/floor_MM').show() elif zone == ToontownGlobals.TheBrrrgh: self.gameBoard.find('**/floor_BR').show() elif zone == ToontownGlobals.DonaldsDreamland: self.gameBoard.find('**/floor_DL').show() else: self.gameBoard.find('**/floor_TT').show() self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) self.toonSDs = {} avId = self.localAvId toonSD = CogThiefGameToonSD.CogThiefGameToonSD(avId, self) self.toonSDs[avId] = toonSD toonSD.load() self.loadCogs() self.toonHitTracks = {} self.toonPieTracks = {} self.sndOof = base.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') self.sndRewardTick = base.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg') self.sndPerfect = base.loadSfx('phase_4/audio/sfx/ring_perfect.ogg') self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.hide() purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui') self.jarImage = purchaseModels.find('**/Jar') self.jarImage.reparentTo(hidden) self.rewardPanel = DirectLabel(parent=hidden, relief=None, pos=(1.16, 0.0, 0.45), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -0.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage) self.rewardPanelTitle = DirectLabel(parent=self.rewardPanel, relief=None, pos=(0, 0, 0.06), scale=0.08, text=TTLocalizer.CannonGameReward, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1)) self.initGameWalk() return def unload(self): self.notify.debug('unload') DistributedMinigame.unload(self) del self.music self.removeChildGameFSM(self.gameFSM) del self.gameFSM self.gameBoard.removeNode() del self.gameBoard for barrel in self.barrels: barrel.removeNode() del self.barrels for avId in self.toonSDs.keys(): toonSD = self.toonSDs[avId] toonSD.unload() del self.toonSDs self.timer.destroy() del self.timer self.rewardPanel.destroy() del self.rewardPanel self.jarImage.removeNode() del self.jarImage del self.sndRewardTick def onstage(self): self.notify.debug('onstage') DistributedMinigame.onstage(self) self.gameBoard.reparentTo(render) lt = base.localAvatar lt.reparentTo(render) self.__placeToon(self.localAvId) lt.setSpeed(0, 0) self.moveCameraToTop() toonSD = self.toonSDs[self.localAvId] toonSD.enter() toonSD.fsm.request('normal') self.stopGameWalk() for cogIndex in xrange(self.getNumCogs()): suit = self.cogInfo[cogIndex]['suit'].suit pos = self.cogInfo[cogIndex]['pos'] suit.reparentTo(self.gameBoard) suit.setPos(pos) for avId in self.avIdList: self.toonHitTracks[avId] = Wait(0.1) self.toonRNGs = [] for i in xrange(self.numPlayers): self.toonRNGs.append(RandomNumGen.RandomNumGen(self.randomNumGen)) self.sndTable = {'hitBySuit': [None] * self.numPlayers, 'falling': [None] * self.numPlayers} for i in xrange(self.numPlayers): self.sndTable['hitBySuit'][i] = base.loadSfx('phase_4/audio/sfx/MG_Tag_C.ogg') self.sndTable['falling'][i] = base.loadSfx('phase_4/audio/sfx/MG_cannon_whizz.ogg') base.playMusic(self.music, looping=1, volume=0.8) self.introTrack = self.getIntroTrack() self.introTrack.start() return def offstage(self): self.notify.debug('offstage') self.gameBoard.hide() self.music.stop() for barrel in self.barrels: barrel.hide() for avId in self.toonSDs.keys(): self.toonSDs[avId].exit() for avId in self.avIdList: av = self.getAvatar(avId) if av: av.resetLOD() self.timer.reparentTo(hidden) self.rewardPanel.reparentTo(hidden) if self.introTrack.isPlaying(): self.introTrack.finish() del self.introTrack DistributedMinigame.offstage(self) def handleDisabledAvatar(self, avId): self.notify.debug('handleDisabledAvatar') self.notify.debug('avatar ' + str(avId) + ' disabled') self.toonSDs[avId].exit(unexpectedExit=True) del self.toonSDs[avId] DistributedMinigame.handleDisabledAvatar(self, avId) def setGameReady(self): if not self.hasLocalToon: return self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.reparentTo(render) self.__placeToon(avId) toon.useLOD(1000) toonSD = CogThiefGameToonSD.CogThiefGameToonSD(avId, self) self.toonSDs[avId] = toonSD toonSD.load() toonSD.enter() toonSD.fsm.request('normal') toon.startSmooth() def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug('setGameStart') DistributedMinigame.setGameStart(self, timestamp) if not base.config.GetBool('cog-thief-endless', 0): self.timer.show() self.timer.countdown(CTGG.GameTime, self.__gameTimerExpired) self.clockStopTime = None self.rewardPanel.reparentTo(aspect2d) self.scoreMult = MinigameGlobals.getScoreMult(self.cr.playGame.hood.id) self.__startRewardCountdown() if self.introTrack.isPlaying(): self.introTrack.finish() self.gameFSM.request('play') return def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterPlay(self): self.notify.debug('enterPlay') self.startGameWalk() self.spawnUpdateSuitsTask() self.accept('control', self.controlKeyPressed) self.pieHandler = CollisionHandlerEvent() self.pieHandler.setInPattern('pieHit-%fn') def exitPlay(self): self.ignore('control') if self.resultIval and self.resultIval.isPlaying(): self.resultIval.finish() self.resultIval = None return def enterCleanup(self): self.__killRewardCountdown() if hasattr(self, 'jarIval'): self.jarIval.finish() del self.jarIval for key in self.toonHitTracks: ival = self.toonHitTracks[key] if ival.isPlaying(): ival.finish() self.toonHitTracks = {} for key in self.toonPieTracks: ival = self.toonPieTracks[key] if ival.isPlaying(): ival.finish() self.toonPieTracks = {} for key in self.cogInfo: cogThief = self.cogInfo[key]['suit'] cogThief.cleanup() self.removeUpdateSuitsTask() self.notify.debug('enterCleanup') def exitCleanup(self): pass def __placeToon(self, avId): toon = self.getAvatar(avId) if toon: index = self.avIdList.index(avId) toon.setPos(CTGG.ToonStartingPositions[index]) toon.setHpr(0, 0, 0) def moveCameraToTop(self): camera.reparentTo(render) p = self.cameraTopView camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5]) base.camLens.setMinFov(46/(4./3.)) camera.setZ(camera.getZ() + base.config.GetFloat('cog-thief-z-camera-adjust', 0.0)) def destroyGameWalk(self): self.notify.debug('destroyOrthoWalk') self.gameWalk.destroy() del self.gameWalk def initGameWalk(self): self.notify.debug('startOrthoWalk') def doCollisions(oldPos, newPos, self = self): x = bound(newPos[0], CTGG.StageHalfWidth, -CTGG.StageHalfWidth) y = bound(newPos[1], CTGG.StageHalfHeight, -CTGG.StageHalfHeight) newPos.setX(x) newPos.setY(y) return newPos orthoDrive = OrthoDrive(self.ToonSpeed, customCollisionCallback=doCollisions, instantTurn=True) self.gameWalk = OrthoWalk(orthoDrive, broadcast=not self.isSinglePlayer()) def initCogInfo(self): for cogIndex in xrange(self.getNumCogs()): self.cogInfo[cogIndex] = {'pos': Point3(CTGG.CogStartingPositions[cogIndex]), 'goal': CTGG.NoGoal, 'goalId': CTGG.InvalidGoalId, 'suit': None} return def loadCogs(self): suitTypes = ['ds', 'ac', 'bc', 'ms'] for suitIndex in xrange(self.getNumCogs()): st = self.randomNumGen.choice(suitTypes) suit = CogThief.CogThief(suitIndex, st, self, self.getCogSpeed()) self.cogInfo[suitIndex]['suit'] = suit def handleEnterSphere(self, colEntry): if self.gameIsEnding: return intoName = colEntry.getIntoNodePath().getName() fromName = colEntry.getFromNodePath().getName() debugInto = intoName.split('/') debugFrom = fromName.split('/') self.notify.debug('handleEnterSphere gametime=%s %s into %s' % (self.getCurrentGameTime(), debugFrom[-1], debugInto[-1])) intoName = colEntry.getIntoNodePath().getName() if 'CogThiefSphere' in intoName: parts = intoName.split('-') suitNum = int(parts[1]) self.localToonHitBySuit(suitNum) def localToonHitBySuit(self, suitNum): self.notify.debug('localToonHitBySuit %d' % suitNum) timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32) pos = self.cogInfo[suitNum]['suit'].suit.getPos() self.sendUpdate('hitBySuit', [self.localAvId, timestamp, suitNum, pos[0], pos[1], pos[2]]) self.showToonHitBySuit(self.localAvId, timestamp) self.makeSuitRespondToToonHit(timestamp, suitNum) def hitBySuit(self, avId, timestamp, suitNum, x, y, z): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() not in ['play']: self.notify.warning('ignoring msg: av %s hit by suit' % avId) return if self.gameIsEnding: return self.notify.debug('avatar ' + `avId` + ' hit by a suit') if avId != self.localAvId: self.showToonHitBySuit(avId, timestamp) self.makeSuitRespondToToonHit(timestamp, suitNum) def showToonHitBySuit(self, avId, timestamp): toon = self.getAvatar(avId) if toon == None: return rng = self.toonRNGs[self.avIdList.index(avId)] curPos = toon.getPos(render) oldTrack = self.toonHitTracks[avId] if oldTrack.isPlaying(): oldTrack.finish() toon.setPos(curPos) toon.setZ(self.TOON_Z) parentNode = render.attachNewNode('mazeFlyToonParent-' + `avId`) parentNode.setPos(toon.getPos()) toon.reparentTo(parentNode) toon.setPos(0, 0, 0) startPos = parentNode.getPos() dropShadow = toon.dropShadow.copyTo(parentNode) dropShadow.setScale(toon.dropShadow.getScale(render)) trajectory = Trajectory.Trajectory(0, Point3(0, 0, 0), Point3(0, 0, 50), gravMult=1.0) oldFlyDur = trajectory.calcTimeOfImpactOnPlane(0.0) trajectory = Trajectory.Trajectory(0, Point3(0, 0, 0), Point3(0, 0, 50), gravMult=0.55) flyDur = trajectory.calcTimeOfImpactOnPlane(0.0) avIndex = self.avIdList.index(avId) endPos = CTGG.ToonStartingPositions[avIndex] def flyFunc(t, trajectory, startPos = startPos, endPos = endPos, dur = flyDur, moveNode = parentNode, flyNode = toon): u = t / dur moveNode.setX(startPos[0] + u * (endPos[0] - startPos[0])) moveNode.setY(startPos[1] + u * (endPos[1] - startPos[1])) flyNode.setPos(trajectory.getPos(t)) flyTrack = Sequence(LerpFunctionInterval(flyFunc, fromData=0.0, toData=flyDur, duration=flyDur, extraArgs=[trajectory]), name=toon.uniqueName('hitBySuit-fly')) geomNode = toon.getGeomNode() startHpr = geomNode.getHpr() destHpr = Point3(startHpr) hRot = rng.randrange(1, 8) if rng.choice([0, 1]): hRot = -hRot destHpr.setX(destHpr[0] + hRot * 360) spinHTrack = Sequence(LerpHprInterval(geomNode, flyDur, destHpr, startHpr=startHpr), Func(geomNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinH')) parent = geomNode.getParent() rotNode = parent.attachNewNode('rotNode') geomNode.reparentTo(rotNode) rotNode.setZ(toon.getHeight() / 2.0) oldGeomNodeZ = geomNode.getZ() geomNode.setZ(-toon.getHeight() / 2.0) startHpr = rotNode.getHpr() destHpr = Point3(startHpr) pRot = rng.randrange(1, 3) if rng.choice([0, 1]): pRot = -pRot destHpr.setY(destHpr[1] + pRot * 360) spinPTrack = Sequence(LerpHprInterval(rotNode, flyDur, destHpr, startHpr=startHpr), Func(rotNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinP')) i = self.avIdList.index(avId) soundTrack = Sequence(Func(base.playSfx, self.sndTable['hitBySuit'][i]), Wait(flyDur * (2.0 / 3.0)), SoundInterval(self.sndTable['falling'][i], duration=flyDur * (1.0 / 3.0)), name=toon.uniqueName('hitBySuit-soundTrack')) def preFunc(self = self, avId = avId, toon = toon, dropShadow = dropShadow): forwardSpeed = toon.forwardSpeed rotateSpeed = toon.rotateSpeed if avId == self.localAvId: self.stopGameWalk() else: toon.stopSmooth() if forwardSpeed or rotateSpeed: toon.setSpeed(forwardSpeed, rotateSpeed) toon.dropShadow.hide() def postFunc(self = self, avId = avId, oldGeomNodeZ = oldGeomNodeZ, dropShadow = dropShadow, parentNode = parentNode): if avId == self.localAvId: base.localAvatar.setPos(endPos) if hasattr(self, 'gameWalk'): toon = base.localAvatar toon.setSpeed(0, 0) self.startGameWalk() dropShadow.removeNode() del dropShadow toon = self.getAvatar(avId) if toon: toon.dropShadow.show() geomNode = toon.getGeomNode() rotNode = geomNode.getParent() baseNode = rotNode.getParent() geomNode.reparentTo(baseNode) rotNode.removeNode() del rotNode geomNode.setZ(oldGeomNodeZ) if toon: toon.reparentTo(render) toon.setPos(endPos) parentNode.removeNode() del parentNode if avId != self.localAvId: if toon: toon.startSmooth() preFunc() slipBack = Parallel(Sequence(ActorInterval(toon, 'slip-backward', endFrame=24), Wait(CTGG.LyingDownDuration - (flyDur - oldFlyDur)), ActorInterval(toon, 'slip-backward', startFrame=24))) if toon.doId == self.localAvId: slipBack.append(SoundInterval(self.sndOof)) hitTrack = Sequence(Parallel(flyTrack, spinHTrack, spinPTrack, soundTrack), slipBack, Func(postFunc), name=toon.uniqueName('hitBySuit')) self.notify.debug('hitTrack duration = %s' % hitTrack.getDuration()) self.toonHitTracks[avId] = hitTrack hitTrack.start(globalClockDelta.localElapsedTime(timestamp)) return def updateSuitGoal(self, timestamp, inResponseToClientStamp, suitNum, goalType, goalId, x, y, z): if not self.hasLocalToon: return self.notify.debug('updateSuitGoal gameTime=%s timeStamp=%s cog=%s goal=%s goalId=%s (%.1f, %.1f,%.1f)' % (self.getCurrentGameTime(), timestamp, suitNum, CTGG.GoalStr[goalType], goalId, x, y, z)) cog = self.cogInfo[suitNum] cog['goal'] = goalType cog['goalId'] = goalId newPos = Point3(x, y, z) cog['pos'] = newPos suit = cog['suit'] suit.updateGoal(timestamp, inResponseToClientStamp, goalType, goalId, newPos) def spawnUpdateSuitsTask(self): self.notify.debug('spawnUpdateSuitsTask') for cogIndex in self.cogInfo: suit = self.cogInfo[cogIndex]['suit'] suit.gameStart(self.gameStartTime) taskMgr.remove(self.UPDATE_SUITS_TASK) taskMgr.add(self.updateSuitsTask, self.UPDATE_SUITS_TASK) def removeUpdateSuitsTask(self): taskMgr.remove(self.UPDATE_SUITS_TASK) def updateSuitsTask(self, task): if self.gameIsEnding: return task.done for cogIndex in self.cogInfo: suit = self.cogInfo[cogIndex]['suit'] suit.think() return task.cont def makeSuitRespondToToonHit(self, timestamp, suitNum): cog = self.cogInfo[suitNum]['suit'] cog.respondToToonHit(timestamp) def handleEnterBarrel(self, colEntry): if self.gameIsEnding: return intoName = colEntry.getIntoNodePath().getName() fromName = colEntry.getFromNodePath().getName() debugInto = intoName.split('/') debugFrom = fromName.split('/') self.notify.debug('handleEnterBarrel gameTime=%s %s into %s' % (self.getCurrentGameTime(), debugFrom[-1], debugInto[-1])) if 'CogThiefSphere' in intoName: parts = intoName.split('-') cogIndex = int(parts[1]) barrelName = colEntry.getFromNodePath().getName() barrelParts = barrelName.split('-') barrelIndex = int(barrelParts[1]) cog = self.cogInfo[cogIndex]['suit'] if cog.barrel == CTGG.NoBarrelCarried and barrelIndex not in self.stolenBarrels: timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32) if cog.suit: cogPos = cog.suit.getPos() collisionPos = colEntry.getContactPos(render) if (cogPos - collisionPos).length() > 4: import pdb pdb.set_trace() self.sendUpdate('cogHitBarrel', [timestamp, cogIndex, barrelIndex, cogPos[0], cogPos[1], cogPos[2]]) def makeCogCarryBarrel(self, timestamp, inResponseToClientStamp, cogIndex, barrelIndex, x, y, z): if not self.hasLocalToon: return if self.gameIsEnding: return self.notify.debug('makeCogCarryBarrel gameTime=%s timeStamp=%s cog=%s barrel=%s (%.1f, %.1f,%.1f)' % (self.getCurrentGameTime(), timestamp, cogIndex, barrelIndex, x, y, z)) barrel = self.barrels[barrelIndex] self.notify.debug('barrelPos= %s' % barrel.getPos()) cog = self.cogInfo[cogIndex]['suit'] cogPos = Point3(x, y, z) cog.makeCogCarryBarrel(timestamp, inResponseToClientStamp, barrel, barrelIndex, cogPos) def makeCogDropBarrel(self, timestamp, inResponseToClientStamp, cogIndex, barrelIndex, x, y, z): if not self.hasLocalToon: return self.notify.debug('makeCogDropBarrel gameTime=%s timeStamp=%s cog=%s barrel=%s (%.1f, %.1f,%.1f)' % (self.getCurrentGameTime(), timestamp, cogIndex, barrelIndex, x, y, z)) barrel = self.barrels[barrelIndex] self.notify.debug('barrelPos= %s' % barrel.getPos()) cog = self.cogInfo[cogIndex]['suit'] cogPos = Point3(x, y, z) cog.makeCogDropBarrel(timestamp, inResponseToClientStamp, barrel, barrelIndex, cogPos) def controlKeyPressed(self): if self.isToonPlayingHitTrack(self.localAvId): return if self.gameIsEnding: return if self.getCurrentGameTime() - self.lastTimeControlPressed > self.ControlKeyLimitTime: self.lastTimeControlPressed = self.getCurrentGameTime() self.notify.debug('controlKeyPressed') toonSD = self.toonSDs[self.localAvId] curState = toonSD.fsm.getCurrentState().getName() toon = self.getAvatar(self.localAvId) timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32) pos = toon.getPos() heading = toon.getH() self.sendUpdate('throwingPie', [self.localAvId, timestamp, heading, pos[0], pos[1], pos[2]]) self.showToonThrowingPie(self.localAvId, timestamp, heading, pos) def throwingPie(self, avId, timestamp, heading, x, y, z): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() not in ['play']: self.notify.warning('ignoring msg: av %s hit by suit' % avId) return self.notify.debug('avatar ' + `avId` + ' throwing pie') if avId != self.localAvId: pos = Point3(x, y, z) self.showToonThrowingPie(avId, timestamp, heading, pos) def showToonThrowingPie(self, avId, timestamp, heading, pos): toon = self.getAvatar(avId) if toon: tossTrack, pieTrack, flyPie = self.getTossPieInterval(toon, pos[0], pos[1], pos[2], heading, 0, 0, 0) def removePieFromTraverser(flyPie = flyPie): if base.cTrav: if flyPie: base.cTrav.removeCollider(flyPie) if avId == self.localAvId: flyPie.setTag('throwerId', str(avId)) collSphere = CollisionSphere(0, 0, 0, 0.5) collSphere.setTangible(0) name = 'PieSphere-%d' % avId collSphereName = self.uniqueName(name) collNode = CollisionNode(collSphereName) collNode.setFromCollideMask(ToontownGlobals.PieBitmask) collNode.addSolid(collSphere) colNp = flyPie.attachNewNode(collNode) colNp.show() base.cTrav.addCollider(colNp, self.pieHandler) self.accept('pieHit-' + collSphereName, self.handlePieHitting) def matchRunningAnim(toon = toon): toon.playingAnim = None toon.setSpeed(toon.forwardSpeed, toon.rotateSpeed) return newTossTrack = Sequence(tossTrack, Func(matchRunningAnim)) pieTrack = Parallel(newTossTrack, pieTrack) elapsedTime = globalClockDelta.localElapsedTime(timestamp) if elapsedTime < 16.0 / 24.0: elapsedTime = 16.0 / 24.0 pieTrack.start(elapsedTime) self.toonPieTracks[avId] = pieTrack def getTossPieInterval(self, toon, x, y, z, h, p, r, power, beginFlyIval = Sequence()): from toontown.toonbase import ToontownBattleGlobals from toontown.battle import BattleProps pie = toon.getPieModel() pie.setScale(0.9) flyPie = pie.copyTo(NodePath('a')) pieName = ToontownBattleGlobals.pieNames[toon.pieType] pieType = BattleProps.globalPropPool.getPropType(pieName) animPie = Sequence() if pieType == 'actor': animPie = ActorInterval(pie, pieName, startFrame=48) sound = loader.loadSfx('phase_3.5/audio/sfx/AA_pie_throw_only.ogg') t = power / 100.0 dist = 100 - 70 * t time = 1 + 0.5 * t proj = ProjectileInterval(None, startPos=Point3(0, 0, 0), endPos=Point3(0, dist, 0), duration=time) relVel = proj.startVel def getVelocity(toon = toon, relVel = relVel): return render.getRelativeVector(toon, relVel) * 0.6 toss = Track((0, Sequence(Func(toon.setPosHpr, x, y, z, h, p, r), Func(pie.reparentTo, toon.rightHand), Func(pie.setPosHpr, 0, 0, 0, 0, 0, 0), Parallel(ActorInterval(toon, 'throw', startFrame=48, partName='torso'), animPie), Func(toon.loop, 'neutral'))), (16.0 / 24.0, Func(pie.detachNode))) fly = Track((14.0 / 24.0, SoundInterval(sound, node=toon)), (16.0 / 24.0, Sequence(Func(flyPie.reparentTo, render), Func(flyPie.setPosHpr, toon, 0.52, 0.97, 2.24, 0, -45, 0), beginFlyIval, ProjectileInterval(flyPie, startVel=getVelocity, duration=6), Func(flyPie.detachNode)))) return (toss, fly, flyPie) def handlePieHitting(self, colEntry): if self.gameIsEnding: return into = colEntry.getIntoNodePath() intoName = into.getName() if 'CogThiefPieSphere' in intoName: timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32) parts = intoName.split('-') suitNum = int(parts[1]) pos = self.cogInfo[suitNum]['suit'].suit.getPos() if pos in CTGG.CogStartingPositions: self.notify.debug('Cog %d hit at starting pos %s, ignoring' % (suitNum, pos)) else: self.sendUpdate('pieHitSuit', [self.localAvId, timestamp, suitNum, pos[0], pos[1], pos[2]]) self.makeSuitRespondToPieHit(timestamp, suitNum) def pieHitSuit(self, avId, timestamp, suitNum, x, y, z): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() not in ['play']: self.notify.warning('ignoring msg: av %s hit by suit' % avId) return if self.gameIsEnding: return self.notify.debug('avatar ' + `avId` + ' hit by a suit') if avId != self.localAvId: self.makeSuitRespondToPieHit(timestamp, suitNum) def makeSuitRespondToPieHit(self, timestamp, suitNum): cog = self.cogInfo[suitNum]['suit'] cog.respondToPieHit(timestamp) def sendCogAtReturnPos(self, cogIndex, barrelIndex): timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32) self.sendUpdate('cogAtReturnPos', [timestamp, cogIndex, barrelIndex]) def markBarrelStolen(self, timestamp, inResponseToClientStamp, barrelIndex): if not self.hasLocalToon: return if barrelIndex not in self.stolenBarrels: self.stolenBarrels.append(barrelIndex) barrel = self.barrels[barrelIndex] barrel.hide() if base.config.GetBool('cog-thief-check-barrels', 1): if not base.config.GetBool('cog-thief-endless', 0): if len(self.stolenBarrels) == len(self.barrels): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) gameTime = self.local2GameTime(localStamp) self.clockStopTime = gameTime self.notify.debug('clockStopTime = %s' % gameTime) score = int(self.scoreMult * CTGG.calcScore(gameTime) + 0.5) self.rewardPanel['text'] = str(score) self.showResults() def __gameTimerExpired(self): self.notify.debug('game timer expired') self.showResults() def __startRewardCountdown(self): taskMgr.remove(self.REWARD_COUNTDOWN_TASK) taskMgr.add(self.__updateRewardCountdown, self.REWARD_COUNTDOWN_TASK) def __killRewardCountdown(self): taskMgr.remove(self.REWARD_COUNTDOWN_TASK) def __updateRewardCountdown(self, task): curTime = self.getCurrentGameTime() if self.clockStopTime is not None: if self.clockStopTime < curTime: self.notify.debug('self.clockStopTime < curTime %s %s' % (self.clockStopTime, curTime)) self.__killRewardCountdown() curTime = self.clockStopTime if curTime > CTGG.GameTime: curTime = CTGG.GameTime score = int(self.scoreMult * CTGG.calcScore(curTime) + 0.5) if not hasattr(task, 'curScore'): task.curScore = score result = Task.cont if hasattr(self, 'rewardPanel'): self.rewardPanel['text'] = str(score) if task.curScore != score: if hasattr(self, 'jarIval'): self.jarIval.finish() s = self.rewardPanel.getScale() self.jarIval = Parallel(Sequence(self.rewardPanel.scaleInterval(0.15, s * 3.0 / 4.0, blendType='easeOut'), self.rewardPanel.scaleInterval(0.15, s, blendType='easeIn')), SoundInterval(self.sndRewardTick), name='cogThiefGameRewardJarThrob') self.jarIval.start() task.curScore = score else: result = Task.done return result def startGameWalk(self): self.gameWalk.start() def stopGameWalk(self): self.gameWalk.stop() def getCogThief(self, cogIndex): return self.cogInfo[cogIndex]['suit'] def isToonPlayingHitTrack(self, avId): if avId in self.toonHitTracks: track = self.toonHitTracks[avId] if track.isPlaying(): return True return False def getNumCogs(self): result = base.config.GetInt('cog-thief-num-cogs', 0) if not result: safezone = self.getSafezoneId() result = CTGG.calculateCogs(self.numPlayers, safezone) return result def getCogSpeed(self): result = 6.0 safezone = self.getSafezoneId() result = CTGG.calculateCogSpeed(self.numPlayers, safezone) return result def showResults(self): if not self.gameIsEnding: self.gameIsEnding = True for barrel in self.barrels: barrel.wrtReparentTo(render) for key in self.cogInfo: thief = self.cogInfo[key]['suit'] thief.suit.setPos(100, 0, 0) thief.suit.hide() self.__killRewardCountdown() self.stopGameWalk() numBarrelsSaved = len(self.barrels) - len(self.stolenBarrels) resultStr = '' if numBarrelsSaved == len(self.barrels): resultStr = TTLocalizer.CogThiefPerfect elif numBarrelsSaved > 1: resultStr = TTLocalizer.CogThiefBarrelsSaved % {'num': numBarrelsSaved} elif numBarrelsSaved == 1: resultStr = TTLocalizer.CogThiefBarrelSaved % {'num': numBarrelsSaved} else: resultStr = TTLocalizer.CogThiefNoBarrelsSaved perfectTextSubnode = hidden.attachNewNode(self.__genText(resultStr)) perfectText = hidden.attachNewNode('perfectText') perfectTextSubnode.reparentTo(perfectText) frame = self.__textGen.getCardActual() offsetY = -abs(frame[2] + frame[3]) / 2.0 perfectTextSubnode.setPos(0, 0, offsetY) perfectText.setColor(1, 0.1, 0.1, 1) def fadeFunc(t, text = perfectText): text.setColorScale(1, 1, 1, t) def destroyText(text = perfectText): text.removeNode() def safeGameOver(self = self): if not self.frameworkFSM.isInternalStateInFlux(): self.gameOver() textTrack = Sequence(Func(perfectText.reparentTo, aspect2d), Parallel(LerpScaleInterval(perfectText, duration=0.5, scale=0.3, startScale=0.0), LerpFunctionInterval(fadeFunc, fromData=0.0, toData=1.0, duration=0.5)), Wait(2.0), Parallel(LerpScaleInterval(perfectText, duration=0.5, scale=1.0), LerpFunctionInterval(fadeFunc, fromData=1.0, toData=0.0, duration=0.5, blendType='easeIn')), Func(destroyText), WaitInterval(0.5), Func(safeGameOver)) if numBarrelsSaved == len(self.barrels): soundTrack = SoundInterval(self.sndPerfect) else: soundTrack = Sequence() self.resultIval = Parallel(textTrack, soundTrack) self.resultIval.start() def __genText(self, text): self.__textGen.setText(text) return self.__textGen.generate() def getIntroTrack(self): base.camera.setPosHpr(0, -13.66, 13.59, 0, -51.6, 0) result = Sequence(Wait(2), LerpPosHprInterval(base.camera, 13, Point3(self.cameraTopView[0], self.cameraTopView[1], self.cameraTopView[2]), Point3(self.cameraTopView[3], self.cameraTopView[4], self.cameraTopView[5]), blendType='easeIn')) return result
class PartyCogActivity(DirectObject): notify = directNotify.newCategory('PartyCogActivity') cog = None arena = None player = None players = {} def __init__(self, activity, arenaModel=None, texture=None): self.activity = activity self.root = self.activity.root self.toonPieTracks = {} self.toonPieEventNames = {} self.toonIdsToAnimIntervals = {} self.pieIvals = [] self.resultsIval = None self.arenaModel = arenaModel self.texture = texture def load(self): self.arena = loader.loadModel(self.arenaModel) self.arena.reparentTo(self.root) ground = self.arena.find('**/ground') ground.setBin('ground', 1) entranceArrows = self.arena.findAllMatches('**/arrowFlat*') for arrow in entranceArrows: arrow.setBin('ground', 5) self.leftEntranceLocator = self.arena.find('**/leftEntrance_locator') self.rightEntranceLocator = self.arena.find('**/rightEntrance_locator') self.leftExitLocator = self.arena.find('**/leftExit_locator') self.rightExitLocator = self.arena.find('**/rightExit_locator') self.teamCamPosLocators = (self.arena.find('**/team0CamPos_locator'), self.arena.find('**/team1CamPos_locator')) self.teamCamAimLocators = (self.arena.find('**/team0CamAim_locator'), self.arena.find('**/team1CamAim_locator')) leftTeamLocator = NodePath('TeamLocator-%d' % PartyGlobals.TeamActivityTeams.LeftTeam) leftTeamLocator.reparentTo(self.root) leftTeamLocator.setH(90) rightTeamLocator = NodePath('TeamLocator-%d' % PartyGlobals.TeamActivityTeams.RightTeam) rightTeamLocator.reparentTo(self.root) rightTeamLocator.setH(-90) self.teamLocators = (leftTeamLocator, rightTeamLocator) self._lengthBetweenEntrances = self.leftEntranceLocator.getY( ) - self.rightExitLocator.getY() self._skyCollisionsCollection = self.arena.findAllMatches( '**/cogPieArena_sky*_collision') if len(self._skyCollisionsCollection) > 0: self._skyCollisionParent = self._skyCollisionsCollection[ 0].getParent() else: self._skyCollisionParent = self.arena self._wallCollisionsCollection = self.arena.findAllMatches( '**/cogPieArena_wall*_collision') self._arenaFlagGroups = (self.arena.find('**/flagsL_grp'), self.arena.find('**/flagsR_grp')) self._initArenaDoors() self.cogManager = PartyCogManager() self.arrows = [] self.distanceLabels = [] self.teamColors = list(PartyGlobals.CogActivityColors) + [ PartyGlobals.TeamActivityStatusColor ] for i in range(3): start = self.arena.find('**/cog%d_start_locator' % (i + 1)) end = self.arena.find('**/cog%d_end_locator' % (i + 1)) cog = self.cogManager.generateCog(self.arena) cog.setEndPoints(start.getPos(), end.getPos()) arrow1 = StretchingArrow(self.arena, useColor='orange') arrow2 = StretchingArrow(self.arena, useColor='blue') arrow1.setZ(0.1) arrow2.setZ(0.1) self.arrows.append([arrow1, arrow2]) distanceLabel = self.createDistanceLabel(0, self.teamColors[1]) distanceLabel[0].stash() distanceLabel2 = self.createDistanceLabel(0, self.teamColors[0]) distanceLabel2[0].stash() self.distanceLabels.append([distanceLabel, distanceLabel2]) self.winText = [] text1 = self.createText(0, Point3(-0.5, 0.0, -0.5), self.teamColors[1]) text2 = self.createText(1, Point3(0.5, 0.0, -0.5), self.teamColors[0]) self.winText.append(text1) self.winText.append(text2) self.winStatus = self.createText(2, Point3(0.0, 0.0, -0.8), self.teamColors[0]) signLocator = self.arena.find('**/eventSign_locator') self.activity.sign.setPos(signLocator.getPos(self.root)) if self.texture: textureAlpha = self.texture[:-4] + '_a.rgb' reskinTexture = loader.loadTexture(self.texture, textureAlpha) self.arena.find('**/center_grp').setTexture(reskinTexture, 100) self.arena.find('**/leftSide_grp').setTexture(reskinTexture, 100) self.arena.find('**/rightSide_grp').setTexture(reskinTexture, 100) self.enable() def _initArenaDoors(self): self._arenaDoors = (self.arena.find('**/doorL'), self.arena.find('**/doorR')) arenaDoorLocators = (self.arena.find('**/doorL_locator'), self.arena.find('**/doorR_locator')) for i in range(len(arenaDoorLocators)): arenaDoorLocators[i].wrtReparentTo(self._arenaDoors[i]) self._arenaDoorTimers = (self.createDoorTimer( PartyGlobals.TeamActivityTeams.LeftTeam), self.createDoorTimer( PartyGlobals.TeamActivityTeams.RightTeam)) self._arenaDoorIvals = [None, None] self._doorStartPos = [] for i in range(len(self._arenaDoors)): door = self._arenaDoors[i] timer = self._arenaDoorTimers[i] timer.reparentTo(arenaDoorLocators[i]) timer.hide() self._doorStartPos.append(door.getPos()) door.setPos(door, 0, 0, -7.0) def _destroyArenaDoors(self): for ival in self._arenaDoorIvals: ival.finish() self._arenaDoorIvals = None self._arenaDoors = None for timer in self._arenaDoorTimers: timer.stop() timer.removeNode() self._arenaDoorTimers = None def createDoorTimer(self, team): timer = ToontownTimer(useImage=False, highlightNearEnd=False) timer['text_font'] = ToontownGlobals.getMinnieFont() timer.setFontColor(PartyGlobals.CogActivityColors[team]) timer.setScale(7.0) timer.setPos(0.2, -0.03, 0.0) return timer def createText(self, number, position, color): text = TextNode('winText%d' % number) text.setAlign(TextNode.ACenter) text.setTextColor(color) text.setFont(ToontownGlobals.getSignFont()) text.setText('') noteText = aspect2d.attachNewNode(text) noteText.setScale(0.2) noteText.setPos(position) noteText.stash() return text, noteText def createDistanceLabel(self, number, color): text = TextNode('distanceText-%d' % number) text.setAlign(TextNode.ACenter) text.setTextColor(color) text.setFont(ToontownGlobals.getSignFont()) text.setText('10 ft') node = self.root.attachNewNode(text) node.setBillboardPointEye() node.setScale(2.5) node.setZ(5.0) return node, text def unload(self): self.disable() self._cleanupResultsIval() if self.winText is not None: for pair in self.winText: pair[1].reparentTo(hidden) pair[1].removeNode() self.winText = None if self.winStatus is not None: self.winStatus[1].reparentTo(hidden) self.winStatus[1].removeNode() self.winStatus = None if self.cogManager is not None: self.cogManager.unload() self.cogManager = None if self.arrows is not None: for pair in self.arrows: for arrow in pair: arrow.destroy() arrow = None pair = None self.arrows = None if self.distanceLabels is not None: for pair in self.distanceLabels: for node, text in pair: node.removeNode() pair = None self.distanceLabels = None if len(self.players): for player in self.players.values(): player.disable() player.destroy() self.players.clear() self.player = None if self.arena is not None: self.leftEntranceLocator = None self.rightEntranceLocator = None self.leftExitLocator = None self.rightExitLocator = None self._skyCollisions = None self._skyCollisionParent = None self._arenaFlagGroups = None self._destroyArenaDoors() self.arena.removeNode() self.arena = None for ival in self.toonPieTracks.values(): if ival is not None and ival.isPlaying(): try: ival.finish() except Exception as theException: self.notify.warning( 'Ival could not finish:\n %s \nException %s ' % (str(ival), str(theException))) self.toonPieTracks = {} for ival in self.pieIvals: if ival is not None and ival.isPlaying(): try: ival.finish() except Exception as theException: self.notify.warning( 'Ival could not finish:\n %s \nException %s ' % (str(ival), str(theException))) self.pieIvals = [] self.toonIdsToAnimIntervals = {} for eventName in self.toonPieEventNames.values(): self.ignore(eventName) self.toonPieEventNames = {} def enable(self): self.enableEnterGateCollision() def disable(self): self.disableEnterGateCollision() self.ignoreAll() def hideTeamFlags(self, team): self._arenaFlagGroups[team].stash() def showTeamFlags(self, team): self._arenaFlagGroups[team].unstash() def _playArenaDoorIval(self, team, opening=True): ival = self._arenaDoorIvals[team] if ival is not None and ival.isPlaying(): ival.pause() if not opening: pos = self._doorStartPos[team] else: pos = (self._doorStartPos[team] + Point3(0, 0, -7.0), ) ival = self._arenaDoors[team].posInterval(0.75, Point3(0, 0, -7.0), blendType='easeIn') self._arenaDoorIvals[team] = ival ival.start() def openArenaDoorForTeam(self, team): self._playArenaDoorIval(team, opening=False) def closeArenaDoorForTeam(self, team): self._playArenaDoorIval(team, opening=False) def openArenaDoors(self): self.enableEnterGateCollision() for i in range(len(self._arenaDoors)): self.openArenaDoorForTeam(i) def closeArenaDoors(self): self.disableEnterGateCollision() for i in range(len(self._arenaDoors)): self.closeArenaDoorForTeam(i) def showArenaDoorTimers(self, duration): for timer in self._arenaDoorTimers: timer.setTime(duration) timer.countdown(duration) timer.show() def hideArenaDoorTimers(self): for timer in self._arenaDoorTimers: timer.hide() def enableEnterGateCollision(self): self.acceptOnce('entercogPieArena_entranceLeft_collision', self.handleEnterLeftEntranceTrigger) self.acceptOnce('entercogPieArena_entranceRight_collision', self.handleEnterRightEntranceTrigger) def disableEnterGateCollision(self): self.ignore('entercogPieArena_entranceLeft_collision') self.ignore('entercogPieArena_entranceRight_collision') def enableWallCollisions(self): self._wallCollisionsCollection.unstash() def disableWallCollisions(self): self._wallCollisionsCollection.stash() def enableSkyCollisions(self): self._skyCollisionsCollection.unstash() def disableSkyCollisions(self): self._skyCollisionsCollection.stash() def handleEnterLeftEntranceTrigger(self, collEntry): self.activity.d_toonJoinRequest( PartyGlobals.TeamActivityTeams.LeftTeam) def handleEnterRightEntranceTrigger(self, collEntry): self.activity.d_toonJoinRequest( PartyGlobals.TeamActivityTeams.RightTeam) def checkOrthoDriveCollision(self, oldPos, newPos): x = bound(newPos[0], -16.8, 16.8) y = bound(newPos[1], -17.25, -24.1) newPos.setX(x) newPos.setY(y) return newPos def getPlayerStartPos(self, team, spot): if team == PartyGlobals.TeamActivityTeams.LeftTeam: node = self.leftExitLocator else: node = self.rightExitLocator d = self._lengthBetweenEntrances / ( self.activity.getMaxPlayersPerTeam() + 1) yOffset = node.getY(self.root) + d * (spot + 1) pos = node.getPos(self.root) pos.setY(yOffset) return pos def handleToonJoined(self, toon, team, lateEntry=False): pos = self.getPlayerStartPos(team, self.activity.getIndex(toon.doId, team)) if toon == base.localAvatar: player = PartyCogActivityLocalPlayer(self.activity, pos, team, self.handleToonExited) player.entersActivity() self.player = player self.disableSkyCollisions() self.playPlayerEnterIval() else: player = PartyCogActivityPlayer(self.activity, toon, pos, team) player.entersActivity() if lateEntry: player.updateToonPosition() self.players[toon.doId] = player def handleToonSwitchedTeams(self, toon): toonId = toon.doId player = self.players.get(toonId) if player is None: self.notify.warning( 'handleToonSwitchedTeams: toonId %s not found' % toonId) return team = self.activity.getTeam(toonId) spot = self.activity.getIndex(toonId, team) pos = self.getPlayerStartPos(team, spot) self.finishToonIval(toonId) player.setTeam(team) player.setToonStartPosition(pos) player.updateToonPosition() def handleToonShifted(self, toon): toonId = toon.doId if self.players.has_key(toonId): player = self.players[toonId] spot = self.activity.getIndex(toonId, player.team) pos = self.getPlayerStartPos(player.team, spot) player.setToonStartPosition(pos) if self.player is not None and toon == self.player.toon: self.playToonIval(base.localAvatar.doId, self.player.getRunToStartPositionIval()) def handleToonDisabled(self, toonId): self.finishToonIval(toonId) self.finishPieIvals(toonId) player = self.players.get(toonId) if player is not None: player.disable() if player == self.player: self.player = None del self.players[toonId] def finishPieIvals(self, toonId): for ival in self.pieIvals: if ival.isPlaying(): if ival.getName().find(str(toonId)) != -1: ival.finish() def playPlayerEnterIval(self): def conditionallyShowSwitchButton(self=self, enable=True): if enable and self.activity.activityFSM.state in ('WaitForEnough', 'WaitToStart'): self.activity.teamActivityGui.enableSwitchButton() else: self.activity.teamActivityGui.disableSwitchButton() ival = Sequence(Func(self.disableWallCollisions), Func(conditionallyShowSwitchButton, self, False), self.player.getRunToStartPositionIval(), Func(conditionallyShowSwitchButton, self, True), Func(self.enableWallCollisions)) self.playToonIval(base.localAvatar.doId, ival) def finishToonIval(self, toonId): if self.toonIdsToAnimIntervals.get( toonId ) is not None and self.toonIdsToAnimIntervals[toonId].isPlaying(): self.toonIdsToAnimIntervals[toonId].finish() def playToonIval(self, toonId, ival): self.finishToonIval(toonId) self.toonIdsToAnimIntervals[toonId] = ival ival.start() def startActivity(self, timestamp): self.pieHandler = CollisionHandlerEvent() self.pieHandler.setInPattern('pieHit-%fn') if self.player is not None: self.player.resetScore() self.hideTeamFlags(self.player.team) for player in self.players.values(): self.finishToonIval(player.toon.doId) player.enable() for cog in self.cogManager.cogs: cog.request('Active', timestamp) for ival in self.pieIvals: if ival.isPlaying(): ival.finish() self.pieIvals = [] def stopActivity(self): for player in self.players.values(): player.disable() for eventName in self.toonPieEventNames.values(): self.ignore(eventName) self.toonPieEventNames.clear() for cog in self.cogManager.cogs: cog.request('Static') def handleToonExited(self, toon): self.finishToonIval(toon.doId) player = self.players[toon.doId] player.disable() player.exitsActivity() player.destroy() if player == self.player: self.showTeamFlags(self.activity.getTeam(toon.doId)) self.player = None self.enableEnterGateCollision() self.enableSkyCollisions() del self.players[toon.doId] def pieThrow(self, avId, timestamp, heading, pos, power): toon = self.activity.getAvatar(avId) if toon is None: return tossTrack, pieTrack, flyPie = self.getTossPieInterval( toon, pos[0], pos[1], pos[2], heading, 0, 0, power) if avId == base.localAvatar.doId: flyPie.setTag('throwerId', str(avId)) collSphere = CollisionSphere(0, 0, 0, 0.5) collSphere.setTangible(0) name = 'PieSphere-%d' % avId collSphereName = self.activity.uniqueName(name) collNode = CollisionNode(collSphereName) collNode.setFromCollideMask(ToontownGlobals.PieBitmask) collNode.addSolid(collSphere) collNP = flyPie.attachNewNode(collNode) base.cTrav.addCollider(collNP, self.pieHandler) self.toonPieEventNames[collNP] = 'pieHit-' + collSphereName self.accept(self.toonPieEventNames[collNP], self.handlePieCollision) else: player = self.players.get(avId) if player is not None: player.faceForward() def matchRunningAnim(toon=toon): toon.playingAnim = None toon.setSpeed(toon.forwardSpeed, toon.rotateSpeed) newTossTrack = Sequence(tossTrack, Func(matchRunningAnim)) pieTrack = Parallel(newTossTrack, pieTrack, name='PartyCogActivity.pieTrack-%d-%s' % (avId, timestamp)) elapsedTime = globalClockDelta.localElapsedTime(timestamp) if elapsedTime < 16.0 / 24.0: elapsedTime = 16.0 / 24.0 pieTrack.start(elapsedTime) self.pieIvals.append(pieTrack) self.toonPieTracks[avId] = pieTrack def getTossPieInterval(self, toon, x, y, z, h, p, r, power, beginFlyIval=Sequence()): from toontown.toonbase import ToontownBattleGlobals from toontown.battle import BattleProps pie = toon.getPieModel() pie.setScale(0.5) flyPie = pie.copyTo(NodePath('a')) pieName = ToontownBattleGlobals.pieNames[toon.pieType] pieType = BattleProps.globalPropPool.getPropType(pieName) animPie = Sequence() if pieType == 'actor': animPie = ActorInterval(pie, pieName, startFrame=48) sound = loader.loadSfx('phase_3.5/audio/sfx/AA_pie_throw_only.ogg') t = power / 100.0 dist = lerp(PartyGlobals.CogActivityPieMinDist, PartyGlobals.CogActivityPieMaxDist, t) time = lerp(1.0, 1.5, t) proj = ProjectileInterval(None, startPos=Point3(0, 0, 0), endPos=Point3(0, dist, 0), duration=time) relVel = proj.startVel def getVelocity(toon=toon, relVel=relVel): return render.getRelativeVector(toon, relVel) * 0.6 def __safeSetAnimState(toon=toon, state='Happy'): if toon and hasattr(toon, 'animFSM'): toon.setAnimState('Happy') else: self.notify.warning( 'The toon is being destroyed. No attribute animState.') toss = Track((0, Sequence( Func(toon.setPosHpr, x, y, z, h, p, r), Func(pie.reparentTo, toon.rightHand), Func(pie.setPosHpr, 0, 0, 0, 0, 0, 0), animPie, Parallel( ActorInterval(toon, 'throw', startFrame=48, playRate=1.5, partName='torso'), animPie), Func(__safeSetAnimState, toon, 'Happy'))), (16.0 / 24.0, Func(pie.detachNode))) fly = Track( (14.0 / 24.0, SoundInterval( sound, node=toon, cutOff=PartyGlobals.PARTY_COG_CUTOFF)), (16.0 / 24.0, Sequence( Func(flyPie.reparentTo, render), Func(flyPie.setPosHpr, toon, 0.52, 0.97, 2.24, 0, -45, 0), beginFlyIval, ProjectileInterval(flyPie, startVel=getVelocity, duration=6), Func(flyPie.detachNode)))) return toss, fly, flyPie def handlePieCollision(self, colEntry): if not self.activity.isState('Active') or self.player is None: return handled = False into = colEntry.getIntoNodePath() intoName = into.getName() timestamp = globalClockDelta.localToNetworkTime( globalClock.getFrameTime(), bits=32) if 'PartyCog' in intoName: if self.toonPieTracks.get(base.localAvatar.doId) is not None: self.toonPieTracks[base.localAvatar.doId].finish() self.toonPieTracks[base.localAvatar.doId] = None parts = intoName.split('-') cogID = int(parts[1]) point = colEntry.getSurfacePoint(self.cogManager.cogs[cogID].root) cog = self.cogManager.cogs[cogID] hitHead = point.getZ() > cog.getHeadLocation( ) and not parts[2].startswith('Arm') if self.activity.getTeam( base.localAvatar.doId ) == PartyGlobals.TeamActivityTeams.LeftTeam: direction = -1.0 else: direction = 1.0 self.activity.b_pieHitsCog(timestamp, cogID, point, direction, hitHead) if hitHead: hitPoints = self.player.hitHead() else: hitPoints = self.player.hitBody() self.player.updateScore() if hitPoints > 0: cog.showHitScore(hitPoints) handled = True elif 'distAvatarCollNode' in intoName: parts = intoName.split('-') hitToonId = int(parts[1]) toon = base.cr.doId2do.get(hitToonId) if toon is not None and self.activity.getTeam( hitToonId) != self.player.team: point = colEntry.getSurfacePoint(toon) self.activity.b_pieHitsToon(hitToonId, timestamp, point) handled = True if handled: eventName = self.toonPieEventNames.get(colEntry.getFromNodePath()) if eventName is not None: self.ignore(eventName) del self.toonPieEventNames[colEntry.getFromNodePath()] def pieHitsCog(self, timestamp, cogNum, pos, direction, part): cog = self.cogManager.cogs[cogNum] cog.respondToPieHit(timestamp, pos, part, direction) def pieHitsToon(self, toonId, timestamp, pos): player = self.players.get(toonId) if player is not None: player.respondToPieHit(timestamp, pos) def setCogDistances(self, distances): self.cogManager.updateDistances(distances) def showCogs(self): for cog in self.cogManager.cogs: cog.request('Static') def hideCogs(self): for cog in self.cogManager.cogs: cog.request('Down') def showResults(self, resultsText, winner, totals): if self.player is None: return None base.localAvatar.showName() self.resultsIval = Sequence( Wait(0.1), Func(self.activity.setStatus, TTLocalizer.PartyCogTimeUp), Func(self.activity.showStatus), Wait(2.0), Func(self.activity.hideStatus), Wait(0.5), Func(self.player.lookAtArena), Func(self.showTeamFlags, self.activity.getTeam(base.localAvatar.doId)), Wait(1.0), Func(self.showArrow, 0), Wait(1.3), Func(self.showArrow, 1), Wait(1.3), Func(self.showArrow, 2), Wait(1.3), Func(self.showTotals, totals), Wait(1.0), Func(self.showWinner, resultsText, winner), Func(self._cleanupResultsIval), name='PartyCog-conclusionSequence') self.accept('DistributedPartyActivity-showJellybeanReward', self._cleanupResultsIval) self.resultsIval.start() def _cleanupResultsIval(self): if self.resultsIval: if self.resultsIval.isPlaying(): self.resultsIval.pause() self.resultsIval = None self.ignore('DistributedPartyActivity-showJellybeanReward') def showTotals(self, totals): newtotals = (totals[1] - totals[0] + PartyGlobals.CogActivityArenaLength / 2.0 * 3, totals[0] - totals[1] + PartyGlobals.CogActivityArenaLength / 2.0 * 3) self.winText[0][0].setText(TTLocalizer.PartyCogDistance % newtotals[0]) self.winText[1][0].setText(TTLocalizer.PartyCogDistance % newtotals[1]) for textPair in self.winText: textPair[1].unstash() def hideTotals(self): for textPair in self.winText: textPair[0].setText('') textPair[1].stash() def showWinner(self, text, winner): self.winStatus[0].setText(text) self.winStatus[0].setTextColor(self.teamColors[winner]) self.winStatus[1].unstash() def hideWinner(self): self.winStatus[0].setText('') self.winStatus[1].stash() def showArrow(self, arrowNum): arrows = self.arrows[arrowNum] cog = self.cogManager.cogs[arrowNum] points = [ self.arena.find('**/cog%d_start_locator' % (arrowNum + 1)), self.arena.find('**/cog%d_end_locator' % (arrowNum + 1)) ] Y = cog.root.getY() for point in points: point.setY(Y) for i in range(len(arrows)): arrow = arrows[i] arrow.draw(points[i].getPos(), cog.root.getPos(), animate=False) arrow.unstash() i = -1 length = PartyGlobals.CogActivityArenaLength for node, text in self.distanceLabels[arrowNum]: current = bound(i, 0, 1) node.setPos(cog.root.getPos(self.root) + Point3(i * 4, 2, 4)) dist = PartyCogUtils.getCogDistanceUnitsFromCenter(cog.currentT) dist = abs(dist - i * length / 2) if dist > length - dist: node.setScale(2.8) else: node.setScale(2.2) text.setText(TTLocalizer.PartyCogDistance % dist) if dist > 0: node.unstash() else: arrows[current].stash() i += 2 def hideArrows(self): for pair in self.arrows: for arrow in pair: arrow.stash() for pair in self.distanceLabels: for node, text in pair: node.stash() def hideResults(self): self.hideArrows() self.hideTotals() self.hideWinner()
class PartyCogActivity(DirectObject): __module__ = __name__ notify = directNotify.newCategory('PartyCogActivity') cog = None arena = None player = None players = {} def __init__(self, activity, arenaModel = None, texture = None): self.activity = activity self.root = self.activity.root self.toonPieTracks = {} self.toonPieEventNames = {} self.toonIdsToAnimIntervals = {} self.pieIvals = [] self.resultsIval = None self.arenaModel = arenaModel self.texture = texture return def load(self): self.arena = loader.loadModel(self.arenaModel) self.arena.reparentTo(self.root) ground = self.arena.find('**/ground') ground.setBin('ground', 1) entranceArrows = self.arena.findAllMatches('**/arrowFlat*') for arrow in entranceArrows: arrow.setBin('ground', 5) self.leftEntranceLocator = self.arena.find('**/leftEntrance_locator') self.rightEntranceLocator = self.arena.find('**/rightEntrance_locator') self.leftExitLocator = self.arena.find('**/leftExit_locator') self.rightExitLocator = self.arena.find('**/rightExit_locator') self.teamCamPosLocators = (self.arena.find('**/team0CamPos_locator'), self.arena.find('**/team1CamPos_locator')) self.teamCamAimLocators = (self.arena.find('**/team0CamAim_locator'), self.arena.find('**/team1CamAim_locator')) leftTeamLocator = NodePath('TeamLocator-%d' % PartyGlobals.TeamActivityTeams.LeftTeam) leftTeamLocator.reparentTo(self.root) leftTeamLocator.setH(90) rightTeamLocator = NodePath('TeamLocator-%d' % PartyGlobals.TeamActivityTeams.RightTeam) rightTeamLocator.reparentTo(self.root) rightTeamLocator.setH(-90) self.teamLocators = (leftTeamLocator, rightTeamLocator) self._lengthBetweenEntrances = self.leftEntranceLocator.getY() - self.rightExitLocator.getY() self._skyCollisionsCollection = self.arena.findAllMatches('**/cogPieArena_sky*_collision') if len(self._skyCollisionsCollection) > 0: self._skyCollisionParent = self._skyCollisionsCollection[0].getParent() else: self._skyCollisionParent = self.arena self._wallCollisionsCollection = self.arena.findAllMatches('**/cogPieArena_wall*_collision') self._arenaFlagGroups = (self.arena.find('**/flagsL_grp'), self.arena.find('**/flagsR_grp')) self._initArenaDoors() self.cogManager = PartyCogManager() self.arrows = [] self.distanceLabels = [] self.teamColors = list(PartyGlobals.CogActivityColors) + [PartyGlobals.TeamActivityStatusColor] for i in range(3): start = self.arena.find('**/cog%d_start_locator' % (i + 1)) end = self.arena.find('**/cog%d_end_locator' % (i + 1)) cog = self.cogManager.generateCog(self.arena) cog.setEndPoints(start.getPos(), end.getPos()) arrow1 = StretchingArrow(self.arena, useColor='orange') arrow2 = StretchingArrow(self.arena, useColor='blue') arrow1.setZ(0.1) arrow2.setZ(0.1) self.arrows.append([arrow1, arrow2]) distanceLabel = self.createDistanceLabel(0, self.teamColors[1]) distanceLabel[0].stash() distanceLabel2 = self.createDistanceLabel(0, self.teamColors[0]) distanceLabel2[0].stash() self.distanceLabels.append([distanceLabel, distanceLabel2]) self.winText = [] text1 = self.createText(0, Point3(-0.5, 0.0, -0.5), self.teamColors[1]) text2 = self.createText(1, Point3(0.5, 0.0, -0.5), self.teamColors[0]) self.winText.append(text1) self.winText.append(text2) self.winStatus = self.createText(2, Point3(0.0, 0.0, -0.8), self.teamColors[0]) signLocator = self.arena.find('**/eventSign_locator') self.activity.sign.setPos(signLocator.getPos(self.root)) if self.texture: textureAlpha = self.texture[:-4] + '_a.rgb' reskinTexture = loader.loadTexture(self.texture, textureAlpha) self.arena.find('**/center_grp').setTexture(reskinTexture, 100) self.arena.find('**/leftSide_grp').setTexture(reskinTexture, 100) self.arena.find('**/rightSide_grp').setTexture(reskinTexture, 100) self.enable() def _initArenaDoors(self): self._arenaDoors = (self.arena.find('**/doorL'), self.arena.find('**/doorR')) arenaDoorLocators = (self.arena.find('**/doorL_locator'), self.arena.find('**/doorR_locator')) for i in range(len(arenaDoorLocators)): arenaDoorLocators[i].wrtReparentTo(self._arenaDoors[i]) self._arenaDoorTimers = (self.createDoorTimer(PartyGlobals.TeamActivityTeams.LeftTeam), self.createDoorTimer(PartyGlobals.TeamActivityTeams.RightTeam)) self._arenaDoorIvals = [None, None] self._doorStartPos = [] for i in range(len(self._arenaDoors)): door = self._arenaDoors[i] timer = self._arenaDoorTimers[i] timer.reparentTo(arenaDoorLocators[i]) timer.hide() self._doorStartPos.append(door.getPos()) door.setPos(door, 0, 0, -7.0) return def _destroyArenaDoors(self): for ival in self._arenaDoorIvals: ival.finish() self._arenaDoorIvals = None self._arenaDoors = None for timer in self._arenaDoorTimers: timer.stop() timer.removeNode() self._arenaDoorTimers = None return def createDoorTimer(self, team): timer = ToontownTimer(useImage=False, highlightNearEnd=False) timer['text_font'] = ToontownGlobals.getMinnieFont() timer.setFontColor(PartyGlobals.CogActivityColors[team]) timer.setScale(7.0) timer.setPos(0.2, -0.03, 0.0) return timer def createText(self, number, position, color): text = TextNode('winText%d' % number) text.setAlign(TextNode.ACenter) text.setTextColor(color) text.setFont(ToontownGlobals.getSignFont()) text.setText('') noteText = aspect2d.attachNewNode(text) noteText.setScale(0.2) noteText.setPos(position) noteText.stash() return (text, noteText) def createDistanceLabel(self, number, color): text = TextNode('distanceText-%d' % number) text.setAlign(TextNode.ACenter) text.setTextColor(color) text.setFont(ToontownGlobals.getSignFont()) text.setText('10 ft') node = self.root.attachNewNode(text) node.setBillboardPointEye() node.setScale(2.5) node.setZ(5.0) return (node, text) def unload(self): self.disable() self._cleanupResultsIval() if self.winText is not None: for pair in self.winText: pair[1].reparentTo(hidden) pair[1].removeNode() self.winText = None if self.winStatus is not None: self.winStatus[1].reparentTo(hidden) self.winStatus[1].removeNode() self.winStatus = None if self.cogManager is not None: self.cogManager.unload() self.cogManager = None if self.arrows is not None: for pair in self.arrows: for arrow in pair: arrow.destroy() arrow = None pair = None self.arrows = None if self.distanceLabels is not None: for pair in self.distanceLabels: for node, text in pair: node.removeNode() pair = None self.distanceLabels = None if len(self.players): for player in self.players.values(): player.disable() player.destroy() self.players.clear() self.player = None if self.arena is not None: self.leftEntranceLocator = None self.rightEntranceLocator = None self.leftExitLocator = None self.rightExitLocator = None self._skyCollisions = None self._skyCollisionParent = None self._arenaFlagGroups = None self._destroyArenaDoors() self.arena.removeNode() self.arena = None for ival in self.toonPieTracks.values(): if ival is not None and ival.isPlaying(): try: ival.finish() except Exception as theException: self.notify.warning('Ival could not finish:\n %s \nException %s ' % (str(ival), str(theException))) self.toonPieTracks = {} for ival in self.pieIvals: if ival is not None and ival.isPlaying(): try: ival.finish() except Exception as theException: self.notify.warning('Ival could not finish:\n %s \nException %s ' % (str(ival), str(theException))) self.pieIvals = [] self.toonIdsToAnimIntervals = {} for eventName in self.toonPieEventNames.values(): self.ignore(eventName) self.toonPieEventNames = {} return def enable(self): self.enableEnterGateCollision() def disable(self): self.disableEnterGateCollision() self.ignoreAll() def hideTeamFlags(self, team): self._arenaFlagGroups[team].stash() def showTeamFlags(self, team): self._arenaFlagGroups[team].unstash() def _playArenaDoorIval(self, team, opening = True): ival = self._arenaDoorIvals[team] if ival is not None and ival.isPlaying(): ival.pause() if not opening: pos = self._doorStartPos[team] else: pos = (self._doorStartPos[team] + Point3(0, 0, -7.0),) ival = self._arenaDoors[team].posInterval(0.75, pos, blendType='easeIn') self._arenaDoorIvals[team] = ival ival.start() return def openArenaDoorForTeam(self, team): self._playArenaDoorIval(team, opening=True) def closeArenaDoorForTeam(self, team): self._playArenaDoorIval(team, opening=False) def openArenaDoors(self): self.enableEnterGateCollision() for i in range(len(self._arenaDoors)): self.openArenaDoorForTeam(i) def closeArenaDoors(self): self.disableEnterGateCollision() for i in range(len(self._arenaDoors)): self.closeArenaDoorForTeam(i) def showArenaDoorTimers(self, duration): for timer in self._arenaDoorTimers: timer.setTime(duration) timer.countdown(duration) timer.show() def hideArenaDoorTimers(self): for timer in self._arenaDoorTimers: timer.hide() def enableEnterGateCollision(self): self.acceptOnce('entercogPieArena_entranceLeft_collision', self.handleEnterLeftEntranceTrigger) self.acceptOnce('entercogPieArena_entranceRight_collision', self.handleEnterRightEntranceTrigger) def disableEnterGateCollision(self): self.ignore('entercogPieArena_entranceLeft_collision') self.ignore('entercogPieArena_entranceRight_collision') def enableWallCollisions(self): self._wallCollisionsCollection.unstash() def disableWallCollisions(self): self._wallCollisionsCollection.stash() def enableSkyCollisions(self): self._skyCollisionsCollection.unstash() def disableSkyCollisions(self): self._skyCollisionsCollection.stash() def handleEnterLeftEntranceTrigger(self, collEntry): self.activity.d_toonJoinRequest(PartyGlobals.TeamActivityTeams.LeftTeam) def handleEnterRightEntranceTrigger(self, collEntry): self.activity.d_toonJoinRequest(PartyGlobals.TeamActivityTeams.RightTeam) def checkOrthoDriveCollision(self, oldPos, newPos): x = bound(newPos[0], -16.8, 16.8) y = bound(newPos[1], -17.25, -24.1) newPos.setX(x) newPos.setY(y) return newPos def getPlayerStartPos(self, team, spot): if team == PartyGlobals.TeamActivityTeams.LeftTeam: node = self.leftExitLocator else: node = self.rightExitLocator d = self._lengthBetweenEntrances / (self.activity.getMaxPlayersPerTeam() + 1) yOffset = node.getY(self.root) + d * (spot + 1) pos = node.getPos(self.root) pos.setY(yOffset) return pos def handleToonJoined(self, toon, team, lateEntry = False): pos = self.getPlayerStartPos(team, self.activity.getIndex(toon.doId, team)) if toon == base.localAvatar: player = PartyCogActivityLocalPlayer(self.activity, pos, team, self.handleToonExited) player.entersActivity() self.player = player self.disableSkyCollisions() self.playPlayerEnterIval() else: player = PartyCogActivityPlayer(self.activity, toon, pos, team) player.entersActivity() if lateEntry: player.updateToonPosition() self.players[toon.doId] = player def handleToonSwitchedTeams(self, toon): toonId = toon.doId player = self.players.get(toonId) if player is None: self.notify.warning('handleToonSwitchedTeams: toonId %s not found' % toonId) return team = self.activity.getTeam(toonId) spot = self.activity.getIndex(toonId, team) pos = self.getPlayerStartPos(team, spot) self.finishToonIval(toonId) player.setTeam(team) player.setToonStartPosition(pos) player.updateToonPosition() return def handleToonShifted(self, toon): toonId = toon.doId if self.players.has_key(toonId): player = self.players[toonId] spot = self.activity.getIndex(toonId, player.team) pos = self.getPlayerStartPos(player.team, spot) player.setToonStartPosition(pos) if self.player is not None and toon == self.player.toon: self.playToonIval(base.localAvatar.doId, self.player.getRunToStartPositionIval()) return def handleToonDisabled(self, toonId): self.finishToonIval(toonId) self.finishPieIvals(toonId) player = self.players.get(toonId) if player is not None: player.disable() if player == self.player: self.player = None del self.players[toonId] return def finishPieIvals(self, toonId): for ival in self.pieIvals: if ival.isPlaying(): if ival.getName().find(str(toonId)) != -1: ival.finish() def playPlayerEnterIval(self): def conditionallyShowSwitchButton(self = self, enable = True): if enable and self.activity.activityFSM.state in ['WaitForEnough', 'WaitToStart']: self.activity.teamActivityGui.enableSwitchButton() else: self.activity.teamActivityGui.disableSwitchButton() ival = Sequence(Func(self.disableWallCollisions), Func(conditionallyShowSwitchButton, self, False), self.player.getRunToStartPositionIval(), Func(conditionallyShowSwitchButton, self, True), Func(self.enableWallCollisions)) self.playToonIval(base.localAvatar.doId, ival) def finishToonIval(self, toonId): if self.toonIdsToAnimIntervals.get(toonId) is not None and self.toonIdsToAnimIntervals[toonId].isPlaying(): self.toonIdsToAnimIntervals[toonId].finish() return def playToonIval(self, toonId, ival): self.finishToonIval(toonId) self.toonIdsToAnimIntervals[toonId] = ival ival.start() def startActivity(self, timestamp): self.pieHandler = CollisionHandlerEvent() self.pieHandler.setInPattern('pieHit-%fn') if self.player is not None: self.player.resetScore() self.hideTeamFlags(self.player.team) for player in self.players.values(): self.finishToonIval(player.toon.doId) player.enable() for cog in self.cogManager.cogs: cog.request('Active', timestamp) for ival in self.pieIvals: if ival.isPlaying(): ival.finish() self.pieIvals = [] return def stopActivity(self): for player in self.players.values(): player.disable() for eventName in self.toonPieEventNames.values(): self.ignore(eventName) self.toonPieEventNames.clear() for cog in self.cogManager.cogs: cog.request('Static') def handleToonExited(self, toon): self.finishToonIval(toon.doId) player = self.players[toon.doId] player.disable() player.exitsActivity() player.destroy() if player == self.player: self.showTeamFlags(self.activity.getTeam(toon.doId)) self.player = None self.enableEnterGateCollision() self.enableSkyCollisions() del self.players[toon.doId] return def pieThrow(self, avId, timestamp, heading, pos, power): toon = self.activity.getAvatar(avId) if toon is None: return tossTrack, pieTrack, flyPie = self.getTossPieInterval(toon, pos[0], pos[1], pos[2], heading, 0, 0, power) if avId == base.localAvatar.doId: flyPie.setTag('throwerId', str(avId)) collSphere = CollisionSphere(0, 0, 0, 0.5) collSphere.setTangible(0) name = 'PieSphere-%d' % avId collSphereName = self.activity.uniqueName(name) collNode = CollisionNode(collSphereName) collNode.setFromCollideMask(ToontownGlobals.PieBitmask) collNode.addSolid(collSphere) collNP = flyPie.attachNewNode(collNode) base.cTrav.addCollider(collNP, self.pieHandler) self.toonPieEventNames[collNP] = 'pieHit-' + collSphereName self.accept(self.toonPieEventNames[collNP], self.handlePieCollision) else: player = self.players.get(avId) if player is not None: player.faceForward() def matchRunningAnim(toon = toon): toon.playingAnim = None toon.setSpeed(toon.forwardSpeed, toon.rotateSpeed) return newTossTrack = Sequence(tossTrack, Func(matchRunningAnim)) pieTrack = Parallel(newTossTrack, pieTrack, name='PartyCogActivity.pieTrack-%d-%s' % (avId, timestamp)) elapsedTime = globalClockDelta.localElapsedTime(timestamp) if elapsedTime < 16.0 / 24.0: elapsedTime = 16.0 / 24.0 pieTrack.start(elapsedTime) self.pieIvals.append(pieTrack) self.toonPieTracks[avId] = pieTrack return def getTossPieInterval(self, toon, x, y, z, h, p, r, power, beginFlyIval = Sequence()): from toontown.toonbase import ToontownBattleGlobals from toontown.battle import BattleProps pie = toon.getPieModel() pie.setScale(0.5) flyPie = pie.copyTo(NodePath('a')) pieName = ToontownBattleGlobals.pieNames[toon.pieType] pieType = BattleProps.globalPropPool.getPropType(pieName) animPie = Sequence() if pieType == 'actor': animPie = ActorInterval(pie, pieName, startFrame=48) sound = loader.loadSfx('phase_3.5/audio/sfx/AA_pie_throw_only.mp3') t = power / 100.0 dist = lerp(PartyGlobals.CogActivityPieMinDist, PartyGlobals.CogActivityPieMaxDist, t) time = lerp(1.0, 1.5, t) proj = ProjectileInterval(None, startPos=Point3(0, 0, 0), endPos=Point3(0, dist, 0), duration=time) relVel = proj.startVel def getVelocity(toon = toon, relVel = relVel): return render.getRelativeVector(toon, relVel) * 0.6 def __safeSetAnimState(toon = toon, state = 'Happy'): if toon and hasattr(toon, 'animFSM'): toon.setAnimState('Happy') else: self.notify.warning('The toon is being destroyed. No attribute animState.') toss = Track((0, Sequence(Func(toon.setPosHpr, x, y, z, h, p, r), Func(pie.reparentTo, toon.rightHand), Func(pie.setPosHpr, 0, 0, 0, 0, 0, 0), animPie, Parallel(ActorInterval(toon, 'throw', startFrame=48, playRate=1.5, partName='torso'), animPie), Func(__safeSetAnimState, toon, 'Happy'))), (16.0 / 24.0, Func(pie.detachNode))) fly = Track((14.0 / 24.0, SoundInterval(sound, node=toon, cutOff=PartyGlobals.PARTY_COG_CUTOFF)), (16.0 / 24.0, Sequence(Func(flyPie.reparentTo, render), Func(flyPie.setPosHpr, toon, 0.52, 0.97, 2.24, 0, -45, 0), beginFlyIval, ProjectileInterval(flyPie, startVel=getVelocity, duration=6), Func(flyPie.detachNode)))) return (toss, fly, flyPie) def handlePieCollision(self, colEntry): if not self.activity.isState('Active') or self.player is None: return handled = False into = colEntry.getIntoNodePath() intoName = into.getName() timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32) if 'PartyCog' in intoName: if self.toonPieTracks.get(base.localAvatar.doId) is not None: self.toonPieTracks[base.localAvatar.doId].finish() self.toonPieTracks[base.localAvatar.doId] = None parts = intoName.split('-') cogID = int(parts[1]) point = colEntry.getSurfacePoint(self.cogManager.cogs[cogID].root) cog = self.cogManager.cogs[cogID] if point.getZ() > cog.getHeadLocation(): hitHead = not parts[2].startswith('Arm') if self.activity.getTeam(base.localAvatar.doId) == PartyGlobals.TeamActivityTeams.LeftTeam: direction = -1.0 else: direction = 1.0 self.activity.b_pieHitsCog(timestamp, cogID, point, direction, hitHead) if hitHead: hitPoints = self.player.hitHead() else: hitPoints = self.player.hitBody() self.player.updateScore() if hitPoints > 0: cog.showHitScore(hitPoints) handled = True elif 'distAvatarCollNode' in intoName: parts = intoName.split('-') hitToonId = int(parts[1]) toon = base.cr.doId2do.get(hitToonId) if toon is not None and self.activity.getTeam(hitToonId) != self.player.team: point = colEntry.getSurfacePoint(toon) self.activity.b_pieHitsToon(hitToonId, timestamp, point) handled = True if handled: eventName = self.toonPieEventNames.get(colEntry.getFromNodePath()) eventName is not None and self.ignore(eventName) del self.toonPieEventNames[colEntry.getFromNodePath()] return def pieHitsCog(self, timestamp, cogNum, pos, direction, part): cog = self.cogManager.cogs[cogNum] cog.respondToPieHit(timestamp, pos, part, direction) def pieHitsToon(self, toonId, timestamp, pos): player = self.players.get(toonId) if player is not None: player.respondToPieHit(timestamp, pos) return def setCogDistances(self, distances): self.cogManager.updateDistances(distances) def showCogs(self): for cog in self.cogManager.cogs: cog.request('Static') def hideCogs(self): for cog in self.cogManager.cogs: cog.request('Down') def showResults(self, resultsText, winner, totals): if self.player is None: return base.localAvatar.showName() self.resultsIval = Sequence(Wait(0.1), Func(self.activity.setStatus, TTLocalizer.PartyCogTimeUp), Func(self.activity.showStatus), Wait(2.0), Func(self.activity.hideStatus), Wait(0.5), Func(self.player.lookAtArena), Func(self.showTeamFlags, self.activity.getTeam(base.localAvatar.doId)), Wait(1.0), Func(self.showArrow, 0), Wait(1.3), Func(self.showArrow, 1), Wait(1.3), Func(self.showArrow, 2), Wait(1.3), Func(self.showTotals, totals), Wait(1.0), Func(self.showWinner, resultsText, winner), Func(self._cleanupResultsIval), name='PartyCog-conclusionSequence') self.accept('DistributedPartyActivity-showJellybeanReward', self._cleanupResultsIval) self.resultsIval.start() return def _cleanupResultsIval(self): if self.resultsIval: if self.resultsIval.isPlaying(): self.resultsIval.pause() self.resultsIval = None self.ignore('DistributedPartyActivity-showJellybeanReward') return def showTotals(self, totals): newtotals = (totals[1] - totals[0] + PartyGlobals.CogActivityArenaLength / 2.0 * 3, totals[0] - totals[1] + PartyGlobals.CogActivityArenaLength / 2.0 * 3) self.winText[0][0].setText(TTLocalizer.PartyCogDistance % newtotals[0]) self.winText[1][0].setText(TTLocalizer.PartyCogDistance % newtotals[1]) for textPair in self.winText: textPair[1].unstash() def hideTotals(self): for textPair in self.winText: textPair[0].setText('') textPair[1].stash() def showWinner(self, text, winner): self.winStatus[0].setText(text) self.winStatus[0].setTextColor(self.teamColors[winner]) self.winStatus[1].unstash() def hideWinner(self): self.winStatus[0].setText('') self.winStatus[1].stash() def showArrow(self, arrowNum): arrows = self.arrows[arrowNum] cog = self.cogManager.cogs[arrowNum] points = [self.arena.find('**/cog%d_start_locator' % (arrowNum + 1)), self.arena.find('**/cog%d_end_locator' % (arrowNum + 1))] Y = cog.root.getY() for point in points: point.setY(Y) for i in range(len(arrows)): arrow = arrows[i] arrow.draw(points[i].getPos(), cog.root.getPos(), animate=False) arrow.unstash() i = -1 length = PartyGlobals.CogActivityArenaLength for node, text in self.distanceLabels[arrowNum]: current = bound(i, 0, 1) node.setPos(cog.root.getPos(self.root) + Point3(i * 4, 2, 4)) dist = PartyCogUtils.getCogDistanceUnitsFromCenter(cog.currentT) dist = abs(dist - i * length / 2) if dist > length - dist: node.setScale(2.8) else: node.setScale(2.2) text.setText(TTLocalizer.PartyCogDistance % dist) if dist > 0: node.unstash() else: arrows[current].stash() i += 2 def hideArrows(self): for pair in self.arrows: for arrow in pair: arrow.stash() for pair in self.distanceLabels: for node, text in pair: node.stash() def hideResults(self): self.hideArrows() self.hideTotals() self.hideWinner()
class PartyCogActivity(DirectObject): notify = directNotify.newCategory("PartyCogActivity") cog = None arena = None player = None players = {} def __init__(self, activity): self.activity = activity self.root = self.activity.root self.toonPieTracks = {} self.toonPieEventNames = {} self.toonIdsToAnimIntervals = {} self.pieIvals = [] self.resultsIval = None def load(self): self.arena = loader.loadModel("phase_13/models/parties/cogPieArena_model") self.arena.reparentTo(self.root) ground = self.arena.find("**/ground") # Make the ground plane draw before the shadow! ground.setBin("ground", 1) entranceArrows = self.arena.findAllMatches("**/arrowFlat*") for arrow in entranceArrows: arrow.setBin("ground", 5) # Get Entrance/Exit Locations self.leftEntranceLocator = self.arena.find("**/leftEntrance_locator") self.rightEntranceLocator = self.arena.find("**/rightEntrance_locator") self.leftExitLocator = self.arena.find("**/leftExit_locator") self.rightExitLocator = self.arena.find("**/rightExit_locator") self.teamCamPosLocators = ( self.arena.find("**/team0CamPos_locator"), self.arena.find("**/team1CamPos_locator") ) self.teamCamAimLocators = ( self.arena.find("**/team0CamAim_locator"), self.arena.find("**/team1CamAim_locator"), ) # Setup team locators # Toons are parented to these guys in order to do # Orthowalk properly leftTeamLocator = NodePath("TeamLocator-%d" % PartyGlobals.TeamActivityTeams.LeftTeam) leftTeamLocator.reparentTo(self.root) leftTeamLocator.setH(90) rightTeamLocator = NodePath("TeamLocator-%d" % PartyGlobals.TeamActivityTeams.RightTeam) rightTeamLocator.reparentTo(self.root) rightTeamLocator.setH(-90) self.teamLocators = ( leftTeamLocator, rightTeamLocator ) # Used to place the toons in even spaces self._lengthBetweenEntrances = self.leftEntranceLocator.getY() - self.rightExitLocator.getY() # Setup Sky Collisions. Important for cannons. self._skyCollisionsCollection = self.arena.findAllMatches("**/cogPieArena_sky*_collision") if len(self._skyCollisionsCollection) > 0: self._skyCollisionParent = self._skyCollisionsCollection[0].getParent() else: self._skyCollisionParent = self.arena # Get all the wall collisions: self._wallCollisionsCollection = self.arena.findAllMatches("**/cogPieArena_wall*_collision") # Get a hold of the flags: self._arenaFlagGroups = ( self.arena.find("**/flagsL_grp"), self.arena.find("**/flagsR_grp") ) self._initArenaDoors() # Setup Cogs self.cogManager = PartyCogManager() self.arrows = [] self.distanceLabels = [] self.teamColors = list(PartyGlobals.CogActivityColors) + [PartyGlobals.TeamActivityStatusColor] for i in range(3): start = self.arena.find("**/cog%d_start_locator" % (i+1)) end = self.arena.find("**/cog%d_end_locator" % (i+1)) cog = self.cogManager.generateCog(self.arena) cog.setEndPoints(start.getPos(), end.getPos()) arrow1 = StretchingArrow(self.arena, useColor="orange") arrow2 = StretchingArrow(self.arena, useColor="blue") arrow1.setZ(0.1) arrow2.setZ(0.1) self.arrows.append([arrow1, arrow2]) distanceLabel = self.createDistanceLabel(0, self.teamColors[1]) distanceLabel[0].stash() distanceLabel2 = self.createDistanceLabel(0, self.teamColors[0]) distanceLabel2[0].stash() self.distanceLabels.append([distanceLabel, distanceLabel2]) self.winText = [] text1 = self.createText(0, Point3(-0.5,0.0,-0.5), self.teamColors[1]) text2 = self.createText(1, Point3(0.5,0.0,-0.5), self.teamColors[0]) self.winText.append(text1) self.winText.append(text2) self.winStatus = self.createText(2, Point3(0.0,0.0,-0.8), self.teamColors[0]) signLocator = self.arena.find("**/eventSign_locator") self.activity.sign.setPos(signLocator.getPos(self.root)) self.enable() def _initArenaDoors(self): """Initializes arena door locators, timers, and animations""" # Setup doors self._arenaDoors = ( self.arena.find("**/doorL"), self.arena.find("**/doorR"), ) arenaDoorLocators = ( self.arena.find("**/doorL_locator"), self.arena.find("**/doorR_locator") ) # Reparent those locators to the doors. for i in range(len(arenaDoorLocators)): arenaDoorLocators[i].wrtReparentTo(self._arenaDoors[i]) self._arenaDoorTimers = ( self.createDoorTimer(PartyGlobals.TeamActivityTeams.LeftTeam), self.createDoorTimer(PartyGlobals.TeamActivityTeams.RightTeam) ) self._arenaDoorIvals = [None, None] self._doorStartPos = [] for i in range(len(self._arenaDoors)): door = self._arenaDoors[i] timer = self._arenaDoorTimers[i] timer.reparentTo(arenaDoorLocators[i]) timer.hide() self._doorStartPos.append(door.getPos()) door.setPos(door, 0, 0, -7.0) def _destroyArenaDoors(self): for ival in self._arenaDoorIvals: ival.finish() self._arenaDoorIvals = None self._arenaDoors = None for timer in self._arenaDoorTimers: timer.stop() timer.removeNode() self._arenaDoorTimers = None def createDoorTimer(self, team): timer = ToontownTimer(useImage=False, highlightNearEnd=False) timer["text_font"] = ToontownGlobals.getMinnieFont() timer.setFontColor(PartyGlobals.CogActivityColors[team]) timer.setScale(7.0) timer.setPos(0.2, -0.03, 0.0) return timer def createText(self, number, position, color): text = TextNode("winText%d"%number) text.setAlign(TextNode.ACenter) text.setTextColor(color) text.setFont(ToontownGlobals.getSignFont()) text.setText("") noteText = aspect2d.attachNewNode(text) noteText.setScale(0.2) noteText.setPos(position) noteText.stash() return text, noteText def createDistanceLabel(self, number, color): text = TextNode("distanceText-%d" % number) text.setAlign(TextNode.ACenter) text.setTextColor(color) text.setFont(ToontownGlobals.getSignFont()) text.setText("10 ft") node = self.root.attachNewNode(text) node.setBillboardPointEye() node.setScale(2.5) node.setZ(5.0) return (node, text) def unload(self): self.disable() self._cleanupResultsIval() if self.winText is not None: for pair in self.winText: pair[1].reparentTo(hidden) pair[1].removeNode() self.winText = None if self.winStatus is not None: self.winStatus[1].reparentTo(hidden) self.winStatus[1].removeNode() self.winStatus = None if self.cogManager is not None: self.cogManager.unload() self.cogManager = None if self.arrows is not None: for pair in self.arrows: for arrow in pair: arrow.destroy() arrow = None pair = None self.arrows = None if self.distanceLabels is not None: for pair in self.distanceLabels: for (node, text) in pair: node.removeNode() pair = None self.distanceLabels = None if len(self.players): for player in self.players.values(): player.disable() player.destroy() self.players.clear() self.player = None if self.arena is not None: self.leftEntranceLocator = None self.rightEntranceLocator = None self.leftExitLocator = None self.rightExitLocator = None self._skyCollisions = None self._skyCollisionParent = None self._arenaFlagGroups = None self._destroyArenaDoors() self.arena.removeNode() self.arena = None for ival in self.toonPieTracks.values(): if ival is not None and ival.isPlaying(): ival.finish() self.toonPieTracks = {} for ival in self.pieIvals: if ival is not None and ival.isPlaying(): ival.finish() self.pieIvals = [] self.toonIdsToAnimIntervals = {} for eventName in self.toonPieEventNames.values(): self.ignore(eventName) self.toonPieEventNames = {} def enable(self): self.enableEnterGateCollision() def disable(self): self.disableEnterGateCollision() self.ignoreAll() def hideTeamFlags(self, team): self._arenaFlagGroups[team].stash() def showTeamFlags(self, team): self._arenaFlagGroups[team].unstash() def _playArenaDoorIval(self, team, opening=True): ival = self._arenaDoorIvals[team] if ival is not None and ival.isPlaying(): ival.pause() if not opening: pos = self._doorStartPos[team] else: pos = self._doorStartPos[team] + Point3(0, 0, -7.0), ival = self._arenaDoors[team].posInterval( 0.75, pos, blendType="easeIn" ) self._arenaDoorIvals[team] = ival ival.start() def openArenaDoorForTeam(self, team): self._playArenaDoorIval(team, opening=True) def closeArenaDoorForTeam(self, team): self._playArenaDoorIval(team, opening=False) def openArenaDoors(self): self.enableEnterGateCollision() for i in range(len(self._arenaDoors)): self.openArenaDoorForTeam(i) def closeArenaDoors(self): self.disableEnterGateCollision() for i in range(len(self._arenaDoors)): self.closeArenaDoorForTeam(i) def showArenaDoorTimers(self, duration): for timer in self._arenaDoorTimers: timer.setTime(duration) timer.countdown(duration) timer.show() def hideArenaDoorTimers(self): for timer in self._arenaDoorTimers: timer.hide() def enableEnterGateCollision(self): self.acceptOnce("entercogPieArena_entranceLeft_collision", self.handleEnterLeftEntranceTrigger) self.acceptOnce("entercogPieArena_entranceRight_collision", self.handleEnterRightEntranceTrigger) def disableEnterGateCollision(self): self.ignore("entercogPieArena_entranceLeft_collision") self.ignore("entercogPieArena_entranceRight_collision") def enableWallCollisions(self): self._wallCollisionsCollection.unstash() def disableWallCollisions(self): self._wallCollisionsCollection.stash() def enableSkyCollisions(self): self._skyCollisionsCollection.unstash() def disableSkyCollisions(self): self._skyCollisionsCollection.stash() def handleEnterLeftEntranceTrigger(self, collEntry): assert(self.notify.debug("handleEnterGateCollision")) self.activity.d_toonJoinRequest(PartyGlobals.TeamActivityTeams.LeftTeam) def handleEnterRightEntranceTrigger(self, collEntry): assert(self.notify.debug("handleEnterGateCollision")) self.activity.d_toonJoinRequest(PartyGlobals.TeamActivityTeams.RightTeam) def checkOrthoDriveCollision(self, oldPos, newPos): """Used by OrthoDrive to guarantee that the toon's pos stays inside the play area""" x = bound(newPos[0], -16.8, 16.8) y = bound(newPos[1], -17.25, -24.1) newPos.setX(x) newPos.setY(y) return newPos def getPlayerStartPos(self, team, spot): if team == PartyGlobals.TeamActivityTeams.LeftTeam: node = self.leftExitLocator else: node = self.rightExitLocator d = self._lengthBetweenEntrances / (self.activity.getMaxPlayersPerTeam() + 1) yOffset = node.getY(self.root) + d * (spot + 1) pos = node.getPos(self.root) pos.setY(yOffset) return pos def handleToonJoined(self, toon, team, lateEntry=False): pos = self.getPlayerStartPos(team, self.activity.getIndex(toon.doId, team)) if toon == base.localAvatar: player = PartyCogActivityLocalPlayer(self.activity, pos, team, self.handleToonExited) player.entersActivity() self.player = player self.disableSkyCollisions() self.playPlayerEnterIval() else: player = PartyCogActivityPlayer(self.activity, toon, pos, team) player.entersActivity() # This only happens if the toon is joining after the activity has started if lateEntry: player.updateToonPosition() self.players[toon.doId] = player def handleToonSwitchedTeams(self, toon): toonId = toon.doId player = self.players.get(toonId) if player is None: self.notify.warning("handleToonSwitchedTeams: toonId %s not found" % toonId) return team = self.activity.getTeam(toonId) spot = self.activity.getIndex(toonId, team) pos = self.getPlayerStartPos(team, spot) self.finishToonIval(toonId) player.setTeam(team) player.setToonStartPosition(pos) player.updateToonPosition() def handleToonShifted(self, toon): toonId = toon.doId if self.players.has_key(toonId): player = self.players[toonId] spot = self.activity.getIndex(toonId, player.team) pos = self.getPlayerStartPos(player.team, spot) player.setToonStartPosition(pos) if self.player is not None and toon == self.player.toon: self.playToonIval( base.localAvatar.doId, self.player.getRunToStartPositionIval() ) def handleToonDisabled(self, toonId): self.finishToonIval(toonId) player = self.players.get(toonId) if player is not None: player.disable() if player == self.player: self.player = None del self.players[toonId] def playPlayerEnterIval(self): # Note: Disable "Switch Team" button while running b/c an unknown, bad interaction between # LerpPosInterval and startPosHprBroadcast (both in the run ival) causes the toon to be # immobile for approx. 200 ms or more if we call ival.finish(). def conditionallyShowSwitchButton(self=self, enable=True): if enable and self.activity.activityFSM.state in ["WaitForEnough", "WaitToStart"]: self.activity.teamActivityGui.enableSwitchButton() else: self.activity.teamActivityGui.disableSwitchButton() ival = Sequence( Func(self.disableWallCollisions), Func(conditionallyShowSwitchButton, self, False), self.player.getRunToStartPositionIval(), Func(conditionallyShowSwitchButton, self, True), Func(self.enableWallCollisions) ) self.playToonIval(base.localAvatar.doId, ival) def finishToonIval(self, toonId): if self.toonIdsToAnimIntervals.get(toonId) is not None and \ self.toonIdsToAnimIntervals[toonId].isPlaying(): self.toonIdsToAnimIntervals[toonId].finish() def playToonIval(self, toonId, ival): self.finishToonIval(toonId) self.toonIdsToAnimIntervals[toonId] = ival ival.start() def startActivity(self, timestamp): self.pieHandler = CollisionHandlerEvent() self.pieHandler.setInPattern('pieHit-%fn') if self.player is not None: self.player.resetScore() self.hideTeamFlags(self.player.team) for player in self.players.values(): self.finishToonIval(player.toon.doId) player.enable() for cog in self.cogManager.cogs: cog.request("Active", timestamp) for ival in self.pieIvals: if ival.isPlaying(): ival.finish() self.pieIvals = [] def stopActivity(self): for player in self.players.values(): player.disable() for eventName in self.toonPieEventNames.values(): self.ignore(eventName) self.toonPieEventNames.clear() for cog in self.cogManager.cogs: cog.request("Static") def handleToonExited(self, toon): self.finishToonIval(toon.doId) player = self.players[toon.doId] player.disable() player.exitsActivity() player.destroy() if player == self.player: self.showTeamFlags(self.activity.getTeam(toon.doId)) self.player = None self.enableEnterGateCollision() self.enableSkyCollisions() del self.players[toon.doId] def pieThrow(self, avId, timestamp, heading, pos, power): """Show local or remote toon throwing a pie.""" toon = self.activity.getAvatar(avId) if toon is None: return tossTrack, pieTrack, flyPie = self.getTossPieInterval(toon, pos[0], pos[1], pos[2] , heading, 0, 0, power) if avId == base.localAvatar.doId: flyPie.setTag('throwerId', str(avId)) collSphere = CollisionSphere(0, 0, 0, 0.5) # Make the sphere intangible collSphere.setTangible(0) name = "PieSphere-%d" % avId collSphereName = self.activity.uniqueName(name) collNode = CollisionNode(collSphereName) collNode.setFromCollideMask(ToontownGlobals.PieBitmask) collNode.addSolid(collSphere) collNP = flyPie.attachNewNode(collNode) base.cTrav.addCollider(collNP, self.pieHandler) self.toonPieEventNames[collNP] = 'pieHit-' + collSphereName self.accept(self.toonPieEventNames[collNP], self.handlePieCollision) else: player = self.players.get(avId) if player is not None: player.faceForward() def matchRunningAnim(toon=toon): toon.playingAnim = None toon.setSpeed(toon.forwardSpeed, toon.rotateSpeed) newTossTrack = Sequence(tossTrack, Func(matchRunningAnim)) pieTrack = Parallel( newTossTrack, pieTrack, name="PartyCogActivity.pieTrack-%d-%s" % (avId, timestamp) ) elapsedTime = globalClockDelta.localElapsedTime(timestamp) if elapsedTime < 16. / 24.: elapsedTime = 16. / 24. # make the pie fly immediately pieTrack.start(elapsedTime) self.pieIvals.append(pieTrack) self.toonPieTracks[avId] = pieTrack def getTossPieInterval( self, toon, x, y, z, h, p, r, power, beginFlyIval=Sequence()): """Adapted from toon.py to suit our needs. Returns (toss, pie, flyPie), where toss is an interval to animate the toon tossing a pie, pie is the interval to animate the pie flying through the air, and pieModel is the model that flies. This is used in the final BossBattle sequence of CogHQ when we all throw pies directly at the boss cog. """ from toontown.toonbase import ToontownBattleGlobals from toontown.battle import BattleProps pie = toon.getPieModel() pie.setScale(0.5) flyPie = pie.copyTo(NodePath('a')) pieName = ToontownBattleGlobals.pieNames[toon.pieType] pieType = BattleProps.globalPropPool.getPropType(pieName) animPie = Sequence() if pieType == 'actor': animPie = ActorInterval(pie, pieName, startFrame = 48) sound = loader.loadSfx('phase_3.5/audio/sfx/AA_pie_throw_only.mp3') # First, create a ProjectileInterval to compute the relative # velocity. assert 0 <= power <= 100, "invalid pie throw power %s" % power t = power / 100.0 # Distance ranges from CogActivityPieMinDist to CogActivityPieMaxDist ft, time ranges from 1 to 1.5 s. dist = lerp(PartyGlobals.CogActivityPieMinDist, PartyGlobals.CogActivityPieMaxDist, t) time = lerp(1.0, 1.5, t) proj = ProjectileInterval( None, startPos=Point3(0, 0, 0), endPos=Point3(0, dist, 0), duration=time ) relVel = proj.startVel def getVelocity(toon = toon, relVel = relVel): return render.getRelativeVector(toon, relVel) * 0.6 toss = Track( (0, Sequence(Func(toon.setPosHpr, x, y, z, h, p, r), Func(pie.reparentTo, toon.rightHand), Func(pie.setPosHpr, 0, 0, 0, 0, 0, 0), animPie, Parallel( ActorInterval( toon, 'throw', startFrame=48, #duration=0.25, #self.throwPieLimitTime, playRate=1.5, partName='torso' ), animPie ), Func(toon.setAnimState, 'Happy'), )), (16./24., Func(pie.detachNode))) fly = Track( (14./24., SoundInterval(sound, node = toon, cutOff=PartyGlobals.PARTY_COG_CUTOFF)), (16./24., Sequence(Func(flyPie.reparentTo, render), Func(flyPie.setPosHpr, toon, 0.52, 0.97, 2.24, 0, -45, 0), beginFlyIval, ProjectileInterval(flyPie, startVel = getVelocity , duration = 6), #LerpPosInterval(flyPie, duration = 3, Point3(0.52,50,2.24)), Func(flyPie.detachNode), )), ) return (toss, fly, flyPie) def handlePieCollision(self, colEntry): """Handle the pie thrown by the local toon hitting something.""" if not self.activity.isState("Active") or self.player is None: return handled = False into = colEntry.getIntoNodePath() intoName = into.getName() timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32) if "PartyCog" in intoName: if self.toonPieTracks.get(base.localAvatar.doId) is not None: self.toonPieTracks[base.localAvatar.doId].finish() self.toonPieTracks[base.localAvatar.doId] = None parts = intoName.split('-') cogID = int(parts[1]) point = colEntry.getSurfacePoint(self.cogManager.cogs[cogID].root) cog = self.cogManager.cogs[cogID] hitHead = ((point.getZ() > cog.getHeadLocation()) and not parts[2].startswith("Arm")) if self.activity.getTeam(base.localAvatar.doId) == PartyGlobals.TeamActivityTeams.LeftTeam: direction = -1.0 else: direction = 1.0 self.activity.b_pieHitsCog( timestamp, cogID, point, direction, hitHead ) if hitHead: hitPoints = self.player.hitHead() else: hitPoints = self.player.hitBody() self.player.updateScore() if hitPoints > 0: cog.showHitScore(hitPoints) handled = True elif "distAvatarCollNode" in intoName: parts = intoName.split('-') hitToonId = int(parts[1]) toon = base.cr.doId2do.get(hitToonId) if toon is not None and self.activity.getTeam(hitToonId) != self.player.team: point = colEntry.getSurfacePoint(toon) self.activity.b_pieHitsToon(hitToonId, timestamp, point) handled = True # Ignore other collision events if this collision was handled. if handled: eventName = self.toonPieEventNames.get(colEntry.getFromNodePath()) if eventName is not None: self.ignore(eventName) del self.toonPieEventNames[colEntry.getFromNodePath()] def pieHitsCog(self, timestamp, cogNum, pos, direction, part): """A toon hit the suit, make the suit do something.""" cog = self.cogManager.cogs[cogNum] cog.respondToPieHit(timestamp, pos, part, direction) def pieHitsToon(self, toonId, timestamp, pos): player = self.players.get(toonId) if player is not None: player.respondToPieHit(timestamp, pos) def setCogDistances(self, distances): self.cogManager.updateDistances(distances) def showCogs(self): for cog in self.cogManager.cogs: cog.request("Static") def hideCogs(self): for cog in self.cogManager.cogs: cog.request("Down") def showResults(self, resultsText, winner, totals): if self.player is None: return base.localAvatar.showName() self.resultsIval = Sequence( Wait(0.1), Func(self.activity.setStatus, TTLocalizer.PartyCogTimeUp), Func(self.activity.showStatus), Wait(2.0), Func(self.activity.hideStatus), Wait(0.5), Func(self.player.lookAtArena), Func(self.showTeamFlags, self.activity.getTeam(base.localAvatar.doId)), Wait(1.0), Func(self.showArrow, 0), Wait(1.3), Func(self.showArrow, 1), Wait(1.3), Func(self.showArrow, 2), Wait(1.3), Func(self.showTotals, totals), Wait(1.0), Func(self.showWinner, resultsText, winner), Func(self._cleanupResultsIval), name="PartyCog-conclusionSequence") # Cancel the rewards ival if the jellybean screen pops up. If this happens it means the client # is lagging; the rewards screen tears down the GUI, which this ival uses. self.accept('DistributedPartyActivity-showJellybeanReward', self._cleanupResultsIval) self.resultsIval.start() def _cleanupResultsIval(self): if self.resultsIval: if self.resultsIval.isPlaying(): self.resultsIval.pause() self.resultsIval = None self.ignore('DistributedPartyActivity-showJellybeanReward') def showTotals(self, totals): newtotals = ( totals[1] - totals[0] + (PartyGlobals.CogActivityArenaLength/2.0)*3, totals[0] - totals[1] + (PartyGlobals.CogActivityArenaLength/2.0)*3 ) self.winText[0][0].setText(TTLocalizer.PartyCogDistance % newtotals[0]) self.winText[1][0].setText(TTLocalizer.PartyCogDistance % newtotals[1]) for textPair in self.winText: textPair[1].unstash() def hideTotals(self): for textPair in self.winText: textPair[0].setText("") textPair[1].stash() def showWinner(self, text, winner): self.winStatus[0].setText(text) self.winStatus[0].setTextColor(self.teamColors[winner]) self.winStatus[1].unstash() def hideWinner(self): self.winStatus[0].setText("") self.winStatus[1].stash() def showArrow(self, arrowNum): arrows = self.arrows[arrowNum] cog = self.cogManager.cogs[arrowNum] points = [self.arena.find("**/cog%d_start_locator" % (arrowNum+1)), self.arena.find("**/cog%d_end_locator" % (arrowNum+1))] Y = cog.root.getY() for point in points: point.setY(Y) for i in range(len(arrows)): arrow = arrows[i] arrow.draw(points[i].getPos(), cog.root.getPos(), animate=False) arrow.unstash() i=-1 length = PartyGlobals.CogActivityArenaLength for (node, text) in self.distanceLabels[arrowNum]: current = bound(i, 0, 1) node.setPos(cog.root.getPos(self.root) + Point3(i * 4, 2, 4)) dist = PartyCogUtils.getCogDistanceUnitsFromCenter(cog.currentT) dist = abs(dist - (i*length/2)) #if i == -1: # dist = length/2 + -i*dist if dist > (length-dist): node.setScale(2.8) else: node.setScale(2.2) text.setText(TTLocalizer.PartyCogDistance % dist) if dist > 0: node.unstash() else: arrows[current].stash() i += 2 def hideArrows(self): for pair in self.arrows: for arrow in pair: arrow.stash() for pair in self.distanceLabels: for (node, text) in pair: node.stash() def hideResults(self): self.hideArrows() self.hideTotals() self.hideWinner()