class JugglingBalls(ToonUpGag): def __init__(self): ToonUpGag.__init__(self, CIGlobals.JugglingBalls, 'phase_5/models/props/cubes-mod.bam', 90, 120, 100, GagGlobals.JUGGLE_SFX, 1, anim='phase_5/models/props/cubes-chan.bam') self.setImage('phase_3.5/maps/juggling-cubes.png') self.track = None self.soundInterval = None return def start(self): super(JugglingBalls, self).start() self.setupHips() self.build() self.placeProp(self.hips, self.gag) self.soundInterval = self.getSoundTrack(0.7, self.gag, 7.7) propInterval = Sequence() propInterval.append(ActorInterval(self.gag, 'chan')) if self.avatar == base.localAvatar: propInterval.append(Func(self.setHealAmount)) propInterval.append(Func(self.healNearbyAvatars, 25)) propInterval.append(Func(self.cleanupGag)) propInterval.append(Func(self.reset)) self.track = Parallel(ActorInterval(self.avatar, 'juggle'), propInterval, Func(self.soundInterval.start)) self.track.start() def equip(self): super(JugglingBalls, self).equip() def unEquip(self): if self.track: self.soundInterval.finish() self.track.finish() self.track = None self.reset() return
def movementTask( self, task ): # show and hide depending on distance to camera if (base.camera.getPos( render ) - self.getPos()).length() > 100.0: self.pandaActor.hide() else: self.pandaActor.show() try: # calculate time passed / we cant use task.time in a doMethodLater deltaT = time.time() - self.oldTaskTime # save current time self.oldTaskTime = time.time() except: # save current time self.oldTaskTime = time.time() deltaT = 0.0 # get future rotation and position rot = self.getRotation( UPDATETIME, random.randint( -10, 10) ) pos = self.getForwardPos( UPDATETIME * (random.random()/2.0+1.0) ) posZ = self.getHeight( (pos.getX(), pos.getY()) ) pos.setZ( posZ ) # create movement and rotation intervals myInterval1=self.posInterval(UPDATETIME*1.25,pos) myInterval2=self.hprInterval(UPDATETIME*1.25,rot) # myInterval1=self.globalPandaNode.posInterval(UPDATETIME*1.25,pos) # myInterval2=self.globalPandaNode.hprInterval(UPDATETIME*1.25,rot) myParallel=Parallel(myInterval1,myInterval2) myParallel.start() return Task.again
def getSwapVisibleIval(self, wait = 5.0, tFadeOut = 3.0, tFadeIn = 3.0): loader = base.cr.playGame.hood.loader npl = render.findAllMatches('**/=DNARoot=holiday_prop;+s') p = Parallel() for i in range(npl.getNumPaths()): np = npl.getPath(i) np.setTransparency(TransparencyAttrib.MDual, 1) if not np.hasTag('DNACode'): continue dnaCode = np.getTag('DNACode') dnaNode = self.dnaStore.findNode(dnaCode) if dnaNode.isEmpty(): continue newNP = dnaNode.copyTo(np.getParent()) newNP.setTag('DNARoot', 'holiday_prop') newNP.setTag('DNACode', dnaCode) newNP.setColorScale(1, 1, 1, 0) newNP.setTransparency(TransparencyAttrib.MDual, 1) if np.hasTag('transformIndex'): index = int(np.getTag('transformIndex')) transform = loader.holidayPropTransforms.get(index, TransformState.makeIdentity()) newNP.setTransform(NodePath(), transform) newNP.setTag('transformIndex', `index`) s = Sequence(Wait(wait), np.colorScaleInterval(tFadeOut, Vec4(1, 1, 1, 0), startColorScale=Vec4(1, 1, 1, 1), blendType='easeInOut'), Func(np.detachNode), Func(np.clearTransparency), newNP.colorScaleInterval(tFadeOut, Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0), blendType='easeInOut'), Func(newNP.clearTransparency), Func(newNP.clearColorScale)) p.append(s) return p
def doSpray(self, scaleUp, scaleDown, hold): base.audio3d.attachSoundToObject(self.spraySfx, self.gag) self.spraySfx.play() spraySequence = Sequence(Func(self.getSprayTrack(self.origin, self.sprayRange, scaleUp, hold, scaleDown).start)) sprayParallel = Parallel() sprayParallel.append(Func(spraySequence.start)) sprayParallel.start()
def enterFinalResults(self): lerpTrack = Parallel() lerpDur = 0.5 tY = 0.6 bY = -0.05 lX = -0.5 cX = 0 rX = 0.5 scorePanelLocs = ( ((cX, bY),), ((lX, bY), (rX, bY)), ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY), (lX, bY), (rX, bY)), ) scorePanelLocs = scorePanelLocs[self.numPlayers - 1] for i in xrange(self.numPlayers): panel = self.scorePanels[i] pos = scorePanelLocs[i] panel.wrtReparentTo(aspect2d) lerpTrack.append( Parallel( LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType="easeInOut"), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType="easeInOut"), ) ) self.showScoreTrack = Parallel( lerpTrack, Sequence(Wait(IceGameGlobals.ShowScoresDuration), Func(self.gameOver)) ) self.showScoreTrack.start()
def activeAnim(self): self.cam_anim_enter = Parallel(name="cam gates enter") self.cam_anim_enter.append(camera.posInterval(1,Point3(0,-29,25))) self.cam_anim_enter.append(self.gates.posInterval(1,Point3(0,9,0))) self.cam_anim_exit = Parallel(name="cam gates exit") self.cam_anim_exit.append(camera.posInterval(1,Point3(0,-34,25))) self.cam_anim_exit.append(self.gates.posInterval(1,Point3(0,14,0)))
def toggle(self): self.visible = not self.visible self.debug("Toggle buffer viewer") if self.currentGUIEffect is not None: self.currentGUIEffect.finish() if not self.visible: self.currentGUIEffect = Sequence( self.parent.colorScaleInterval( 0.12, Vec4(1, 1, 1, 0), blendType="easeIn"), Func(self.parent.hide) ) self.currentGUIEffect.start() else: self.renderBuffers() self.parent.show() self.currentGUIEffect = Parallel( self.parent.colorScaleInterval( 0.12, Vec4(1, 1, 1, 1), blendType="easeIn"), ) self.currentGUIEffect.start()
def _toggleGUI(self): self.debug("Toggle overlay") if self.currentGUIEffect is not None: self.currentGUIEffect.finish() if not self.guiActive: self.currentGUIEffect = Parallel( self.watermark.posInterval( 0.4, self.watermark.getInitialPos() + Vec3(0, 0, 200), blendType="easeIn"), self.showDebugger.posInterval( 0.4, self.showDebugger.getInitialPos() + Vec3(0, 0, 400), blendType="easeIn"), self.debuggerParent.posInterval( 0.3, Vec3(0, 0, 0), blendType="easeOut"), ) self.currentGUIEffect.start() else: self.currentGUIEffect = Parallel( self.watermark.posInterval( 0.4, self.watermark.getInitialPos(), blendType="easeOut"), self.showDebugger.posInterval( 0.4, self.showDebugger.getInitialPos(), blendType="easeOut"), self.debuggerParent.posInterval( 0.3, Vec3(-350, 0, 0), blendType="easeInOut"), ) self.currentGUIEffect.start() self.guiActive = not self.guiActive
def getScaleBlendIntervals(self, props, duration, startScale, endScale, blendType): tracks = Parallel() if not isinstance(props, list): props = [props] for prop in props: tracks.append(LerpScaleInterval(prop, duration, endScale, startScale=startScale, blendType=blendType)) return tracks
def getScaleTrack(self, props, duration, startScale, endScale): track = Parallel() if not isinstance(props, list): props = [props] for prop in props: track.append(LerpScaleInterval(prop, duration, endScale, startScale=startScale)) return track
def showPath(self, fr, to): path = set() showSquareSequences = Parallel() if self.pieces[fr]: path.update(self.pieces[fr].path(to)) for sq in path: showSquareSequences.append(self.showSquare(sq)) return showSquareSequences
def AnimateIn(self, blade): x, y, z = blade.getPos() ending_position = (self.originals[blade]) position1 = blade.posInterval(1, ending_position, (x, y, z)) rotate1 = blade.hprInterval(1, (0, 0, 0), blade.getHpr()) scale1 = blade.scaleInterval(1, (1, 1, 1), blade.getScale()) move = Parallel(position1, rotate1, scale1, name="move") move.start() blade.setTag('state', 'in')
def AnimateOut(self, blade): x, y, z = blade.getPos() self.originals[blade] = (x, y, z) ending_position = (40 + random.uniform(0,120), y-(random.uniform(20,100)), z + random.uniform(-10,50)) position1 = blade.posInterval(1, ending_position, (x, y, z)) rotate1 = blade.hprInterval(1, (90, 0, 0), blade.getHpr()) scale1 = blade.scaleInterval(1, (2, 2, 2), blade.getScale()) move = Parallel(position1, rotate1, scale1, name="move") move.start() blade.setTag('state', 'out')
def start(self): SoundGag.start(self) tracks = Parallel() delay = 2.45 INSTRUMENT_SCALE_MODIFIER = 0.5 instrMin = Vec3(0.001, 0.001, 0.001) instrMax1 = Vec3(1.7, 1.7, 1.7) instrMax1 *= INSTRUMENT_SCALE_MODIFIER instrMax2 = Vec3(2.2, 2.2, 2.2) instrMax2 *= INSTRUMENT_SCALE_MODIFIER instrStretch = Vec3(0.4, 0.4, 0.4) instrStretch *= INSTRUMENT_SCALE_MODIFIER head = self.gag.find('**/opera_singer') head.setPos(0, 0, 0) def setInstrumentStats(): newPos = Vec3(-0.8, -0.9, 0.2) newPos *= 1.3 self.gag.setPos(newPos[0], newPos[1], newPos[2]) self.gag.setHpr(145, 0, 90) self.gag.setScale(instrMin) megaphoneShow = Sequence(Func(self.placeProp, self.handJoint, self.megaphone), Func(self.placeProp, self.handJoint, self.gag), Func(setInstrumentStats)) grow1 = self.getScaleBlendIntervals(self.gag, duration=1, startScale=instrMin, endScale=instrMax1, blendType='easeOut') grow2 = self.getScaleBlendIntervals(self.gag, duration=1.1, startScale=instrMax1, endScale=instrMax2, blendType='easeIn') shrink2 = self.getScaleIntervals(self.gag, duration=0.1, startScale=instrMax2, endScale=instrMin) instrumentAppear = Parallel(Sequence(grow1, grow2, Wait(6.0), shrink2, Wait(0.4), Func(self.finish)), SoundInterval(self.appearSfx, node=self.avatar)) delayTime = delay megaphoneTrack = Sequence(megaphoneShow, Wait(delayTime + 1.0), instrumentAppear) tracks.append(megaphoneTrack) toonTrack = self.__createToonInterval(0) tracks.append(toonTrack) soundTrack = Sequence(Wait(delayTime), Parallel(SoundInterval(self.soundSfx, node=self.avatar), Func(self.damageCogsNearby))) tracks.append(soundTrack) tracks.start()
def append(self,text,width,height,spacing = 0, fadein = 0, fadeinType = 0): '''Add a NodePath that contains a generated text geom This method is called by SogalText ''' self.__lock.acquire() self.items.append(text) text.reparentTo(self) textPos = self.currentPtr text.setPos(textPos) if fadein: interval = Parallel() if fadeinType == 0 or fadeinType == 'normal': interval.append(LerpFunc(_modifyAlphaScale,fadein,0,1,blendType = 'easeOut',extraArgs = [text])) if fadeinType == 1 or fadeinType == 'flyin': interval.append(LerpFunc(_modifyAlphaScale,fadein,0,1,blendType = 'easeOut',extraArgs = [text])) interval.append(LerpPosInterval(text,fadein, self.currentPtr, (self.currentPtr[0],self.currentPtr[1],self.currentPtr[2] -0.3), blendType = 'easeOut')) interval.start() self.__lerpIntervals.append(interval) self.lineWidth = self.currentPtr[0] + width self.lineHeight = max(height, self.lineHeight) self.currentPtr = (self.lineWidth + spacing, 0, 0) self.__lock.release()
def construct(self): track = Sequence() # First, set the avatar's initial rotational components: track.append(Func(self.avatar.setQuat, self.quatA)) # Next, construct the rotate track: rotateTrack = Parallel() if self.animName is not None: rotateTrack.append( Func(self.avatar.setPlayRate, self.animPlayRate, self.animName) ) rotateTrack.append(Func(self.avatar.loop, self.animName)) if self.sfx is not None: rotateTrack.append( Func(base.playSfx, self.sfx, looping=1, node=self.avatar) ) rotateTrack.append(self.getQuatInterval()) track.append(rotateTrack) # Finally, clean up what is necessary: if self.animName is not None: track.append(Func(self.avatar.setPlayRate, 1, self.animName)) if self.sfx is not None: track.append(Func(self.sfx.stop)) return track
def start(self): SoundGag.start(self) tracks = Parallel() delayTime = 2.45 delayUntilAppearSound = 1.0 INSTRUMENT_SCALE_MODIFIER = 0.5 instrMin = Vec3(0.001, 0.001, 0.001) instrMax1 = Vec3(0.1, 0.1, 0.1) instrMax1 *= INSTRUMENT_SCALE_MODIFIER instrMax2 = Vec3(0.3, 0.3, 0.3) instrMax2 *= INSTRUMENT_SCALE_MODIFIER instrStretch = Vec3(0.4, 0.4, 0.4) instrStretch *= INSTRUMENT_SCALE_MODIFIER def setInstrumentStats(): self.gag.setPos(-0.8, -0.9, 0.2) self.gag.setHpr(145, 0, 0) self.gag.setScale(instrMin) megaphoneSh = Sequence(Func(self.placeProp, self.handJoint, self.megaphone), Func(self.placeProp, self.handJoint, self.gag), Func(setInstrumentStats)) grow = self.getScaleIntervals(self.gag, duration=1, startScale=instrMin, endScale=instrMax1) instrumentAppear = Parallel(grow) stretchInstr = self.getScaleBlendIntervals(self.gag, duration=0.3, startScale=instrMax2, endScale=instrStretch, blendType='easeOut') backInstr = self.getScaleBlendIntervals(self.gag, duration=1.0, startScale=instrStretch, endScale=instrMin, blendType='easeIn') spinInstr = LerpHprInterval(self.gag, duration=1.5, startHpr=Vec3(145, 0, 0), hpr=Vec3(145, 0, 90), blendType='easeInOut') attackTrack = Parallel(Sequence(Wait(0.2), spinInstr), Sequence(stretchInstr, Wait(0.5), backInstr)) megaphoneTrack = Sequence(megaphoneSh, Wait(delayUntilAppearSound), SoundInterval(self.appearSfx, node=self.avatar), Wait(delayTime + 1.0), instrumentAppear) tracks.append(megaphoneTrack) tracks.append(ActorInterval(self.avatar, 'sound')) soundTrack = Sequence(Wait(delayTime), Parallel(attackTrack, SoundInterval(self.soundSfx, node=self.avatar), Func(self.damageCogsNearby), Wait(0.4), Func(self.finish))) tracks.append(soundTrack) tracks.start()
def handleMatch(self, cardA, cardB, withBonus): self.notify.debug('we got a match %d %d' % (cardA, cardB)) self.matches += 1 if cardA in self.faceUpList: self.faceUpList.remove(cardA) if cardB in self.faceUpList: self.faceUpList.remove(cardB) self.inactiveList.append(cardA) self.inactiveList.append(cardB) matchIval = Parallel() for card in [ cardA, cardB]: self.cards[card].setTransparency(1) cardSeq = Sequence(LerpColorScaleInterval(self.cards[card], duration = 1, colorScale = Vec4(1.0, 1.0, 1.0, 0.0)), Func(self.cards[card].hide)) matchIval.append(cardSeq) if withBonus: matchIval.append(SoundInterval(self.matchWithBonusSfx, node = self.cards[card], listenerNode = base.localAvatar, cutOff = 240)) else: matchIval.append(SoundInterval(self.matchSfx, node = self.cards[card], listenerNode = base.localAvatar, cutOff = 240)) matchIval.start() if len(self.inactiveList) == len(self.cards): self.sendUpdate('reportDone')
def start(self): SoundGag.start(self) INSTRUMENT_SCALE_MODIFIER = 0.5 delayTime = 2.45 delayUntilAppearSound = 1.0 tracks = Parallel() instrMin = Vec3(0.001, 0.001, 0.001) instrMax = Vec3(0.2, 0.2, 0.2) instrMax *= INSTRUMENT_SCALE_MODIFIER instrStretch = Vec3(0.25, 0.25, 0.25) instrStretch *= INSTRUMENT_SCALE_MODIFIER def setInstrumentStats(): self.gag.setPos(-1.2, -1.3, 0.1) self.gag.setHpr(145, 0, 85) self.gag.setScale(instrMin) megaphoneShow = Sequence(Func(self.placeProp, self.handJoint, self.megaphone), Func(self.placeProp, self.handJoint, self.gag), Func(setInstrumentStats)) grow = self.getScaleIntervals(self.gag, duration=0.2, startScale=instrMin, endScale=instrMax) instrumentAppear = grow stretchInstr = self.getScaleBlendIntervals(self.gag, duration=0.2, startScale=instrMax, endScale=instrStretch, blendType='easeOut') backInstr = self.getScaleBlendIntervals(self.gag, duration=0.2, startScale=instrStretch, endScale=instrMax, blendType='easeIn') attackTrack = Sequence(stretchInstr, backInstr) megaphoneTrack = Sequence(megaphoneShow, Wait(delayUntilAppearSound), SoundInterval(self.appearSfx, node=self.avatar), instrumentAppear) tracks.append(megaphoneTrack) tracks.append(ActorInterval(self.avatar, 'sound')) instrumentshrink = self.getScaleIntervals(self.gag, duration=0.1, startScale=instrMax, endScale=instrMin) soundTrack = Sequence(Wait(delayTime), Parallel(attackTrack, SoundInterval(self.soundSfx, node=self.avatar), Wait(0.2), instrumentshrink, Func(self.damageCogsNearby), Wait(0.4), Func(self.finish))) tracks.append(soundTrack) tracks.start()
def startEntity(self, cog): if not cog: self.completeSquirt() return scaleUpPoint = Point3(1.5, 1.5, 1.5) rainDelay = 1 effectDelay = 0.3 cloudHold = 4.7 tContact = 2.4 if cog.isDead(): cloudHold = 1.7 cloud01, trickleFx, rainEffects, entity = self.buildEntity() cloud01.setZ(cog.suitPlan.getNametagZ() + 2) cloud01.reparentTo(cog) cloud02 = Actor(self.model, {'chan': GagGlobals.getProp(4, 'stormcloud-chan')}) cloud02.reparentTo(cloud01) def damageCog(): if self.isLocal(): self.avatar.sendUpdate('suitHitByPie', [cog.doId, self.getID()]) def __getCloudTrack(cloud, useEffect = 1): track = Sequence(Func(cloud.pose, 'chan', 0), LerpScaleInterval(cloud, 1.5, scaleUpPoint, startScale=GagGlobals.PNT3NEAR0), Wait(rainDelay)) if useEffect == 1: pTrack = Parallel() delay = trickleDuration = cloudHold * 0.25 trickleTrack = ParticleInterval(trickleFx, cloud, worldRelative=0, duration=trickleDuration, cleanup=True) track.append(trickleTrack) for i in range(0, 3): dur = cloudHold - 2 * trickleDuration pTrack.append(Sequence(Wait(delay), ParticleInterval(rainEffects[i], cloud, worldRelative=0, duration=dur, cleanup=True))) delay += effectDelay pTrack.append(Sequence(Wait(3 * effectDelay), ActorInterval(cloud, 'chan', startTime=1, duration=cloudHold))) damageTrack = Sequence() if cog.getHealth() - self.getDamage() <= 0: damageTrack.append(Func(cog.d_disableMovement, wantRay=True)) damageTrack.append(Func(damageCog)) else: damageTrack.append(Wait(tContact)) damageTrack.append(Func(damageCog)) pTrack.append(damageTrack) track.append(pTrack) else: track.append(ActorInterval(cloud, 'chan', startTime=1, duration=cloudHold)) track.append(LerpScaleInterval(cloud, 0.5, GagGlobals.PNT3NEAR0)) track.append(Func(GagUtils.destroyProp, cloud)) return track tracks = Parallel() soundTrack01 = self.getSoundTrack(1.3, self.avatar) soundTrack02 = self.getSoundTrack(3.4, self.avatar) tracks.append(soundTrack01) tracks.append(soundTrack02) cloud01Track = __getCloudTrack(cloud01) cloud02Track = __getCloudTrack(cloud02, useEffect=0) tracks.append(cloud01Track) tracks.append(cloud02Track) tracks.append(Func(self.destroyEntity, entity)) tracks.start()
def __tickNearbyCogs(self): self.__selectNearbyCogs() tickTrack = Parallel() tickDuration = 0.4 for cog in self.selectedCogs: if not cog.isDead(): base.audio3d.attachSoundToObject(self.tickSfx, cog) tickTrack.append(Parallel(Sequence(LerpColorScaleInterval(cog, tickDuration, VBase4(1, 0, 0, 1)), Func(cog.clearColorScale), Func(cog.d_disableMovement)), SoundInterval(self.tickSfx, duration=tickDuration))) else: self.selectedCogs.remove(cog) return tickTrack
class Megaphone(ToonUpGag): def __init__(self): ToonUpGag.__init__(self, CIGlobals.Megaphone, 'phase_5/models/props/megaphone.bam', 10, 20, 100, GagGlobals.TELLJOKE_SFX, 1) self.setImage('phase_3.5/maps/megaphone.png') self.track = None self.soundInterval = None return def start(self): super(Megaphone, self).start() if not self.gag: self.build() if self.avatar == base.localAvatar: question, answer = random.choice(CIGlobals.ToonHealJokes) self.setupHandJoints() self.placeProp(self.handJoint, self.gag) self.soundInterval = self.getSoundTrack(self.avatar.getDuration('shout', fromFrame=0, toFrame=18), self.gag, 5.5) propInterval = Sequence() propInterval.append(Wait(self.avatar.getDuration('shout', fromFrame=0, toFrame=25))) if self.avatar == base.localAvatar: propInterval.append(Func(base.localAvatar.b_setChat, question)) propInterval.append(Wait(self.avatar.getDuration('shout', fromFrame=26, toFrame=75))) if self.avatar == base.localAvatar: propInterval.append(Func(base.localAvatar.b_setChat, answer)) propInterval.append(Wait(self.avatar.getDuration('shout', fromFrame=76, toFrame=118))) if self.avatar == base.localAvatar: propInterval.append(Func(self.setHealAmount)) propInterval.append(Func(self.healNearbyAvatars, 20)) propInterval.append(Wait(self.avatar.getDuration('shout', fromFrame=118))) propInterval.append(Func(self.cleanupGag)) propInterval.append(Func(self.reset)) self.track = Parallel(propInterval, ActorInterval(self.avatar, 'shout'), self.soundInterval) self.track.start() def equip(self): super(Megaphone, self).equip() self.build() def unEquip(self): if self.track: self.track.finish() self.track = None self.soundInterval = None self.cleanupGag() self.reset() return def cleanupGag(self): if self.gag: self.gag.removeNode() self.gag = None return
def showPathIfVisible(self, fr, to): if self.pieces[fr]: path = set() showSquareSequences = Parallel() if self.pieces[fr]: path.update(self.pieces[fr].path(to)) if any(self.isVisible(sq) for sq in path): for sq in path: showSquareSequences.append(self.showSquare(sq)) return showSquareSequences else: return Parallel()
def showSuitsFalling(self, suits, ts, name, callback): if self.bossCog is None: return suitTrack = Parallel() delay = 0 for suit in suits: suit.setState('Battle') if suit.dna.dept == 'l': suit.reparentTo(self.bossCog) suit.setPos(0, 0, 0) if suit in self.joiningSuits: i = len(self.pendingSuits) + self.joiningSuits.index(suit) destPos, h = self.suitPendingPoints[i] destHpr = VBase3(h, 0, 0) else: destPos, destHpr = self.getActorPosHpr(suit, self.suits) startPos = destPos + Point3(0, 0, SuitTimings.fromSky * ToontownGlobals.SuitWalkSpeed) self.notify.debug('startPos for %s = %s' % (suit, startPos)) suit.reparentTo(self) suit.setPos(startPos) suit.headsUp(self) moveIval = Sequence() chairInfo = self.bossCog.claimOneChair() if chairInfo: moveIval = self.createDinerMoveIval(suit, destPos, chairInfo) suitTrack.append( Track( (delay, Sequence( moveIval, Func( suit.loop, 'neutral'))))) delay += 1 if self.hasLocalToon(): camera.reparentTo(self) self.notify.debug('self.battleSide =%s' % self.battleSide) camHeading = -20 camX = -4 if self.battleSide == 0: camHeading = 20 camX = 4 camera.setPosHpr(camX, -15, 7, camHeading, 0, 0) done = Func(callback) track = Sequence(suitTrack, done, name=name) track.start(ts) self.storeInterval(track, name) return
class CogdoMazeSplattable: def __init__(self, object, name, collisionRadius): self.object = object self.splat = CogdoUtil.loadMazeModel('splash') self.splat.setBillboardPointEye() self.splat.setBin('fixed', 40) self.splat.setDepthTest(False) self.splat.setDepthWrite(False) self.splatTrack = None self._splatSfxIval = base.cogdoGameAudioMgr.createSfxIval('splat') self.initGagCollision(name, collisionRadius) return def destroy(self): self.disableGagCollision() if self._splatSfxIval.isPlaying(): self._splatSfxIval.finish() del self._splatSfxIval def initGagCollision(self, name, radius): self.gagCollisionName = name collision = CollisionTube(0, 0, 0, 0, 0, 4, radius) collision.setTangible(1) self.gagCollNode = CollisionNode(self.gagCollisionName) self.gagCollNode.setIntoCollideMask(ToontownGlobals.PieBitmask) self.gagCollNode.addSolid(collision) self.gagCollNodePath = self.object.attachNewNode(self.gagCollNode) def disableGagCollision(self): self.gagCollNodePath.removeNode() def doSplat(self): if self.splatTrack and self.splatTrack.isPlaying(): self.splatTrack.finish() self.splat.reparentTo(render) self.splat.setPos(self.object, 0, 0, 3.0) self.splat.setY(self.splat.getY() - 1.0) self._splatSfxIval.node = self.splat self.splatTrack = Parallel( self._splatSfxIval, Sequence( Func(self.splat.showThrough), LerpScaleInterval( self.splat, duration=0.5, scale=6, startScale=1, blendType='easeOut'), Func(self.splat.hide))) self.splatTrack.start()
def showToonThrowingGag(self, heading, pos): gag = self.equippedGag if gag is None: return self.removeGag() tossTrack, flyTrack, object = self.getThrowInterval(gag, pos[0], pos[1], pos[2], heading, 0, 0) def matchRunningAnim(toon = self.toon): toon.playingAnim = None toon.setSpeed(toon.forwardSpeed, toon.rotateSpeed) newTossTrack = Sequence(tossTrack, Func(matchRunningAnim)) throwTrack = Parallel(newTossTrack, flyTrack) throwTrack.start(0) return object
def exitAnim(self): if len(self.gameObject.postAnimationList) > 0: self.animSeq = Parallel(*self.gameObject.postAnimationList) self.animSeq.start() self.gameObject.animationList = [] self.gameObject.postAnimationList = []
def startConclusion(self): DistributedPartyCatchActivity.notify.debug('startConclusion') for avId in self.toonIds: if self.toonSDs.has_key(avId): toonSD = self.toonSDs[avId] toonSD.fsm.request('notPlaying') self.destroyCatchCollisions() if base.localAvatar.doId not in self.toonIds: return else: self.localToonExiting() if self.fruitsCaught >= self.numFruits: finishText = TTLocalizer.PartyCatchActivityFinishPerfect else: finishText = TTLocalizer.PartyCatchActivityFinish perfectTextSubnode = hidden.attachNewNode(self.__genText(finishText)) 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() 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)) soundTrack = SoundInterval(self.sndPerfect) self.finishIval = Parallel(textTrack, soundTrack) self.finishIval.start()
def doAttack(self, ts = 0): self.loadAttack() if hasattr(self.suit, 'uniqueName'): name = self.suit.uniqueName('doHangupAttack') else: name = 'doHangupAttack' if self.suit.type == 'A': delay2playSound = 1.0 delayAfterSoundToPlaceDownReceiver = 0.2 delayAfterShootToIgnoreCollisions = 1.0 delay2PickUpReceiver = 1.0 receiverInHandPos = Point3(-0.5, 0.5, -1) elif self.suit.type == 'B': delay2playSound = 1.5 delayAfterSoundToPlaceDownReceiver = 0.7 delayAfterShootToIgnoreCollisions = 1.0 delay2PickUpReceiver = 1.5 receiverInHandPos = Point3(-0.3, 0.5, -0.8) elif self.suit.type == 'C': delay2playSound = 1.0 delayAfterSoundToPlaceDownReceiver = 1.15 delayAfterShootToIgnoreCollisions = 1.0 delay2PickUpReceiver = 1.5 receiverInHandPos = Point3(-0.3, 0.5, -0.8) self.suitTrack = Parallel(name=name) self.suitTrack.append(ActorInterval(self.suit, 'phone')) self.suitTrack.append(Sequence(Wait(delay2playSound), SoundInterval(self.phoneSfx, duration=2.1), Wait(delayAfterSoundToPlaceDownReceiver), Func(self.receiver.setPos, 0, 0, 0), Func(self.receiver.setH, 0.0), Func(self.receiver.reparentTo, self.phone), Func(self.acceptOnce, 'enter' + self.collNP.node().getName(), self.handleCollision), Func(self.shootOut), Parallel(SoundInterval(self.hangupSfx), Sequence(Wait(delayAfterShootToIgnoreCollisions), Func(self.ignore, 'enter' + self.collNP.node().getName()))))) self.suitTrack.append(Sequence(Func(self.phone.reparentTo, self.suit.find('**/joint_Lhold')), Func(self.cord.reparentTo, render), Wait(delay2PickUpReceiver), Func(self.receiver.reparentTo, self.suit.find('**/joint_Rhold')), Func(self.receiver.setPos, receiverInHandPos), Func(self.receiver.setH, 270.0))) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self.suit, name) self.suitTrack.start(ts)
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
class CogThief(DirectObject): """This represents a single cog thief in the cog thief game""" notify = directNotify.newCategory("CogThief") DefaultSpeedWalkAnim = 4. CollisionRadius = 1.25 MaxFriendsVisible = 4 Infinity = 100000.0 # just a really big number SeparationDistance = 6.0 MinUrgency = 0.5 MaxUrgency = 0.75 def __init__(self, cogIndex, suitType, game, cogSpeed): self.cogIndex = cogIndex self.suitType = suitType self.game = game self.cogSpeed = cogSpeed suit = Suit.Suit() d = SuitDNA.SuitDNA() d.newSuit(suitType) suit.setDNA(d) # cache the walk anim suit.pose('walk', 0) self.suit = suit self.goal = CTGG.NoGoal self.goalId = CTGG.InvalidGoalId self.lastLocalTimeStampFromAI = 0 self.lastPosFromAI = Point3(0, 0, 0) self.lastThinkTime = 0 self.doneAdjust = False self.barrel = CTGG.NoBarrelCarried self.signalledAtReturnPos = False self.defaultPlayRate = 1.0 self.netTimeSentToStartByHit = 0 # steering loosely based on boid code game programming gems #1 # "Portions Copyright (C) Steven Woodcock, 2000" self.velocity = Vec3(0, 0, 0) self.oldVelocity = Vec3(0, 0, 0) self.acceleration = Vec3(0, 0, 0) self.bodyLength = self.CollisionRadius * 2 # Desired distance from closest neighbor when flying. self.cruiseDistance = 2 * self.bodyLength self.maxVelocity = self.cogSpeed # Maximum magnitude of acceleration as a fraction of maxSpeed. self.maxAcceleration = 5.0 self.perceptionRange = 6 self.notify.debug('cogSpeed=%s' % self.cogSpeed) self.kaboomSound = loader.loadSfx( "phase_4/audio/sfx/MG_cannon_fire_alt.mp3") self.kaboom = loader.loadModel( 'phase_4/models/minigames/ice_game_kaboom') self.kaboom.setScale(2.0) self.kaboom.setBillboardPointEye() self.kaboom.hide() self.kaboomTrack = None splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splatType = globalPropPool.getPropType(splatName) self.pieHitSound = globalBattleSoundCache.getSound( 'AA_wholepie_only.mp3') def destroy(self): self.ignoreAll() self.suit.delete() self.game = None def uniqueName(self, baseStr): return baseStr + '-' + str(self.game.doId) def handleEnterSphere(self, collEntry): """Handle the suit colliding with localToon.""" #assert self.notify.debugStateCall(self) intoNp = collEntry.getIntoNodePath() self.notify.debug('handleEnterSphere suit %d hit %s' % (self.cogIndex, intoNp)) if self.game: self.game.handleEnterSphere(collEntry) def gameStart(self, gameStartTime): self.gameStartTime = gameStartTime self.initCollisions() self.startWalkAnim() def gameEnd(self): self.moveIval.pause() del self.moveIval self.shutdownCollisions() # keep the suits from walking in place self.suit.loop('neutral') def initCollisions(self): # Make a sphere, give it a unique name, and parent it # to the suit. self.collSphere = CollisionSphere(0, 0, 0, 1.25) # Make he sphere intangible self.collSphere.setTangible(1) name = "CogThiefSphere-%d" % self.cogIndex self.collSphereName = self.uniqueName(name) self.collNode = CollisionNode(self.collSphereName) self.collNode.setIntoCollideMask(CTGG.BarrelBitmask | ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.suit.attachNewNode(self.collNode) #self.collNodePath.hide() # Add a hook looking for collisions with localToon self.accept('enter' + self.collSphereName, self.handleEnterSphere) # we need a taller collision tube to collide against for pie self.pieCollSphere = CollisionTube(0, 0, 0, 0, 0, 4, self.CollisionRadius) # Make he sphere intangible self.pieCollSphere.setTangible(1) name = "CogThiefPieSphere-%d" % self.cogIndex self.pieCollSphereName = self.uniqueName(name) self.pieCollNode = CollisionNode(self.pieCollSphereName) self.pieCollNode.setIntoCollideMask(ToontownGlobals.PieBitmask) self.pieCollNode.addSolid(self.pieCollSphere) self.pieCollNodePath = self.suit.attachNewNode(self.pieCollNode) #self.pieCollNodePath.show() # Add a hook looking for collisions with localToon #self.accept('enter' + self.pieCollSphereName, # self.handleEnter) def shutdownCollisions(self): self.ignore(self.uniqueName('enter' + self.collSphereName)) del self.collSphere self.collNodePath.removeNode() del self.collNodePath del self.collNode def updateGoal(self, timestamp, inResponseClientStamp, goalType, goalId, pos): """Update our goal and position.""" assert self.notify.debugStateCall(self) self.notify.debug('self.netTimeSentToStartByHit =%s' % self.netTimeSentToStartByHit) if not self.game: self.notify.debug('updateGoal self.game is None, just returning') return if not self.suit: self.notify.debug('updateGoal self.suit is None, just returning') return if self.goal == CTGG.NoGoal: self.startWalkAnim() if goalType == CTGG.NoGoal: self.notify.debug('updateGoal setting position to %s' % pos) self.suit.setPos(pos) self.lastThinkTime = 0 self.velocity = Vec3(0, 0, 0) self.oldVelocity = Vec3(0, 0, 0) self.acceleration = Vec3(0, 0, 0) if goalType == CTGG.RunAwayGoal: #import pdb; pdb.set_trace() pass if inResponseClientStamp < self.netTimeSentToStartByHit and \ self.goal == CTGG.NoGoal and \ goalType == CTGG.RunAwayGoal: #import pdb; pdb.set_trace() self.notify.warning( 'ignoring newGoal %s as cog %d was recently hit responsetime=%s hitTime=%s' % (CTGG.GoalStr[goalType], self.cogIndex, inResponseClientStamp, self.netTimeSentToStartByHit)) else: self.lastLocalTimeStampFromAI = globalClockDelta.networkToLocalTime( timestamp, bits=32) self.goal = goalType self.goalId = goalId self.lastPosFromAI = pos self.doneAdjust = False self.signalledAtReturnPos = False # TODO move the suit to where we expect him to be given the time difference def startWalkAnim(self): if self.suit: self.suit.loop('walk') speed = self.cogSpeed # float(MazeData.CELL_WIDTH) / self.cellWalkDuration self.defaultPlayRate = float(self.cogSpeed / self.DefaultSpeedWalkAnim) self.suit.setPlayRate(self.defaultPlayRate, 'walk') def think(self): """Calculate where we should go.""" if self.goal == CTGG.ToonGoal: self.thinkAboutCatchingToon() elif self.goal == CTGG.BarrelGoal: self.thinkAboutGettingBarrel() elif self.goal == CTGG.RunAwayGoal: self.thinkAboutRunAway() def thinkAboutCatchingToon(self): if not self.game: return av = self.game.getAvatar(self.goalId) if av: if not self.lastThinkTime: self.lastThinkTime = globalClock.getFrameTime() diffTime = globalClock.getFrameTime() - self.lastThinkTime avPos = av.getPos() myPos = self.suit.getPos() if not self.doneAdjust: myPos = self.lastPosFromAI self.notify.debug( 'thinkAboutCatchingToon not doneAdjust setting pos %s' % myPos) self.doneAdjust = True self.suit.setPos(myPos) if self.game.isToonPlayingHitTrack(self.goalId): # do nothing, just look at toon self.suit.headsUp(av) self.velocity = Vec3(0, 0, 0) self.oldVelocity = Vec3(0, 0, 0) self.acceleration = Vec3(0, 0, 0) else: self.commonMove() newPos = self.suit.getPos() self.adjustPlayRate(newPos, myPos, diffTime) self.lastThinkTime = globalClock.getFrameTime() def convertNetworkStampToGameTime(self, timestamp): """Convert a network timestamp to game time.""" localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) gameTime = self.game.local2GameTime(localStamp) return gameTime def respondToToonHit(self, timestamp): """The toon hit us, react appropriately.""" assert self.notify.debugStateCall(self) localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) # using 1.0 sec as fudge #if localStamp > self.lastLocalTimeStampFromAI: if self.netTimeSentToStartByHit < timestamp: self.clearGoal() self.showKaboom() # move him to his starting postion startPos = CTGG.CogStartingPositions[self.cogIndex] oldPos = self.suit.getPos() self.suit.setPos(startPos) if self.netTimeSentToStartByHit < timestamp: self.netTimeSentToStartByHit = timestamp else: self.notify.debug( 'localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToToonHit' % (localStamp, self.lastLocalTimeStampFromAI)) self.notify.debug( 'respondToToonHit self.netTimeSentToStartByHit = %s' % self.netTimeSentToStartByHit) def clearGoal(self): """Clear goal and goal id.""" self.goal = CTGG.NoGoal self.goalId = CTGG.InvalidGoalId def thinkAboutGettingBarrel(self): """Go for a barrel.""" if not self.game: return if not hasattr(self.game, 'barrels'): return if not self.goalId in xrange(len(self.game.barrels)): return if not self.lastThinkTime: self.lastThinkTime = globalClock.getFrameTime() diffTime = globalClock.getFrameTime() - self.lastThinkTime barrel = self.game.barrels[self.goalId] barrelPos = barrel.getPos() myPos = self.suit.getPos() if not self.doneAdjust: myPos = self.lastPosFromAI self.notify.debug( 'thinkAboutGettingBarrel not doneAdjust setting position to %s' % myPos) self.suit.setPos(myPos) """ diffTime = globalClock.getFrameTime()- self.lastLocalTimeStampFromAI self.notify.debug('doing adjust, diffTime = %s' % diffTime) if diffTime < 0: # it just looks really weird when it moves backwards diffTime = 0 self.notify.debug('forcing diffTime to %s' % diffTime) """ self.doneAdjust = True displacement = barrelPos - myPos distanceToToon = displacement.length() #self.notify.debug('diffTime = %s' % diffTime) self.suit.headsUp(barrel) lengthTravelled = diffTime * self.cogSpeed #self.notify.debug('lengthTravelled = %s' % lengthTravelled) # don't overshoot our target if lengthTravelled > distanceToToon: lengthTravelled = distanceToToon #self.notify.debug('overshooting lengthTravelled = %s' % lengthTravelled) displacement.normalize() dirVector = displacement dirVector *= lengthTravelled newPos = myPos + dirVector # always keep them grounded newPos.setZ(0) self.suit.setPos(newPos) self.adjustPlayRate(newPos, myPos, diffTime) self.lastThinkTime = globalClock.getFrameTime() def stopWalking(self, timestamp): """Stop the cog from walking.""" localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) if localStamp > self.lastLocalTimeStampFromAI: self.suit.loop('neutral') self.clearGoal() def thinkAboutRunAway(self): """Go for a barrel.""" if not self.game: return if not self.lastThinkTime: self.lastThinkTime = globalClock.getFrameTime() diffTime = globalClock.getFrameTime() - self.lastThinkTime returnPos = CTGG.CogReturnPositions[self.goalId] myPos = self.suit.getPos() if not self.doneAdjust: myPos = self.lastPosFromAI self.suit.setPos(myPos) """ diffTime = globalClock.getFrameTime()- self.lastLocalTimeStampFromAI self.notify.debug('run away doing adjust, diffTime = %s' % diffTime) if diffTime < 0: # it just looks really weird when it moves backwards diffTime = 0 self.notify.debug('forcing diffTime to %s' % diffTime) """ self.doneAdjust = True displacement = returnPos - myPos distanceToToon = displacement.length() #self.notify.debug('diffTime = %s' % diffTime) tempNp = render.attachNewNode('tempRet') tempNp.setPos(returnPos) self.suit.headsUp(tempNp) tempNp.removeNode() lengthTravelled = diffTime * self.cogSpeed #self.notify.debug('lengthTravelled = %s' % lengthTravelled) # don't overshoot our target if lengthTravelled > distanceToToon: lengthTravelled = distanceToToon #self.notify.debug('overshooting lengthTravelled = %s' % lengthTravelled) displacement.normalize() dirVector = displacement dirVector *= lengthTravelled newPos = myPos + dirVector # always keep them grounded newPos.setZ(0) self.suit.setPos(newPos) self.adjustPlayRate(newPos, myPos, diffTime) if (self.suit.getPos() - returnPos).length() < 0.0001: if not self.signalledAtReturnPos and self.barrel >= 0: # tell the AI we're at return Pos self.game.sendCogAtReturnPos(self.cogIndex, self.barrel) self.signalledAtReturnPos = True self.lastThinkTime = globalClock.getFrameTime() def makeCogCarryBarrel(self, timestamp, inResponseClientStamp, barrelModel, barrelIndex, cogPos): """Handle the AI telling us the barrel is attached to a cog.""" #assert self.notify.debugStateCall(self) if not self.game: return localTimeStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) # TODO validate time? self.lastLocalTimeStampFromAI = localTimeStamp inResponseGameTime = self.convertNetworkStampToGameTime( inResponseClientStamp) self.notify.debug('inResponseGameTime =%s timeSentToStart=%s' % (inResponseGameTime, self.netTimeSentToStartByHit)) if inResponseClientStamp < self.netTimeSentToStartByHit and \ self.goal == CTGG.NoGoal: self.notify.warning('ignoring makeCogCarrybarrel') else: barrelModel.setPos(0, -1.0, 1.5) barrelModel.reparentTo(self.suit) self.suit.setPos(cogPos) self.barrel = barrelIndex def makeCogDropBarrel(self, timestamp, inResponseClientStamp, barrelModel, barrelIndex, barrelPos): """Handle the AI telling us the barrel is attached to a cog.""" #assert self.notify.debugStateCall(self) localTimeStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) # TODO validate time? self.lastLocalTimeStampFromAI = localTimeStamp barrelModel.reparentTo(render) barrelModel.setPos(barrelPos) self.barrel = CTGG.NoBarrelCarried # #self.suit.setPos(cogPos) def respondToPieHit(self, timestamp): """The toon hit us, react appropriately.""" assert self.notify.debugStateCall(self) localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) # argh using 1.0 sec as fudge #if localStamp > self.lastLocalTimeStampFromAI: if self.netTimeSentToStartByHit < timestamp: self.clearGoal() self.showSplat() # move him to his starting postion startPos = CTGG.CogStartingPositions[self.cogIndex] oldPos = self.suit.getPos() self.suit.setPos(startPos) if self.netTimeSentToStartByHit < timestamp: self.netTimeSentToStartByHit = timestamp else: self.notify.debug( 'localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToPieHit' % (localStamp, self.lastLocalTimeStampFromAI)) self.notify.debug( 'respondToPieHit self.netTimeSentToStartByHit = %s' % self.netTimeSentToStartByHit) def cleanup(self): """Do whatever is necessary to cleanup properly.""" self.clearGoal() self.ignoreAll() self.suit.delete() if self.kaboomTrack and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.suit = None self.game = None def adjustPlayRate(self, newPos, oldPos, diffTime): """Adjust animation rate based on how far he's moved.""" # lets slowdown playrate if they're not moving much lengthTravelled = (newPos - oldPos).length() if diffTime: speed = lengthTravelled / diffTime else: speed = self.cogSpeed rateMult = speed / self.cogSpeed newRate = rateMult * self.defaultPlayRate self.suit.setPlayRate(newRate, 'walk') def commonMove(self): """Move the cog thief. Common for all 3 behaviors """ if not self.lastThinkTime: self.lastThinkTime = globalClock.getFrameTime() dt = globalClock.getFrameTime() - self.lastThinkTime # Step 1: Update our position. # Update our position based on the velocity # vector we computed last time around. self.oldpos = self.suit.getPos() # save off our previous position pos = self.suit.getPos() pos += self.velocity * dt # apply velocities. self.suit.setPos(pos) # Step 2: SeeFriends. # Determine if we can see any of our flockmates. self.seeFriends() acc = Vec3(0, 0, 0) # well first off we want to move to our target self.accumulate(acc, self.getTargetVector()) # Step 3: Flocking behavior. # Do we see any of our flockmates? If yes, it's time to implement # the first Three Rules (they don't matter if we can't see anybody) if self.numFlockmatesSeen > 0: #if hasattr(base,'doDebug') and base.doDebug: # import pdb; pdb.set_trace() keepDistanceVector = self.keepDistance() oldAcc = Vec3(acc) self.accumulate(acc, keepDistanceVector) if self.cogIndex == 0: #self.notify.debug('oldAcc=%s, keepDist=%s newAcc=%s' % # (oldAcc,keepDistanceVector, acc)) pass # Step 8: Constrain acceleration # If our acceleration change is more than we allow, constrain it if (acc.length() > self.maxAcceleration): # definitely too much...constrain to maximum change acc.normalize() acc *= self.maxAcceleration # Step 9: Implementation. # Here's where we apply our newly computed acceleration vector # to create a new velocity vector to use next update cycle. self.oldVelocity = self.velocity # save off our previous velocity # now add in the acceleration self.velocity += acc # Step 10: constraint Y velocity changes. # Attempt to restrict flight straight up/down by damping out Y axis velocity. # This isn't strictly necessary, but does lead to more realistic looking flight. # Step 11: Constrain our speed. # If we're moving faster than we're allowed to move, constrain our velocity. if self.velocity.length() > self.maxVelocity: self.velocity.normalize() self.velocity *= self.maxVelocity # Step 12: Compute roll/pitch/yaw. # Compute our orientation after all this speed adjustment nonsense. # bah no need, we turn on a dime towards our velocity forwardVec = Vec3(1, 0, 0) heading = rad2Deg(math.atan2(self.velocity[1], self.velocity[0])) heading -= 90 self.suit.setH(heading) def getTargetVector(self): """Return a vector to my goal.""" targetPos = Point3(0, 0, 0) if self.goal == CTGG.ToonGoal: av = self.game.getAvatar(self.goalId) if av: targetPos = av.getPos() elif self.goal == CTGG.BarrelGoal: barrel = self.game.barrels[self.goalId] targetPos = barrel.getPos() elif self.goal == CTGG.RunAwayGoal: targetPos = CTGG.CogReturnPositions[self.goalId] targetPos.setZ(0) myPos = self.suit.getPos() diff = targetPos - myPos if diff.length() > 1.0: diff.normalize() diff *= 1.0 return diff def accumulate(self, accumulator, valueToAdd): """Return the magnitude of the accumulated vector.""" accumulator += valueToAdd return accumulator.length() def seeFriends(self): """Determines which flockmates a given flock boid can see.""" # clear the existing visibility list of any holdover from last round self.clearVisibleList() for cogIndex in self.game.cogInfo.keys(): if cogIndex == self.cogIndex: continue if self.sameGoal(cogIndex): dist = self.canISee(cogIndex) if dist != self.Infinity: self.addToVisibleList(cogIndex) if dist < self.distToNearestFlockmate: self.nearestFlockmate = cogIndex self.distToNearestFlockmate = dist return self.numFlockmatesSeen def clearVisibleList(self): """Clears the visibility list and associated fields.""" self.visibleFriendsList = [] self.numFlockmatesSeen = 0 self.nearestFlockmate = None self.distToNearestFlockmate = self.Infinity def addToVisibleList(self, cogIndex): """Add the cog to the visible list.""" # test: do we see enough buddies already? if self.numFlockmatesSeen < self.MaxFriendsVisible: #nope--we can add to this one to the list self.visibleFriendsList.append(cogIndex) self.numFlockmatesSeen += 1 if self.cogIndex == 0: #self.notify.debug('self.numFlockmatesSeen = %s' % self.numFlockmatesSeen) pass def canISee(self, cogIndex): """Return distance if I can see the other cog, infinity otherwise""" if self.cogIndex == cogIndex: # well we should never see ourself return self.Infinity cogThief = self.game.getCogThief(cogIndex) distance = self.suit.getDistance(cogThief.suit) if distance < self.perceptionRange: #self.notify.debug('%s can see %s' % (self.cogIndex, cogIndex)) return distance # fell through; can not see it return self.Infinity def sameGoal(self, cogIndex): """Return true if we have the same goal.""" cogThief = self.game.getCogThief(cogIndex) result = (cogThief.goalId == self.goalId) and (cogThief.goal == self.goal) return result def keepDistance(self): """Generates a vector for a flock boid to maintain his desired separation distance from the nearest flockmate he sees. """ ratio = self.distToNearestFlockmate / self.SeparationDistance nearestThief = self.game.getCogThief(self.nearestFlockmate) change = nearestThief.suit.getPos() - self.suit.getPos() if ratio < self.MinUrgency: ratio = self.MinUrgency if ratio > self.MaxUrgency: ratio = self.MaxUrgency # test: are we too close to our nearest flockmate? if self.distToNearestFlockmate < self.SeparationDistance: #self.notify.debug('%d is too close to %d' % (self.cogIndex, self.nearestFlockmate)) # too close...move away from our neighbor change.normalize() change *= -(1 - ratio ) # the close we are the more we are pushed away elif self.distToNearestFlockmate > self.SeparationDistance: # too far away move towards our neighbor change.normalize() change *= ratio else: # in the UNLIKELY event we're exactly the right distance away, do nothing change = Vec3(0, 0, 0) return change def showKaboom(self): """Show the kaboom graphic and sound.""" if self.kaboomTrack and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.kaboom.reparentTo(render) self.kaboom.setPos(self.suit.getPos()) self.kaboom.setZ(3) self.kaboomTrack = Parallel( SoundInterval(self.kaboomSound, volume=0.5), Sequence( Func(self.kaboom.showThrough), LerpScaleInterval(self.kaboom, duration=0.5, scale=Point3(10, 10, 10), startScale=Point3(1, 1, 1), blendType='easeOut'), Func(self.kaboom.hide), )) self.kaboomTrack.start() def showSplat(self): """Show the splat graphic and sound.""" if self.kaboomTrack and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.splat.reparentTo(render) self.splat.setPos(self.suit.getPos()) self.splat.setZ(3) self.kaboomTrack = Parallel( SoundInterval(self.pieHitSound, volume=1.0), Sequence( Func(self.splat.showThrough), LerpScaleInterval(self.splat, duration=0.5, scale=1.75, startScale=Point3(0.1, 0.1, 0.1), blendType='easeOut'), Func(self.splat.hide), )) self.kaboomTrack.start()
def run(self): boss = base.bspLoader.getPyEntityByTargetName("groom_boss_suit") boss.show() boss.cleanupPropeller() boss.animFSM.request('neutral') camera.reparentTo(boss) onBtn = base.bspLoader.getPyEntityByTargetName("powerovrd_on_button") # press animation (fingerwag): 1-31 32-1 buttonPos = (-1105 / 16.0, 2683 / 16.0, 76 / 16.0) camBtnPosHpr = (-1027 / 16.0, 2638 / 16.0, 96 / 16.0, 135 - 90, 30, 0) camBtnPosHpr2 = (-1009 / 16.0, 2764 / 16.0, 169 / 16.0, 232 - 90, 0, 0) def __pingpongboss_speak(): boss.pingpong("speak", fromFrame=95, toFrame=100) def __boss_pressseq(): return Sequence( ActorInterval(boss, "fingerwag", startFrame=1, endFrame=31), Func(onBtn.d_requestPress), ActorInterval(boss, "fingerwag", startFrame=32, endFrame=1)) def __localavplay_duck(): base.localAvatar.setAnimState('off') base.localAvatar.play("duck", fromFrame=19) numGoons = 6 goonWakeup = Parallel() for i in xrange(numGoons): delay = random.uniform(0.0, 0.5) goon = base.bspLoader.getPyEntityByTargetName( "groom_goon_{0}".format(i)) goonWakeup.append(Sequence(Wait(delay), Func(goon.wakeup))) bdoor = base.bspLoader.getPyEntityByTargetName("to_groom_botdoor") tdoor = base.bspLoader.getPyEntityByTargetName("to_groom_topdoor") oldHpr = boss.getHpr(render) bossTrack = Parallel( Sequence( Wait(10.0), Func(boss.setHpr, oldHpr), ActorInterval(boss, "speak", startFrame=55, endFrame=105, playRate=1.5), #Func(__pingpongboss_speak), Wait(2.0), Func(boss.loop, "neutral")), Sequence( Func(boss.play, "speak"), Func(boss.setChat, "What's this?! How did a Toon get down here?"), Wait(2.5), Func( boss.setChat, "The only place you'll be going is back to the playground." ), Func(boss.loop, "walk"), Func(boss.headsUp, *buttonPos), LerpPosInterval(boss, 2.5, buttonPos), __boss_pressseq(), Wait(2.5), Func(boss.setChat, "Goons, ATTACK!!!"))) camTrack = Sequence( Func(camera.setPos, 2.5, 14, 7), Func(camera.lookAt, boss, 0, 0, 4), Wait(2.5), Func(camera.reparentTo, render), Func(camera.setPosHpr, *camBtnPosHpr), Wait(2.0), Func(camera.setPosHpr, *camBtnPosHpr2), Wait(0.5), Wait(3.0), Func(camera.setPosHpr, 4.351, 126.686, 5.5, -154.16, 16.11, 0), Wait(0.3), Func(bdoor.request, 'Closing'), Func(tdoor.request, 'Closing'), Func(__localavplay_duck), Wait(0.9), Func(base.doCamShake, 0.5, 0.35), Wait(0.9), Func(camera.reparentTo, boss), Func(camera.setPos, 2.5, 17, 7), Func(camera.lookAt, boss, 0, 0, 4), LerpPosHprInterval(camera, duration=0.75, blendType='easeOut', pos=(1, 5, 4), hpr=(165, 20, 0)), Wait(1.75), Func(camera.reparentTo, render), Func(camera.setPosHpr, 88 / 16.0, 2746 / 16.0, 127 / 16.0, 71 - 90, -10, 0)) goonTrack = Sequence(Wait(12.6), goonWakeup) self.ival = Parallel(camTrack, bossTrack, goonTrack) self.ival.start()
class DistributedIceGame(DistributedMinigame.DistributedMinigame, DistributedIceWorld.DistributedIceWorld): notify = directNotify.newCategory('DistributedIceGame') MaxLocalForce = 100 MaxPhysicsForce = 25000 def __init__(self, cr): DistributedMinigame.DistributedMinigame.__init__(self, cr) DistributedIceWorld.DistributedIceWorld.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedIceGame', [State.State('off', self.enterOff, self.exitOff, ['inputChoice']), State.State('inputChoice', self.enterInputChoice, self.exitInputChoice, ['waitServerChoices', 'moveTires', 'displayVotes', 'cleanup']), State.State('waitServerChoices', self.enterWaitServerChoices, self.exitWaitServerChoices, ['moveTires', 'cleanup']), State.State('moveTires', self.enterMoveTires, self.exitMoveTires, ['synch', 'cleanup']), State.State('synch', self.enterSynch, self.exitSynch, ['inputChoice', 'scoring', 'cleanup']), State.State('scoring', self.enterScoring, self.exitScoring, ['cleanup', 'finalResults', 'inputChoice']), State.State('finalResults', self.enterFinalResults, self.exitFinalResults, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.cameraThreeQuarterView = (0, -22, 45, 0, -62.89, 0) self.tireDict = {} self.forceArrowDict = {} self.canDrive = False self.timer = None self.timerStartTime = None self.curForce = 0 self.curHeading = 0 self.headingMomentum = 0.0 self.forceMomentum = 0.0 self.allTireInputs = None self.curRound = 0 self.curMatch = 0 self.controlKeyWarningLabel = DirectLabel(text=TTLocalizer.IceGameControlKeyWarning, text_fg=VBase4(1, 0, 0, 1), relief=None, pos=(0.0, 0, 0), scale=0.15) self.controlKeyWarningLabel.hide() self.waitingMoveLabel = DirectLabel(text=TTLocalizer.IceGameWaitingForPlayersToFinishMove, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075) self.waitingMoveLabel.hide() self.waitingSyncLabel = DirectLabel(text=TTLocalizer.IceGameWaitingForAISync, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075) self.waitingSyncLabel.hide() self.infoLabel = DirectLabel(text='', text_fg=VBase4(0, 0, 0, 1), relief=None, pos=(0.0, 0, 0.7), scale=0.075) self.updateInfoLabel() self.lastForceArrowUpdateTime = 0 self.sendForceArrowUpdateAsap = False self.treasures = [] self.penalties = [] self.obstacles = [] self.controlKeyPressed = False self.controlKeyWarningIval = None return def delete(self): DistributedIceWorld.DistributedIceWorld.delete(self) DistributedMinigame.DistributedMinigame.delete(self) if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningLabel.destroy() del self.controlKeyWarningLabel self.waitingMoveLabel.destroy() del self.waitingMoveLabel self.waitingSyncLabel.destroy() del self.waitingSyncLabel self.infoLabel.destroy() del self.infoLabel for treasure in self.treasures: treasure.destroy() del self.treasures for penalty in self.penalties: penalty.destroy() del self.penalties for obstacle in self.obstacles: obstacle.removeNode() del self.obstacles del self.gameFSM return def announceGenerate(self): DistributedMinigame.DistributedMinigame.announceGenerate(self) DistributedIceWorld.DistributedIceWorld.announceGenerate(self) self.debugTaskName = self.uniqueName('debugTask') def getTitle(self): return TTLocalizer.IceGameTitle def getInstructions(self): szId = self.getSafezoneId() numPenalties = IceGameGlobals.NumPenalties[szId] result = TTLocalizer.IceGameInstructions if numPenalties == 0: result = TTLocalizer.IceGameInstructionsNoTnt return result def getMaxDuration(self): return 0 def load(self): self.notify.debug('load') DistributedMinigame.DistributedMinigame.load(self) self.music = base.loadMusic('phase_4/audio/bgm/MG_IceGame.mid') self.gameBoard = loader.loadModel('phase_4/models/minigames/ice_game_icerink') background = loader.loadModel('phase_4/models/minigames/ice_game_2d') background.reparentTo(self.gameBoard) self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) self.setupSimulation() index = 0 for avId in self.avIdList: self.setupTire(avId, index) self.setupForceArrow(avId) index += 1 for index in xrange(len(self.avIdList), 4): self.setupTire(-index, index) self.setupForceArrow(-index) self.showForceArrows(realPlayersOnly=True) self.westWallModel = NodePath() if not self.westWallModel.isEmpty(): self.westWallModel.reparentTo(self.gameBoard) self.westWallModel.setPos(IceGameGlobals.MinWall[0], IceGameGlobals.MinWall[1], 0) self.westWallModel.setScale(4) self.eastWallModel = NodePath() if not self.eastWallModel.isEmpty(): self.eastWallModel.reparentTo(self.gameBoard) self.eastWallModel.setPos(IceGameGlobals.MaxWall[0], IceGameGlobals.MaxWall[1], 0) self.eastWallModel.setScale(4) self.eastWallModel.setH(180) self.arrowKeys = ArrowKeys.ArrowKeys() self.target = loader.loadModel('phase_3/models/misc/sphere') self.target.setScale(0.01) self.target.reparentTo(self.gameBoard) self.target.setPos(0, 0, 0) self.scoreCircle = loader.loadModel('phase_4/models/minigames/ice_game_score_circle') self.scoreCircle.setScale(0.01) self.scoreCircle.reparentTo(self.gameBoard) self.scoreCircle.setZ(IceGameGlobals.TireRadius / 2.0) self.scoreCircle.setAlphaScale(0.5) self.scoreCircle.setTransparency(1) self.scoreCircle.hide() self.treasureModel = loader.loadModel('phase_4/models/minigames/ice_game_barrel') self.penaltyModel = loader.loadModel('phase_4/models/minigames/ice_game_tnt2') self.penaltyModel.setScale(0.75, 0.75, 0.7) szId = self.getSafezoneId() obstacles = IceGameGlobals.Obstacles[szId] index = 0 cubicObstacle = IceGameGlobals.ObstacleShapes[szId] for pos in obstacles: newPos = Point3(pos[0], pos[1], IceGameGlobals.TireRadius) newObstacle = self.createObstacle(newPos, index, cubicObstacle) self.obstacles.append(newObstacle) index += 1 self.countSound = loader.loadSfx('phase_3.5/audio/sfx/tick_counter.mp3') self.treasureGrabSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_bananas.mp3') self.penaltyGrabSound = loader.loadSfx('phase_4/audio/sfx/MG_cannon_fire_alt.mp3') self.tireSounds = [] for tireIndex in xrange(4): tireHit = loader.loadSfx('phase_4/audio/sfx/Golf_Hit_Barrier_1.mp3') wallHit = loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.mp3') obstacleHit = loader.loadSfx('phase_4/audio/sfx/Golf_Hit_Barrier_2.mp3') self.tireSounds.append({'tireHit': tireHit, 'wallHit': wallHit, 'obstacleHit': obstacleHit}) self.arrowRotateSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_ice_force_rotate.wav') self.arrowUpSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_ice_force_increase_3sec.mp3') self.arrowDownSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_ice_force_decrease_3sec.mp3') self.scoreCircleSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_ice_scoring_1.mp3') def unload(self): self.notify.debug('unload') DistributedMinigame.DistributedMinigame.unload(self) del self.music self.gameBoard.removeNode() del self.gameBoard for forceArrow in self.forceArrowDict.values(): forceArrow.removeNode() del self.forceArrowDict self.scoreCircle.removeNode() del self.scoreCircle del self.countSound def onstage(self): self.notify.debug('onstage') DistributedMinigame.DistributedMinigame.onstage(self) self.gameBoard.reparentTo(render) self.__placeToon(self.localAvId) self.moveCameraToTop() self.scorePanels = [] base.playMusic(self.music, looping=1, volume=0.8) def offstage(self): self.notify.debug('offstage') self.music.stop() self.gameBoard.hide() self.infoLabel.hide() for avId in self.tireDict: self.tireDict[avId]['tireNodePath'].hide() for panel in self.scorePanels: panel.cleanup() del self.scorePanels for obstacle in self.obstacles: obstacle.hide() for treasure in self.treasures: treasure.nodePath.hide() for penalty in self.penalties: penalty.nodePath.hide() for avId in self.avIdList: av = self.getAvatar(avId) if av: av.dropShadow.show() av.resetLOD() taskMgr.remove(self.uniqueName('aimtask')) self.arrowKeys.destroy() del self.arrowKeys DistributedMinigame.DistributedMinigame.offstage(self) def handleDisabledAvatar(self, avId): self.notify.debug('handleDisabledAvatar') self.notify.debug('avatar ' + str(avId) + ' disabled') DistributedMinigame.DistributedMinigame.handleDisabledAvatar(self, avId) def setGameReady(self): if not self.hasLocalToon: return self.notify.debug('setGameReady') if DistributedMinigame.DistributedMinigame.setGameReady(self): return for index in xrange(self.numPlayers): avId = self.avIdList[index] toon = self.getAvatar(avId) if toon: toon.reparentTo(render) self.__placeToon(avId) toon.forwardSpeed = 0 toon.rotateSpeed = False toon.dropShadow.hide() toon.setAnimState('Sit') if avId in self.tireDict: tireNp = self.tireDict[avId]['tireNodePath'] toon.reparentTo(tireNp) toon.setY(1.0) toon.setZ(-3) toon.startLookAround() def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug('setGameStart') DistributedMinigame.DistributedMinigame.setGameStart(self, timestamp) for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.stopLookAround() self.scores = [0] * self.numPlayers spacing = 0.4 for i in xrange(self.numPlayers): avId = self.avIdList[i] avName = self.getAvatarName(avId) scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel(avId, avName) scorePanel.setScale(0.9) scorePanel.setPos(0.75 - spacing * (self.numPlayers - 1 - i), 0.0, 0.875) scorePanel.makeTransparent(0.75) self.scorePanels.append(scorePanel) self.arrowKeys.setPressHandlers([self.__upArrowPressed, self.__downArrowPressed, self.__leftArrowPressed, self.__rightArrowPressed, self.__controlPressed]) def isInPlayState(self): if not self.gameFSM.getCurrentState(): return False if not self.gameFSM.getCurrentState().getName() == 'play': return False return True def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterInputChoice(self): self.notify.debug('enterInputChoice') self.forceLocalToonToTire() self.controlKeyPressed = False if self.curRound == 0: self.setupStartOfMatch() else: self.notify.debug('self.curRound = %s' % self.curRound) self.timer = ToontownTimer.ToontownTimer() self.timer.hide() if self.timerStartTime != None: self.startTimer() self.showForceArrows(realPlayersOnly=True) self.localForceArrow().setPosHpr(0, 0, -1.0, 0, 0, 0) self.localForceArrow().reparentTo(self.localTireNp()) self.localForceArrow().setY(IceGameGlobals.TireRadius) self.localTireNp().headsUp(self.target) self.notify.debug('self.localForceArrow() heading = %s' % self.localForceArrow().getH()) self.curHeading = self.localTireNp().getH() self.curForce = 25 self.updateLocalForceArrow() for avId in self.forceArrowDict: forceArrow = self.forceArrowDict[avId] forceArrow.setPosHpr(0, 0, -1.0, 0, 0, 0) tireNp = self.tireDict[avId]['tireNodePath'] forceArrow.reparentTo(tireNp) forceArrow.setY(IceGameGlobals.TireRadius) tireNp.headsUp(self.target) self.updateForceArrow(avId, tireNp.getH(), 25) taskMgr.add(self.__aimTask, self.uniqueName('aimtask')) if base.localAvatar.laffMeter: base.localAvatar.laffMeter.stop() self.sendForceArrowUpdateAsap = False return def exitInputChoice(self): if not self.controlKeyPressed: if self.controlKeyWarningIval: self.controlKeyWarningIval.finish() self.controlKeyWarningIval = None self.controlKeyWarningIval = Sequence(Func(self.controlKeyWarningLabel.show), self.controlKeyWarningLabel.colorScaleInterval(10, VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)), Func(self.controlKeyWarningLabel.hide)) self.controlKeyWarningIval.start() if self.timer != None: self.timer.destroy() self.timer = None self.timerStartTime = None self.hideForceArrows() self.arrowRotateSound.stop() self.arrowUpSound.stop() self.arrowDownSound.stop() taskMgr.remove(self.uniqueName('aimtask')) return def enterWaitServerChoices(self): self.waitingMoveLabel.show() self.showForceArrows(True) def exitWaitServerChoices(self): self.waitingMoveLabel.hide() self.hideForceArrows() def enterMoveTires(self): for key in self.tireDict: body = self.tireDict[key]['tireBody'] body.setAngularVel(0, 0, 0) body.setLinearVel(0, 0, 0) for index in xrange(len(self.allTireInputs)): input = self.allTireInputs[index] avId = self.avIdList[index] body = self.getTireBody(avId) degs = input[1] + 90 tireNp = self.getTireNp(avId) tireH = tireNp.getH() self.notify.debug('tireH = %s' % tireH) radAngle = deg2Rad(degs) foo = NodePath('foo') dirVector = Vec3(math.cos(radAngle), math.sin(radAngle), 0) self.notify.debug('dirVector is now=%s' % dirVector) inputForce = input[0] inputForce /= self.MaxLocalForce inputForce *= self.MaxPhysicsForce force = dirVector * inputForce self.notify.debug('adding force %s to %d' % (force, avId)) body.addForce(force) self.enableAllTireBodies() self.totalPhysicsSteps = 0 self.startSim() taskMgr.add(self.__moveTiresTask, self.uniqueName('moveTiresTtask')) def exitMoveTires(self): self.forceLocalToonToTire() self.disableAllTireBodies() self.stopSim() self.notify.debug('total Physics steps = %d' % self.totalPhysicsSteps) taskMgr.remove(self.uniqueName('moveTiresTtask')) def enterSynch(self): self.waitingSyncLabel.show() def exitSynch(self): self.waitingSyncLabel.hide() def enterScoring(self): sortedByDistance = [] for avId in self.avIdList: np = self.getTireNp(avId) pos = np.getPos() pos.setZ(0) sortedByDistance.append((avId, pos.length())) def compareDistance(x, y): if x[1] - y[1] > 0: return 1 elif x[1] - y[1] < 0: return -1 else: return 0 sortedByDistance.sort(cmp=compareDistance) self.scoreMovie = Sequence() curScale = 0.01 curTime = 0 self.scoreCircle.setScale(0.01) self.scoreCircle.show() self.notify.debug('newScores = %s' % self.newScores) circleStartTime = 0 for index in xrange(len(sortedByDistance)): distance = sortedByDistance[index][1] avId = sortedByDistance[index][0] scorePanelIndex = self.avIdList.index(avId) time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec if time < 0: time = 0.01 scaleXY = distance + IceGameGlobals.TireRadius self.notify.debug('circleStartTime = %s' % circleStartTime) self.scoreMovie.append(Parallel(LerpScaleInterval(self.scoreCircle, time, Point3(scaleXY, scaleXY, 1.0)), SoundInterval(self.scoreCircleSound, duration=time, startTime=circleStartTime))) circleStartTime += time startScore = self.scorePanels[scorePanelIndex].getScore() destScore = self.newScores[scorePanelIndex] self.notify.debug('for avId %d, startScore=%d, newScores=%d' % (avId, startScore, destScore)) def increaseScores(t, scorePanelIndex = scorePanelIndex, startScore = startScore, destScore = destScore): oldScore = self.scorePanels[scorePanelIndex].getScore() diff = destScore - startScore newScore = int(startScore + diff * t) if newScore > oldScore: base.playSfx(self.countSound) self.scorePanels[scorePanelIndex].setScore(newScore) self.scores[scorePanelIndex] = newScore duration = (destScore - startScore) * IceGameGlobals.ScoreCountUpRate tireNp = self.tireDict[avId]['tireNodePath'] self.scoreMovie.append(Parallel(LerpFunctionInterval(increaseScores, duration), Sequence(LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1))))) curScale += distance self.scoreMovie.append(Func(self.sendUpdate, 'reportScoringMovieDone', [])) self.scoreMovie.start() def exitScoring(self): self.scoreMovie.finish() self.scoreMovie = None self.scoreCircle.hide() return def enterFinalResults(self): lerpTrack = Parallel() lerpDur = 0.5 tY = 0.6 bY = -.05 lX = -.5 cX = 0 rX = 0.5 scorePanelLocs = (((cX, bY),), ((lX, bY), (rX, bY)), ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY), (lX, bY), (rX, bY))) scorePanelLocs = scorePanelLocs[self.numPlayers - 1] for i in xrange(self.numPlayers): panel = self.scorePanels[i] pos = scorePanelLocs[i] lerpTrack.append(Parallel(LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType='easeInOut'), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType='easeInOut'))) self.showScoreTrack = Parallel(lerpTrack, Sequence(Wait(IceGameGlobals.ShowScoresDuration), Func(self.gameOver))) self.showScoreTrack.start() def exitFinalResults(self): self.showScoreTrack.pause() del self.showScoreTrack def enterCleanup(self): self.notify.debug('enterCleanup') if base.localAvatar.laffMeter: base.localAvatar.laffMeter.start() def exitCleanup(self): pass def __placeToon(self, avId): toon = self.getAvatar(avId) if toon: toon.setPos(0, 0, 0) toon.setHpr(0, 0, 0) def moveCameraToTop(self): camera.reparentTo(render) p = self.cameraThreeQuarterView camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5]) def setupTire(self, avId, index): tireNp, tireBody, tireOdeGeom = self.createTire(index) self.tireDict[avId] = {'tireNodePath': tireNp, 'tireBody': tireBody, 'tireOdeGeom': tireOdeGeom} if avId <= 0: tireBlocker = tireNp.find('**/tireblockermesh') if not tireBlocker.isEmpty(): tireBlocker.hide() if avId == self.localAvId: tireNp = self.tireDict[avId]['tireNodePath'] self.treasureSphereName = 'treasureCollider' self.treasureCollSphere = CollisionSphere(0, 0, 0, IceGameGlobals.TireRadius) self.treasureCollSphere.setTangible(0) self.treasureCollNode = CollisionNode(self.treasureSphereName) self.treasureCollNode.setFromCollideMask(ToontownGlobals.PieBitmask) self.treasureCollNode.addSolid(self.treasureCollSphere) self.treasureCollNodePath = tireNp.attachNewNode(self.treasureCollNode) self.treasureHandler = CollisionHandlerEvent() self.treasureHandler.addInPattern('%fn-intoTreasure') base.cTrav.addCollider(self.treasureCollNodePath, self.treasureHandler) eventName = '%s-intoTreasure' % self.treasureCollNodePath.getName() self.notify.debug('eventName = %s' % eventName) self.accept(eventName, self.toonHitSomething) def setupForceArrow(self, avId): arrow = loader.loadModel('phase_4/models/minigames/ice_game_arrow') priority = 0 if avId < 0: priority = -avId else: priority = self.avIdList.index(avId) if avId == self.localAvId: priority = 10 self.forceArrowDict[avId] = arrow def hideForceArrows(self): for forceArrow in self.forceArrowDict.values(): forceArrow.hide() def showForceArrows(self, realPlayersOnly = True): for avId in self.forceArrowDict: if realPlayersOnly: if avId > 0: self.forceArrowDict[avId].show() else: self.forceArrowDict[avId].hide() else: self.forceArrowDict[avId].show() def localForceArrow(self): if self.localAvId in self.forceArrowDict: return self.forceArrowDict[self.localAvId] else: return None return None def setChoices(self, input0, input1, input2, input3): pass def startDebugTask(self): taskMgr.add(self.debugTask, self.debugTaskName) def stopDebugTask(self): taskMgr.remove(self.debugTaskName) def debugTask(self, task): if self.canDrive and self.tireDict.has_key(localAvatar.doId): dt = globalClock.getDt() forceMove = 25000 forceMoveDt = forceMove tireBody = self.tireDict[localAvatar.doId]['tireBody'] if self.arrowKeys.upPressed() and not tireBody.isEnabled(): x = 0 y = 1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.downPressed() and not tireBody.isEnabled(): x = 0 y = -1 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.leftPressed() and not tireBody.isEnabled(): x = -1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) if self.arrowKeys.rightPressed() and not tireBody.isEnabled(): x = 1 y = 0 tireBody.enable() tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0)) return task.cont def __upArrowPressed(self): pass def __downArrowPressed(self): pass def __leftArrowPressed(self): pass def __rightArrowPressed(self): pass def __controlPressed(self): if self.gameFSM.getCurrentState().getName() == 'inputChoice': self.sendForceArrowUpdateAsap = True self.updateLocalForceArrow() self.controlKeyPressed = True self.sendUpdate('setAvatarChoice', [self.curForce, self.curHeading]) self.gameFSM.request('waitServerChoices') def startTimer(self): now = globalClock.getFrameTime() elapsed = now - self.timerStartTime self.timer.posInTopRightCorner() self.timer.setTime(IceGameGlobals.InputTimeout) self.timer.countdown(IceGameGlobals.InputTimeout - elapsed, self.handleChoiceTimeout) self.timer.show() def setTimerStartTime(self, timestamp): if not self.hasLocalToon: return self.timerStartTime = globalClockDelta.networkToLocalTime(timestamp) if self.timer != None: self.startTimer() return def handleChoiceTimeout(self): self.sendUpdate('setAvatarChoice', [0, 0]) self.gameFSM.request('waitServerChoices') def localTireNp(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]['tireNodePath'] return ret def localTireBody(self): ret = None if self.localAvId in self.tireDict: ret = self.tireDict[self.localAvId]['tireBody'] return ret def getTireBody(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]['tireBody'] return ret def getTireNp(self, avId): ret = None if avId in self.tireDict: ret = self.tireDict[avId]['tireNodePath'] return ret def updateForceArrow(self, avId, curHeading, curForce): forceArrow = self.forceArrowDict[avId] tireNp = self.tireDict[avId]['tireNodePath'] tireNp.setH(curHeading) tireBody = self.tireDict[avId]['tireBody'] tireBody.setQuaternion(tireNp.getQuat()) self.notify.debug('curHeading = %s' % curHeading) yScale = curForce / 100.0 yScale *= 1 headY = yScale * 15 xScale = (yScale - 1) / 2.0 + 1.0 shaft = forceArrow.find('**/arrow_shaft') head = forceArrow.find('**/arrow_head') shaft.setScale(xScale, yScale, 1) head.setPos(0, headY, 0) head.setScale(xScale, xScale, 1) def updateLocalForceArrow(self): avId = self.localAvId self.b_setForceArrowInfo(avId, self.curHeading, self.curForce) def __aimTask(self, task): if not hasattr(self, 'arrowKeys'): return task.done dt = globalClock.getDt() headingMomentumChange = dt * 60.0 forceMomentumChange = dt * 160.0 arrowUpdate = False arrowRotating = False arrowUp = False arrowDown = False if self.arrowKeys.upPressed() and not self.arrowKeys.downPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce += self.forceMomentum * dt arrowUpdate = True if oldForce < self.MaxLocalForce: arrowUp = True elif self.arrowKeys.downPressed() and not self.arrowKeys.upPressed(): self.forceMomentum += forceMomentumChange if self.forceMomentum < 0: self.forceMomentum = 0 if self.forceMomentum > 50: self.forceMomentum = 50 oldForce = self.curForce self.curForce -= self.forceMomentum * dt arrowUpdate = True if oldForce > 0.01: arrowDown = True else: self.forceMomentum = 0 if self.arrowKeys.leftPressed() and not self.arrowKeys.rightPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading += self.headingMomentum * dt arrowUpdate = True arrowRotating = True elif self.arrowKeys.rightPressed() and not self.arrowKeys.leftPressed(): self.headingMomentum += headingMomentumChange if self.headingMomentum < 0: self.headingMomentum = 0 if self.headingMomentum > 50: self.headingMomentum = 50 self.curHeading -= self.headingMomentum * dt arrowUpdate = True arrowRotating = True else: self.headingMomentum = 0 if arrowUpdate: self.normalizeHeadingAndForce() self.updateLocalForceArrow() if arrowRotating: if not self.arrowRotateSound.status() == self.arrowRotateSound.PLAYING: base.playSfx(self.arrowRotateSound, looping=True) else: self.arrowRotateSound.stop() if arrowUp: if not self.arrowUpSound.status() == self.arrowUpSound.PLAYING: base.playSfx(self.arrowUpSound, looping=False) else: self.arrowUpSound.stop() if arrowDown: if not self.arrowDownSound.status() == self.arrowDownSound.PLAYING: base.playSfx(self.arrowDownSound, looping=False) else: self.arrowDownSound.stop() return task.cont def normalizeHeadingAndForce(self): if self.curForce > self.MaxLocalForce: self.curForce = self.MaxLocalForce if self.curForce < 0.01: self.curForce = 0.01 def setTireInputs(self, tireInputs): if not self.hasLocalToon: return self.allTireInputs = tireInputs self.gameFSM.request('moveTires') def enableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]['tireBody'].enable() def disableAllTireBodies(self): for avId in self.tireDict.keys(): self.tireDict[avId]['tireBody'].disable() def areAllTiresDisabled(self): for avId in self.tireDict.keys(): if self.tireDict[avId]['tireBody'].isEnabled(): return False return True def __moveTiresTask(self, task): if self.areAllTiresDisabled(): self.sendTirePositions() self.gameFSM.request('synch') return task.done return task.cont def sendTirePositions(self): tirePositions = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) pos = Point3(tire.getPosition()) tirePositions.append([pos[0], pos[1], pos[2]]) self.sendUpdate('endingPositions', [tirePositions]) def setFinalPositions(self, finalPos): if not self.hasLocalToon: return for index in xrange(len(self.avIdList)): avId = self.avIdList[index] tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) for index in xrange(len(self.avIdList), 4): avId = -index tire = self.getTireBody(avId) np = self.getTireNp(avId) pos = finalPos[index] tire.setPosition(pos[0], pos[1], pos[2]) np.setPos(pos[0], pos[1], pos[2]) def updateInfoLabel(self): self.infoLabel['text'] = TTLocalizer.IceGameInfo % {'curMatch': self.curMatch + 1, 'numMatch': IceGameGlobals.NumMatches, 'curRound': self.curRound + 1, 'numRound': IceGameGlobals.NumRounds} def setMatchAndRound(self, match, round): if not self.hasLocalToon: return self.curMatch = match self.curRound = round self.updateInfoLabel() def setScores(self, match, round, scores): if not self.hasLocalToon: return self.newMatch = match self.newRound = round self.newScores = scores def setNewState(self, state): if not self.hasLocalToon: return self.notify.debug('setNewState gameFSM=%s newState=%s' % (self.gameFSM, state)) self.gameFSM.request(state) def putAllTiresInStartingPositions(self): for index in xrange(len(self.avIdList)): avId = self.avIdList[index] np = self.tireDict[avId]['tireNodePath'] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]['tireBody'] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) for index in xrange(len(self.avIdList), 4): avId = -index np = self.tireDict[avId]['tireNodePath'] np.setPos(IceGameGlobals.StartingPositions[index]) self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos)) np.setHpr(0, 0, 0) quat = np.getQuat() body = self.tireDict[avId]['tireBody'] body.setPosition(IceGameGlobals.StartingPositions[index]) body.setQuaternion(quat) def b_setForceArrowInfo(self, avId, force, heading): self.setForceArrowInfo(avId, force, heading) self.d_setForceArrowInfo(avId, force, heading) def d_setForceArrowInfo(self, avId, force, heading): sendIt = False curTime = self.getCurrentGameTime() if self.sendForceArrowUpdateAsap: sendIt = True elif curTime - self.lastForceArrowUpdateTime > 0.2: sendIt = True if sendIt: self.sendUpdate('setForceArrowInfo', [avId, force, heading]) self.sendForceArrowUpdateAsap = False self.lastForceArrowUpdateTime = self.getCurrentGameTime() def setForceArrowInfo(self, avId, force, heading): if not self.hasLocalToon: return self.updateForceArrow(avId, force, heading) def setupStartOfMatch(self): self.putAllTiresInStartingPositions() szId = self.getSafezoneId() self.numTreasures = IceGameGlobals.NumTreasures[szId] if self.treasures: for treasure in self.treasures: treasure.destroy() self.treasures = [] index = 0 treasureMargin = IceGameGlobals.TireRadius + 1.0 while len(self.treasures) < self.numTreasures: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug('yPos=%s' % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newTreasure = IceTreasure.IceTreasure(self.treasureModel, pos, index, self.doId, penalty=False) goodSpot = True for obstacle in self.obstacles: if newTreasure.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break if goodSpot: for treasure in self.treasures: if newTreasure.nodePath.getDistance(treasure.nodePath) < treasureMargin: goodSpot = False break if goodSpot: self.treasures.append(newTreasure) index += 1 else: newTreasure.destroy() self.numPenalties = IceGameGlobals.NumPenalties[szId] if self.penalties: for penalty in self.penalties: penalty.destroy() self.penalties = [] index = 0 while len(self.penalties) < self.numPenalties: xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5) yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5) self.notify.debug('yPos=%s' % yPos) pos = Point3(xPos, yPos, IceGameGlobals.TireRadius) newPenalty = IceTreasure.IceTreasure(self.penaltyModel, pos, index, self.doId, penalty=True) goodSpot = True for obstacle in self.obstacles: if newPenalty.nodePath.getDistance(obstacle) < treasureMargin: goodSpot = False break if goodSpot: for treasure in self.treasures: if newPenalty.nodePath.getDistance(treasure.nodePath) < treasureMargin: goodSpot = False break if goodSpot: for penalty in self.penalties: if newPenalty.nodePath.getDistance(penalty.nodePath) < treasureMargin: goodSpot = False break if goodSpot: self.penalties.append(newPenalty) index += 1 else: newPenalty.destroy() def toonHitSomething(self, entry): self.notify.debug('---- treasure Enter ---- ') self.notify.debug('%s' % entry) name = entry.getIntoNodePath().getName() parts = name.split('-') if len(parts) < 3: self.notify.debug('collided with %s, but returning' % name) return if not int(parts[1]) == self.doId: self.notify.debug("collided with %s, but doId doesn't match" % name) return treasureNum = int(parts[2]) if 'penalty' in parts[0]: self.__penaltyGrabbed(treasureNum) else: self.__treasureGrabbed(treasureNum) def __treasureGrabbed(self, treasureNum): self.treasures[treasureNum].showGrab() self.treasureGrabSound.play() self.sendUpdate('claimTreasure', [treasureNum]) def setTreasureGrabbed(self, avId, treasureNum): if not self.hasLocalToon: return self.notify.debug('treasure %s grabbed by %s' % (treasureNum, avId)) if avId != self.localAvId: self.treasures[treasureNum].showGrab() i = self.avIdList.index(avId) self.scores[i] += 1 self.scorePanels[i].setScore(self.scores[i]) def __penaltyGrabbed(self, penaltyNum): self.penalties[penaltyNum].showGrab() self.sendUpdate('claimPenalty', [penaltyNum]) def setPenaltyGrabbed(self, avId, penaltyNum): if not self.hasLocalToon: return self.notify.debug('penalty %s grabbed by %s' % (penaltyNum, avId)) if avId != self.localAvId: self.penalties[penaltyNum].showGrab() i = self.avIdList.index(avId) self.scores[i] -= 1 self.scorePanels[i].setScore(self.scores[i]) def postStep(self): DistributedIceWorld.DistributedIceWorld.postStep(self) for count in range(self.colCount): c0, c1 = self.getOrderedContacts(count) if c1 in self.tireCollideIds: tireIndex = self.tireCollideIds.index(c1) if c0 in self.tireCollideIds: self.tireSounds[tireIndex]['tireHit'].play() elif c0 == self.wallCollideId: self.tireSounds[tireIndex]['wallHit'].play() elif c0 == self.obstacleCollideId: self.tireSounds[tireIndex]['obstacleHit'].play() def forceLocalToonToTire(self): toon = localAvatar if toon and self.localAvId in self.tireDict: tireNp = self.tireDict[self.localAvId]['tireNodePath'] toon.reparentTo(tireNp) toon.setPosHpr(0, 0, 0, 0, 0, 0) toon.setY(1.0) toon.setZ(-3)
def loadNewBoard(self): self.progressLabel.stash() self.progressDescriptionLabel.stash() if self.totalScore >= self.config.totalPoints: if self.onDeckBoard: self.onDeckBoard.stash() self.progressDescriptionLabel.stash() taskMgr.remove('SawingGame.updateSawTask') self.request('Outro') return None self.currentBoard = self.onDeckBoard self.currentBoardIndex = self.onDeckBoardIndex self.piece1 = self.currentBoard.find('**/piece_1') self.piece1.setTransparency(1) self.piece2 = self.currentBoard.find('**/piece_2') self.piece2.setTransparency(1) self.cut = self.currentBoard.find('**/piece_cut') self.cut.setColor(self.config.cutColor) self.cut.setTransparency(1) self.board_left = self.piece1.find('**/board') self.board_left.setTransparency(1) self.zone1_left = self.piece1.find('**/zone_1') self.zone1_left.setTransparency(1) self.zone2_left = self.piece1.find('**/zone_2') self.zone2_left.setTransparency(1) self.board_right = self.piece2.find('**/board') self.board_right.setTransparency(1) self.zone1_right = self.piece2.find('**/zone_1') self.zone1_right.setTransparency(1) self.zone2_right = self.piece2.find('**/zone_2') self.zone2_right.setTransparency(1) self.board_left.setCollideMask(SAW_COLLIDE_MASK) self.board_right.setCollideMask(SAW_COLLIDE_MASK) self.cut.setCollideMask(SAW_COLLIDE_MASK) self.zone1_right.setCollideMask(SAW_COLLIDE_MASK) self.zone1_left.setCollideMask(SAW_COLLIDE_MASK) self.zone2_right.setCollideMask(SAW_COLLIDE_MASK) self.zone2_left.setCollideMask(SAW_COLLIDE_MASK) self.startPositions = ( self.currentBoard.find('**/locator_start_0').getPos() + Point3(*self.config.activeBoardPosition), self.currentBoard.find('**/locator_start_1').getPos() + Point3(*self.config.activeBoardPosition)) self.currentStartIndex = 0 for waypoint in self.sawWaypoints: waypoint.removeNode() self.sawWaypoints = [] locator = self.currentBoard.find('**/locator_0') index = 0 while not locator.isEmpty(): self.sawWaypoints.append( SawWaypoint(index, self.currentBoard, locator.getPos())) locator = self.currentBoard.find('**/locator_%i' % (index + 1)) index += 1 self.sawButton.deactivate() self.sawButton.setPos(self.startPositions[self.currentStartIndex]) self.hitBoardPenalty = False self.hitZone1Penalty = False self.hitZone2Penalty = False self.lastMousePos = None self.moveDiffForSound = self.config.playSawingSoundDelta + 0.10000000000000001 self.newBoardSequence = Sequence( Parallel( self.currentBoard.posInterval( self.config.newBoardAnimTime, Point3(*self.config.activeBoardPosition)), self.currentBoard.scaleInterval(self.config.newBoardAnimTime, 1.0)), name='RepairSawingGame.newBoardSequence') if self.state in ['Game']: self.newBoardSequence.append(Func(self.sawButton.activate)) self.newBoardSequence.append(Wait(0.5)) self.newBoardSequence.append(Func(self.moveNewBoardOnDeck)) self.newBoardSequence.start()
def initIntervals(self): dur = Globals.LegalEagle.LiftOffTime nestPos = self.nest.getPos(render) airPos = nestPos + Vec3(0.0, 0.0, Globals.LegalEagle.LiftOffHeight) self.takeOffSeq = Sequence(Parallel( Sequence( Wait(dur * 0.6), LerpPosInterval(self.suit, dur * 0.4, startPos=nestPos, pos=airPos, blendType='easeInOut'))), Wait(1.5), Func(self.request, 'next'), name='%s.takeOffSeq-%i' % (self.__class__.__name__, self.index)) self.landOnNestPosLerp = LerpPosInterval(self.suit, 1.0, startPos=airPos, pos=nestPos, blendType='easeInOut') self.landingSeq = Sequence(Func(self.updateLandOnNestPosLerp), Parallel(self.landOnNestPosLerp), Func(self.request, 'next'), name='%s.landingSeq-%i' % (self.__class__.__name__, self.index)) dur = Globals.LegalEagle.ChargeUpTime self.chargeUpPosLerp = LerpFunc( self.moveAlongChargeUpMopathFunc, fromData=0.0, toData=self.chargeUpMotionPath.getMaxT(), duration=dur, blendType='easeInOut') self.chargeUpAttackSeq = Sequence( Func(self.updateChargeUpPosLerp), self.chargeUpPosLerp, Func(self.request, 'next'), name='%s.chargeUpAttackSeq-%i' % (self.__class__.__name__, self.index)) dur = Globals.LegalEagle.RetreatToNestTime self.retreatToNestPosLerp = LerpPosInterval(self.suit, dur, startPos=Vec3(0, 0, 0), pos=airPos, blendType='easeInOut') self.retreatToNestSeq = Sequence(Func(self.updateRetreatToNestPosLerp), self.retreatToNestPosLerp, Func(self.request, 'next'), name='%s.retreatToNestSeq-%i' % (self.__class__.__name__, self.index)) dur = Globals.LegalEagle.RetreatToSkyTime self.retreatToSkyPosLerp = LerpFunc( self.moveAlongRetreatMopathFunc, fromData=0.0, toData=self.retreatToSkyMotionPath.getMaxT(), duration=dur, blendType='easeOut') self.retreatToSkySeq = Sequence(Func(self.updateRetreatToSkyPosLerp), self.retreatToSkyPosLerp, Func(self.request, 'next'), name='%s.retreatToSkySeq-%i' % (self.__class__.__name__, self.index)) dur = Globals.LegalEagle.PreAttackTime self.preAttackLerpXY = LerpFunc(self.updateAttackXY, fromData=0.0, toData=1.0, duration=dur) self.preAttackLerpZ = LerpFunc(self.updateAttackZ, fromData=0.0, toData=1.0, duration=dur, blendType='easeOut') dur = Globals.LegalEagle.PostAttackTime self.postAttackPosLerp = LerpPosInterval(self.suit, dur, startPos=Vec3(0, 0, 0), pos=Vec3(0, 0, 0)) self.attackSeq = Sequence( Parallel(self.preAttackLerpXY, self.preAttackLerpZ), Func(self.updatePostAttackPosLerp), self.postAttackPosLerp, Func(self.request, 'next'), name='%s.attackSeq-%i' % (self.__class__.__name__, self.index)) dur = Globals.LegalEagle.CooldownTime self.cooldownSeq = Sequence(Wait(dur), Func(self.request, 'next'), name='%s.cooldownSeq-%i' % (self.__class__.__name__, self.index)) self.propTrack = Sequence( ActorInterval(self.prop, 'propeller', startFrame=0, endFrame=14)) self.hoverOverNestSeq = Sequence( ActorInterval(self.suit, 'landing', startFrame=10, endFrame=20, playRate=0.5), ActorInterval(self.suit, 'landing', startFrame=20, endFrame=10, playRate=0.5))
class BambooCane(ToonUpGag): def __init__(self): ToonUpGag.__init__(self, CIGlobals.BambooCane, 'phase_5/models/props/cane.bam', 40, 45, 100, GagGlobals.BAMBOO_CANE_SFX, 1) self.setImage('phase_3.5/maps/bamboo-cane.png') self.hatPath = 'phase_5/models/props/hat.bam' self.hat = None self.track = None self.scaleDuration = 0.5 self.scaleUp = None self.scaleDown = None self.soundInterval = None self.timeout = 5.0 def buildHat(self): self.cleanupHat() self.hat = loader.loadModel(self.hatPath) def cleanupHat(self): if self.hat: self.hat.removeNode() def buildScaleTracks(self): props = [] props.append(self.hat) props.append(self.gag) self.scaleUp = self.getScaleTrack(props, self.scaleDuration, self.PNTNEARZERO, self.PNTNORMAL) self.scaleDown = self.getScaleTrack(props, self.scaleDuration, self.PNTNORMAL, self.PNTNEARZERO) def start(self): super(BambooCane, self).start() if not self.hat: self.buildHat() if not self.gag: self.build() self.setupHandJoints() if not self.scaleUp: self.buildScaleTracks() self.placeProp(self.handJoint, self.hat, Point3(0.23, 0.09, 0.69), Point3(180, 0, 0)) self.placeProp(self.lHandJoint, self.gag, Point3(-0.28, 0.0, 0.14), Point3(0.0, 0.0, -150.0)) self.soundInterval = self.getSoundTrack(0.2, self.gag, 6.4) propInterval = Sequence() propInterval.append(self.scaleUp) propInterval.append( Wait(base.localAvatar.getDuration('happy-dance') - 2)) if self.avatar == base.localAvatar: propInterval.append(Func(self.setHealAmount)) propInterval.append(Func(self.healNearbyAvatars, 25)) propInterval.append(self.scaleDown) propInterval.append(Func(self.cleanupGag)) propInterval.append(Func(self.reset)) self.track = Parallel(propInterval, ActorInterval(self.avatar, 'happy-dance'), Func(self.soundInterval.start)) self.track.start() def equip(self): # self.gag returns the cane object. super(BambooCane, self).equip() self.build() self.buildHat() self.buildScaleTracks() def unEquip(self): if self.track: self.soundInterval.finish() self.track.finish() self.track = None self.reset() if self.scaleDown: Sequence(self.scaleDown, Func(self.cleanupGag)).start() def cleanupGag(self): if self.gag: self.gag.removeNode() self.cleanupHat()
def enterScoring(self): sortedByDistance = [] for avId in self.avIdList: np = self.getTireNp(avId) pos = np.getPos() pos.setZ(0) sortedByDistance.append((avId, pos.length())) def compareDistance(x, y): if x[1] - y[1] > 0: return 1 elif x[1] - y[1] < 0: return -1 else: return 0 sortedByDistance.sort(cmp=compareDistance) self.scoreMovie = Sequence() curScale = 0.01 curTime = 0 self.scoreCircle.setScale(0.01) self.scoreCircle.show() self.notify.debug('newScores = %s' % self.newScores) circleStartTime = 0 for index in xrange(len(sortedByDistance)): distance = sortedByDistance[index][1] avId = sortedByDistance[index][0] scorePanelIndex = self.avIdList.index(avId) time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec if time < 0: time = 0.01 scaleXY = distance + IceGameGlobals.TireRadius self.notify.debug('circleStartTime = %s' % circleStartTime) self.scoreMovie.append( Parallel( LerpScaleInterval(self.scoreCircle, time, Point3(scaleXY, scaleXY, 1.0)), SoundInterval(self.scoreCircleSound, duration=time, startTime=circleStartTime))) circleStartTime += time startScore = self.scorePanels[scorePanelIndex].getScore() destScore = self.newScores[scorePanelIndex] self.notify.debug('for avId %d, startScore=%d, newScores=%d' % (avId, startScore, destScore)) def increaseScores(t, scorePanelIndex=scorePanelIndex, startScore=startScore, destScore=destScore): oldScore = self.scorePanels[scorePanelIndex].getScore() diff = destScore - startScore newScore = int(startScore + diff * t) if newScore > oldScore: base.playSfx(self.countSound) self.scorePanels[scorePanelIndex].setScore(newScore) self.scores[scorePanelIndex] = newScore duration = (destScore - startScore) * IceGameGlobals.ScoreCountUpRate tireNp = self.tireDict[avId]['tireNodePath'] self.scoreMovie.append( Parallel( LerpFunctionInterval(increaseScores, duration), Sequence( LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1))))) curScale += distance self.scoreMovie.append( Func(self.sendUpdate, 'reportScoringMovieDone', [])) self.scoreMovie.start()
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.mp3') 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 doDeathTrack(self): def removeDeathSuit(suit, deathSuit): if not deathSuit.isEmpty(): deathSuit.detachNode() suit.cleanupLoseActor() self.deathSuit.reparentTo(self.suit.getParent()) self.deathSuit.setScale(self.suit.getScale()) self.deathSuit.setPos(render, self.suit.getPos(render)) self.deathSuit.setHpr(render, self.suit.getHpr(render)) self.suit.hide() self.collNodePath.reparentTo(self.deathSuit) gearPoint = Point3(0, 0, self.suit.height / 2.0 + 2.0) smallGears = BattleParticles.createParticleEffect( file='gearExplosionSmall') singleGear = BattleParticles.createParticleEffect('GearExplosion', numParticles=1) smallGearExplosion = BattleParticles.createParticleEffect( 'GearExplosion', numParticles=10) bigGearExplosion = BattleParticles.createParticleEffect( 'BigGearExplosion', numParticles=30) smallGears.setPos(gearPoint) singleGear.setPos(gearPoint) smallGearExplosion.setPos(gearPoint) bigGearExplosion.setPos(gearPoint) smallGears.setDepthWrite(False) singleGear.setDepthWrite(False) smallGearExplosion.setDepthWrite(False) bigGearExplosion.setDepthWrite(False) suitTrack = Sequence( Func(self.collNodePath.stash), ActorInterval(self.deathSuit, 'lose', startFrame=80, endFrame=140), Func(removeDeathSuit, self.suit, self.deathSuit, name='remove-death-suit')) explosionTrack = Sequence( Wait(1.5), MovieUtil.createKapowExplosionTrack(self.deathSuit, explosionPoint=gearPoint)) gears1Track = Sequence(ParticleInterval(smallGears, self.deathSuit, worldRelative=0, duration=4.3, cleanup=True), name='gears1Track') gears2MTrack = Track((0.0, explosionTrack), (0.7, ParticleInterval(singleGear, self.deathSuit, worldRelative=0, duration=5.7, cleanup=True)), (5.2, ParticleInterval(smallGearExplosion, self.deathSuit, worldRelative=0, duration=1.2, cleanup=True)), (5.4, ParticleInterval(bigGearExplosion, self.deathSuit, worldRelative=0, duration=1.0, cleanup=True)), name='gears2MTrack') def removeParticle(particle): if particle and hasattr(particle, 'renderParent'): particle.cleanup() del particle removeParticles = Sequence(Func(removeParticle, smallGears), Func(removeParticle, singleGear), Func(removeParticle, smallGearExplosion), Func(removeParticle, bigGearExplosion)) self.deathTrack = Sequence( Parallel(suitTrack, gears2MTrack, gears1Track, self._deathSoundIval), removeParticles) self.deathTrack.start()
def makeToonReleaseInterval(self, toon): temp1 = self.waterPitcherNode.attachNewNode('temp1') temp1.setPos(self.toonPitcherPosition) temp2 = self.waterPitcherNode.attachNewNode('temp2') temp2.setPos(0, -10, -self.waterPitcherNode.getZ()) startPos = temp1.getPos(render) endPos = temp2.getPos(render) temp1.removeNode() temp2.removeNode() def getSlideToPos(toon = toon): return render.getRelativePoint(toon, Point3(0, -10, 0)) if self.gotHitByBoss: self.notify.debug('creating zap interval instead') grabIval = Sequence(Func(toon.loop, 'neutral'), Func(toon.wrtReparentTo, render), Parallel(ActorInterval(toon, 'slip-backward'), toon.posInterval(0.5, getSlideToPos, fluid=1))) else: grabIval = Sequence(Func(toon.loop, 'neutral'), Func(toon.wrtReparentTo, render), Parallel(ActorInterval(toon, 'jump'), Sequence(Wait(0.43), ProjectileInterval(toon, duration=0.9, startPos=startPos, endPos=endPos)))) return grabIval
def makeToonGrabInterval(self, toon): toon.pose('leverNeutral', 0) toon.update() rightHandPos = toon.rightHand.getPos(toon) self.toonPitcherPosition = Point3(self.handPos[0] - rightHandPos[0], self.handPos[1] - rightHandPos[1], 0) destZScale = rightHandPos[2] / self.handPos[2] grabIval = Sequence(Func(toon.wrtReparentTo, self.waterPitcherNode), Func(toon.loop, 'neutral'), Parallel(ActorInterval(toon, 'jump'), Sequence(Wait(0.43), Parallel(ProjectileInterval(toon, duration=0.9, startPos=toon.getPos(self.waterPitcherNode), endPos=self.toonPitcherPosition), LerpHprInterval(toon, 0.9, Point3(0, 0, 0)), LerpScaleInterval(self.waterPitcherModel, 0.9, Point3(1, 1, destZScale))))), Func(toon.setPos, self.toonPitcherPosition), Func(toon.loop, 'leverNeutral')) return grabIval
def start(self): SoundGag.start(self) INSTRUMENT_SCALE_MODIFIER = 0.5 delayTime = 2.45 delayUntilAppearSound = 1.0 tracks = Parallel() instrMin = Vec3(0.001, 0.001, 0.001) instrMax = Vec3(0.65, 0.65, 0.65) instrMax *= INSTRUMENT_SCALE_MODIFIER instrStretch = Vec3(0.6, 1.1, 0.6) instrStretch *= INSTRUMENT_SCALE_MODIFIER def setInstrumentStats(): self.gag.setPos(-1.1, -1.4, 0.1) self.gag.setHpr(145, 0, 0) self.gag.setScale(instrMin) megaphoneShow = Sequence( Func(self.placeProp, self.handJoint, self.megaphone), Func(self.placeProp, self.handJoint, self.gag), Func(setInstrumentStats)) grow = self.getScaleIntervals(self.gag, duration=0.2, startScale=instrMin, endScale=instrMax) instrumentAppear = grow stretchInstr = self.getScaleBlendIntervals(self.gag, duration=0.2, startScale=instrMax, endScale=instrStretch, blendType='easeOut') backInstr = self.getScaleBlendIntervals(self.gag, duration=0.2, startScale=instrStretch, endScale=instrMax, blendType='easeIn') stretchMega = self.getScaleBlendIntervals( self.megaphone, duration=0.2, startScale=self.megaphone.getScale(), endScale=0.9, blendType='easeOut') backMega = self.getScaleBlendIntervals( self.megaphone, duration=0.2, startScale=0.9, endScale=self.megaphone.getScale(), blendType='easeIn') attackTrack = Parallel(Sequence(stretchInstr, backInstr), Sequence(stretchMega, backMega)) megaphoneTrack = Sequence( megaphoneShow, Wait(delayUntilAppearSound), SoundInterval(self.appearSfx, node=self.avatar), instrumentAppear) tracks.append(megaphoneTrack) tracks.append(ActorInterval(self.avatar, 'sound')) instrumentshrink = self.getScaleIntervals(self.gag, duration=0.1, startScale=instrMax, endScale=instrMin) soundTrack = Sequence( Wait(delayTime), Parallel(attackTrack, SoundInterval(self.soundSfx, node=self.avatar), Wait(0.2), instrumentshrink, Func(self.damageCogsNearby), Wait(0.4), Func(self.finish))) tracks.append(soundTrack) tracks.start() self.tracks = tracks
def setHillType(self, type): if self.isUp and (self.hillType == MoleFieldBase.HILL_MOLE and type == MoleFieldBase.HILL_BOMB or self.hillType == MoleFieldBase.HILL_BOMB and type == MoleFieldBase.HILL_MOLE): return self.hillType = type self.moleHead.removeNode() if type == MoleFieldBase.HILL_MOLE: self.moleHead = loader.loadModel( 'phase_12/models/bossbotHQ/mole_norm') self.moleColNodePath.setScale(3.0) self.moleHead.setH(0) self.mole.setBillboardAxis(localAvatar, 0) if type == MoleFieldBase.HILL_BOMB or type == MoleFieldBase.HILL_COGWHACKED: self.moleHead = loader.loadModel( 'phase_12/models/bossbotHQ/mole_cog') self.moleColNodePath.setScale(1.0) self.mole.setBillboardAxis(localAvatar, 0) if type == MoleFieldBase.HILL_COGWHACKED: self.doMoleDown() BattleParticles.loadParticles() singleGear = BattleParticles.createParticleEffect( 'GearExplosion', numParticles=1) smallGearExplosion = BattleParticles.createParticleEffect( 'GearExplosion', numParticles=10) bigGearExplosion = BattleParticles.createParticleEffect( 'BigGearExplosion', numParticles=30) gears2MTrack = Track((0.0, ParticleInterval(singleGear, self.hill, worldRelative=1, duration=5.7, cleanup=True)), (0.0, ParticleInterval(smallGearExplosion, self.hill, worldRelative=0, duration=1.2, cleanup=True)), (0.3, ParticleInterval(bigGearExplosion, self.hill, worldRelative=0, duration=1.0, cleanup=True)), name='gears2MTrack') gears2MTrack.start() self.popIval = Sequence( Parallel( Sequence( LerpPosInterval(self.moleHead, 0.05, Point3(0.28, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, -0.23, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.0, 0.28)), LerpPosInterval(self.moleHead, 0.05, Point3(-0.35, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.28, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.31, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, -0.32, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.0, 0.48)), LerpPosInterval(self.moleHead, 0.05, Point3(-0.28, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.29, 0.0)))), LerpPosInterval(self.mole, 0.5, Point3(0, 0, -2.5)), Func(self.setHillType, MoleFieldBase.HILL_BOMB)) self.popIval.start() else: self.moleHead.setH(0) if type == MoleFieldBase.HILL_WHACKED: self.moleHead = loader.loadModel( 'phase_12/models/bossbotHQ/mole_hit') self.mole.setBillboardAxis(0) self.moleColNodePath.setScale(0.0) if self.popIval: self.popIval.finish() if self.downIval: self.downIval.finish() self.mole.setPos(0.0, 0.0, 0.0) self.popIval = Sequence( Parallel( Sequence( LerpPosInterval(self.moleHead, 0.05, Point3(0.18, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, -0.13, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.0, 0.18)), LerpPosInterval(self.moleHead, 0.05, Point3(-0.15, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.18, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.11, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, -0.12, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.0, 0.18)), LerpPosInterval(self.moleHead, 0.05, Point3(-0.18, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.13, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.18, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, -0.15, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.0, 0.18)), LerpPosInterval(self.moleHead, 0.05, Point3(-0.16, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.18, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.11, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, -0.18, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.0, 0.17)), LerpPosInterval(self.moleHead, 0.05, Point3(-0.18, 0.0, 0.0)), LerpPosInterval(self.moleHead, 0.05, Point3(0.0, 0.0, 0.0))), Sequence(LerpScaleInterval(self.moleHead, 0.5, 3.5), LerpScaleInterval(self.moleHead, 0.5, 1.0))), LerpPosInterval(self.mole, 0.5, Point3(0, 0, -2.5)), Func(self.setHillType, MoleFieldBase.HILL_MOLE)) self.popIval.start() self.moleHead.reparentTo(self.mole)
class DistributedNPCToon(DistributedToon): notify = directNotify.newCategory('DistributedNPCToon') def __init__(self, cr): DistributedToon.__init__(self, cr) self.collisionNodePath = None self.cameraTrack = None self.originIndex = None self.npcId = None self.currentChatIndex = 0 self.chatArray = None return def setLoadout(self, foo): pass def lookAtAvatar(self, avId): av = self.cr.doId2do.get(avId) if av: self.headsUp(av) def setNpcId(self, id): self.npcId = id def getNpcId(self): return self.npcId def setOriginIndex(self, index): self.originIndex = index def getOriginIndex(self): return self.originIndex def __setupCollisions(self): sphere = CollisionSphere(0, 0, 0, 4) sphere.setTangible(0) collisionNode = CollisionNode(self.uniqueName('NPCToonSphere')) collisionNode.addSolid(sphere) collisionNode.setCollideMask(CIGlobals.WallBitmask) self.collisionNodePath = self.attachNewNode(collisionNode) self.collisionNodePath.setY(1.5) def __removeCollisions(self): if self.collisionNodePath: self.collisionNodePath.removeNode() self.collisionNodePath = None return def handleEnterCollision(self, entry): self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.stopSmartCamera() self.sendUpdate('requestEnter', []) def doCameraNPCInteraction(self): currCamPos = camera.getPos() currCamHpr = camera.getHpr() camera.setX(camera.getX() + 5) camera.setY(camera.getY() + 5) camera.headsUp(self) newCamPos = camera.getPos() newCamHpr = camera.getHpr() camera.setPos(currCamPos) camera.setHpr(currCamHpr) self.cameraTrack = Parallel( LerpPosInterval(camera, duration=1.0, pos=newCamPos, startPos=currCamPos, blendType='easeOut'), LerpQuatInterval(camera, duration=1.0, quat=newCamHpr, startHpr=currCamHpr, blendType='easeOut')) self.cameraTrack.start() def stopCameraTrack(self): if self.cameraTrack: self.cameraTrack.finish() self.cameraTrack = None return def oneChatThenExit(self): self.acceptOnce('mouse1-up', self.d_requestExit) def enterAccepted(self): self.doCameraNPCInteraction() questData = base.localAvatar.questManager.getQuestAndIdWhereCurrentObjectiveIsToVisit( self.npcId) if questData: quest = questData[1] self.currentQuestObjective = quest.currentObjectiveIndex self.currentQuestId = questData[0] self.currentChatIndex = 0 if CIGlobals.NPCToonDict[self.npcId][3] == CIGlobals.NPC_HQ: if not quest.isComplete(): self.doNPCChat(array=Quests.QuestHQOfficerDialogue) if CIGlobals.NPCToonDict[self.npcId][3] == CIGlobals.NPC_REGULAR: self.doNPCChat(array=Quests.QuestNPCDialogue) def doNPCChat(self, array=Quests.QuestNPCDialogue, chat=None): if array and not chat: self.chatArray = array self.b_setChat(array[self.currentQuestId][ self.currentQuestObjective][self.currentChatIndex]) self.currentChatIndex += 1 Sequence(Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.doNextNPCChat)).start() else: if chat and not array: self.b_setChat(chat) Sequence( Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.d_requestExit)).start() def d_requestExit(self): self.sendUpdate('requestExit', []) def doNextNPCChat(self): if self.currentChatIndex >= len(self.chatArray[self.currentQuestId][ self.currentQuestObjective]): self.chatArray = None self.d_requestExit() else: self.doNPCChat(self.chatArray) return def rejectEnter(self): self.exitAccepted() def exitAccepted(self): self.stopCameraTrack() self.cr.playGame.getPlace().fsm.request('walk') self.acceptCollisions() def acceptCollisions(self): self.acceptOnce('enter' + self.uniqueName('NPCToonSphere'), self.handleEnterCollision) def ignoreCollisions(self): self.ignore('enter' + self.uniqueName('NPCToonSphere')) def __npcOriginPoll(self, task): if task.time > 4.0: self.notify.warning( 'Giving up waiting for npc origin after %d seconds. Will parent to render.' % task.time) self.reparentTo(render) return task.done npcOrigin = render.find('**/npc_origin_' + str(self.originIndex)) if not npcOrigin.isEmpty(): self.reparentTo(npcOrigin) return task.done return task.cont def startNPCOriginPoll(self): base.taskMgr.add(self.__npcOriginPoll, self.uniqueName('NPCOriginPoll')) def stopNPCOriginPoll(self): base.taskMgr.remove(self.uniqueName('NPCOriginPoll')) def setupNameTag(self, tempName=None): DistributedToon.setupNameTag(self, tempName) self.nametag.setNametagColor( NametagGlobals.NametagColors[NametagGlobals.CCNPC]) self.nametag.setActive(0) self.nametag.updateAll() def announceGenerate(self): DistributedToon.announceGenerate(self) self.startLookAround() self.__setupCollisions() npcOrigin = render.find('**/npc_origin_' + str(self.originIndex)) if not npcOrigin.isEmpty(): self.reparentTo(npcOrigin) else: self.startNPCOriginPoll() self.acceptCollisions() def disable(self): self.ignore('mouse1-up') self.stopLookAround() self.stopNPCOriginPoll() self.chatArray = None self.originIndex = None self.npcId = None self.stopCameraTrack() self.ignoreCollisions() self.__removeCollisions() DistributedToon.disable(self) return
def splitBoard(self): self.sawingLine.reset() board = self.currentBoard boardIndex = self.currentBoardIndex if self.hitZone2Penalty: boardSplitAnim = Parallel( LerpPosInterval(self.board_left, duration=self.config.splitBoardAnimTime, pos=Point3(-2.0, 0.0, 0.0)), LerpPosInterval(self.board_right, duration=self.config.splitBoardAnimTime, pos=Point3(2.0, 0.0, 0.0)), LerpFunc(self.zone2_left.setSa, duration=self.config.splitBoardAnimTime / 2.0, fromData=1.0, toData=0.0), LerpFunc(self.zone2_right.setSa, duration=self.config.splitBoardAnimTime / 2.0, fromData=1.0, toData=0.0), LerpFunc(self.zone1_left.setSa, duration=self.config.splitBoardAnimTime / 2.0, fromData=1.0, toData=0.0), LerpFunc(self.zone1_right.setSa, duration=self.config.splitBoardAnimTime / 2.0, fromData=1.0, toData=0.0), LerpFunc(self.cut.setSa, duration=self.config.splitBoardAnimTime / 2.0, fromData=1.0, toData=0.0)) elif self.hitZone1Penalty: boardSplitAnim = Parallel( LerpPosInterval(self.board_left, duration=self.config.splitBoardAnimTime, pos=Point3(-2.0, 0.0, 0.0)), LerpPosInterval(self.board_right, duration=self.config.splitBoardAnimTime, pos=Point3(2.0, 0.0, 0.0)), LerpPosInterval(self.zone2_left, duration=self.config.splitBoardAnimTime, pos=Point3(-2.0, 0.0, 0.0)), LerpPosInterval(self.zone2_right, duration=self.config.splitBoardAnimTime, pos=Point3(2.0, 0.0, 0.0)), LerpFunc(self.zone1_left.setSa, duration=self.config.splitBoardAnimTime / 2.0, fromData=1.0, toData=0.0), LerpFunc(self.zone1_right.setSa, duration=self.config.splitBoardAnimTime / 2.0, fromData=1.0, toData=0.0), LerpFunc(self.cut.setSa, duration=self.config.splitBoardAnimTime / 2.0, fromData=1.0, toData=0.0)) else: boardSplitAnim = Parallel( LerpPosInterval(self.piece1, duration=self.config.splitBoardAnimTime, pos=Point3(-2.0, self.config.boardYDist, 0.0)), LerpPosInterval(self.piece2, duration=self.config.splitBoardAnimTime, pos=Point3(2.0, self.config.boardYDist, 0.0)), LerpFunc(self.cut.setSa, duration=self.config.splitBoardAnimTime / 2.0, fromData=1.0, toData=0.0)) self.splitBoardSequence = Sequence( Func(self.updateScore), Func(self.boardComplete.play), boardSplitAnim, Func(board.stash), Func(self.piece1.setPos, self.piece1.getPos()), Func(self.piece2.setPos, self.piece2.getPos()), Func(self.board_right.setPos, self.board_right.getPos()), Func(self.board_left.setPos, self.board_left.getPos()), Func(self.zone2_right.setPos, self.zone2_right.getPos()), Func(self.zone2_left.setPos, self.zone2_left.getPos()), Func(self.zone1_right.setPos, self.zone1_right.getPos()), Func(self.zone1_left.setPos, self.zone1_left.getPos()), Func(self.cut.setSa, 1.0), Func(self.zone1_right.setSa, 1.0), Func(self.zone1_left.setSa, 1.0), Func(self.zone2_right.setSa, 1.0), Func(self.zone2_left.setSa, 1.0), Func(self.board_right.setSa, 1.0), Func(self.board_left.setSa, 1.0), Func(self.loadNewBoard), Func(self.addBoardBackToPool, board, boardIndex), name='RepairSawGame.splitBoardSequence') self.splitBoardSequence.start()
def fillSlot(self, index, avId, wantBoardingShow=0): self.notify.debug('%s.fillSlot(%s, %s, ... %s)' % (self.doId, index, avId, globalClock.getRealTime())) request = self.toonRequests.get(index) if request: self.cr.relatedObjectMgr.abortRequest(request) del self.toonRequests[index] if avId == 0: pass elif avId not in self.cr.doId2do: func = PythonUtil.Functor(self.gotToon, index, avId) self.toonRequests[index] = self.cr.relatedObjectMgr.requestObjects( [avId], allCallback=func) elif not self.isSetup: self.deferredSlots.append((index, avId, wantBoardingShow)) else: if avId == base.localAvatar.getDoId(): place = base.cr.playGame.getPlace() if not place: return elevator = self.getPlaceElevator() if elevator == None: place.fsm.request('elevator') elevator = self.getPlaceElevator() if not elevator: return self.localToonOnBoard = 1 if hasattr(localAvatar, 'boardingParty') and localAvatar.boardingParty: localAvatar.boardingParty.forceCleanupInviteePanel() localAvatar.boardingParty.forceCleanupInviterPanels() if hasattr(base.localAvatar, 'elevatorNotifier'): base.localAvatar.elevatorNotifier.cleanup() cameraTrack = Sequence() cameraTrack.append( Func(elevator.fsm.request, 'boarding', [self.getElevatorModel()])) cameraTrack.append(Func(elevator.fsm.request, 'boarded')) toon = self.cr.doId2do[avId] toon.stopSmooth() toon.wrtReparentTo(self.golfKart) sitStartDuration = toon.getDuration('sit-start') jumpTrack = self.generateToonJumpTrack(toon, index) track = Sequence(jumpTrack, Func(toon.setAnimState, 'Sit', 1.0), Func(self.clearToonTrack, avId), name=toon.uniqueName('fillElevator'), autoPause=1) if wantBoardingShow: boardingTrack, boardingTrackType = self.getBoardingTrack( toon, index, True) track = Sequence(boardingTrack, track) if avId == base.localAvatar.getDoId(): cameraWaitTime = 2.5 if boardingTrackType == BoardingGroupShow.TRACK_TYPE_RUN: cameraWaitTime = 0.5 cameraTrack = Sequence(Wait(cameraWaitTime), cameraTrack) if self.canHideBoardingQuitBtn(avId): track = Sequence( Func(localAvatar.boardingParty.groupPanel.disableQuitButton ), track) if avId == base.localAvatar.getDoId(): track = Parallel(cameraTrack, track) track.delayDelete = DelayDelete.DelayDelete( toon, 'CogKart.fillSlot') self.storeToonTrack(avId, track) track.start() self.fillSlotTrack = track self.boardedAvIds[avId] = None return
def createOnePlayerSequence(self, index, duration): numVotes = self.votes[index] direction = self.directions[index] def ticketTicker(t, label=self.entryList[index][direction + 1], startVotes=0, endVotes=numVotes): label['text'] = str(int(t * endVotes + startVotes)) track = Parallel() startVotes = 0 for prev in range(index): if self.directions[prev] == direction: startVotes += self.votes[prev] def totalTicker(t, label=self.totalVotesLabels[direction], startVotes=startVotes, additionalVotes=numVotes): label['text'] = str(int(t * additionalVotes + startVotes)) track.append( LerpFunc(totalTicker, duration=duration, name='countTotal %d' % index)) if index in self.avVotesLabel: def avVotesTicker(t, label=self.avVotesLabel[index], startVotes=0, endVotes=numVotes, direction=direction): oldValue = label['text'] newValue = int(t * endVotes + startVotes) label['text'] = str(newValue) if not oldValue == label['text']: if newValue: if direction == 0: self.upArrowSfx[self.curArrowSfxIndex].play() else: self.downArrowSfx[self.curArrowSfxIndex].play() self.curArrowSfxIndex += 1 if self.curArrowSfxIndex >= len(self.upArrowSfx): self.curArrowSfxIndex = 0 label = self.avVotesLabel[index] track.append( Func(self.avVotesLabel[index].show, name='showName %d' % index)) if index in self.avArrows: track.append( Func(self.avArrows[index].show, name='showArrow %d' % index)) if direction == 0 and numVotes: pass elif direction == 1 and numVotes: pass else: track.append(SoundInterval(self.noVoteSfx)) track.append( LerpFunc(avVotesTicker, duration=duration, name='countAvVotes %d' % index)) return track
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.nametag.setNametag2d(None) suit.nametag.setNametag3d(None) 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) 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): 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
class DistributedPieTurret(DistributedAvatar, DistributedSmoothNode): notify = directNotify.newCategory('DistributedPieTurret') def __init__(self, cr): DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.fsm = ClassicFSM( 'DistributedPieTurret', [ State('off', self.enterOff, self.exitOff), State('scan', self.enterScan, self.exitScan), State('shoot', self.enterShoot, self.exitShoot) ], 'off', 'off' ) self.fsm.enterInitialState() self.reloadTime = 0.25 self.cannon = None self.track = None self.owner = None self.gag = None self.readyGag = None self.hitGag = None self.explosion = None self.wallCollNode = None self.eventCollNode = None self.event = None self.suit = None self.eventId = None self.entities = [] self.upgradeID = None self.deathEvent = None def setOwner(self, avatar): self.owner = avatar def getOwner(self): return self.owner def setGag(self, upgradeId): gags = {0 : CIGlobals.WholeCreamPie, 1 : CIGlobals.WholeFruitPie, 2 : CIGlobals.BirthdayCake, 3 : CIGlobals.WeddingCake} self.gag = gags.get(upgradeId) if not self.readyGag: self.loadGagInTurret() def b_setGag(self, upgradeId): self.sendUpdate('setGag', [upgradeId]) self.setGag(upgradeId) self.upgradeID = upgradeId def getGag(self): return self.gag def getGagID(self): return self.upgradeID def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def announceGenerate(self): DistributedAvatar.announceGenerate(self) DistributedSmoothNode.announceGenerate(self) self.healthLabel.setScale(1.1) self.deathEvent = self.uniqueName('DistributedPieTurret-death') self.makeTurret() def disable(self): self.fsm.requestFinalState() del self.fsm # This should fix crashes related to Sequences. if self.track: self.track.pause() self.track = None # Cleanup entities. for ent in self.entities: ent.cleanup() self.entities = None # Get rid of explosions. if self.explosion: self.explosion.removeNode() self.explosion = None self.removeTurret() DistributedSmoothNode.disable(self) DistributedAvatar.disable(self) def showAndMoveHealthLabel(self): self.unstashHpLabel() self.stopMovingHealthLabel() moveTrack = LerpPosInterval(self.healthLabel, duration = 0.5, pos = Point3(0, 0, 5), startPos = Point3(0, 0, 0), blendType = 'easeOut') self.healthLabelTrack = Sequence(moveTrack, Wait(1.0), Func(self.stashHpLabel)) self.healthLabelTrack.start() # BEGIN STATES def enterShoot(self, suitId): if self.cannon: smoke = loader.loadModel("phase_4/models/props/test_clouds.bam") smoke.setBillboardPointEye() smoke.reparentTo(self.cannon.find('**/cannon')) smoke.setPos(0, 6, -3) smoke.setScale(0.5) smoke.wrtReparentTo(render) self.suit = self.cr.doId2do.get(suitId) self.cannon.find('**/cannon').lookAt(self.suit.find('**/joint_head')) self.cannon.find('**/square_drop_shadow').headsUp(self.suit.find('**/joint_head')) self.track = Sequence(Parallel(LerpScaleInterval(smoke, 0.5, 3), LerpColorScaleInterval(smoke, 0.5, Vec4(2, 2, 2, 0))), Func(smoke.removeNode)) self.track.start() self.createAndShootGag() def exitShoot(self): if hasattr(self, 'suit'): del self.suit def shoot(self, suitId): self.fsm.request('shoot', [suitId]) def scan(self, timestamp = None, afterShooting = 0): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.fsm.request('scan', [ts, afterShooting]) def buildScanTrack(self, ts = None): if self.track: self.track.pause() self.track = None self.track = Parallel( Sequence( LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ), Sequence( LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ) ) if ts: self.track.loop(ts) else: self.track.loop() def enterScan(self, ts = 0, afterShooting = 0): if afterShooting: self.track = Parallel( LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (-60, 0, 0), startHpr = self.cannon.find('**/cannon').getHpr(), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (-60, 0, 0), startHpr = self.cannon.find('**/square_drop_shadow').getHpr(), blendType = 'easeInOut'), name = "afterShootTrack" + str(id(self)) ) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self._afterShootTrackDone) self.track.start(ts) else: self.buildScanTrack(ts) def exitScan(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None def enterOff(self): pass def exitOff(self): pass # END STATES def _afterShootTrackDone(self): self.buildScanTrack() def makeTurret(self): self.cannon = loader.loadModel('phase_4/models/minigames/toon_cannon.bam') self.cannon.reparentTo(self) self.loadGagInTurret() self.setupWallSphere() if self.isLocal(): self.setupEventSphere() def removeTurret(self): self.removeWallSphere() self.removeGagInTurret() if self.cannon: self.cannon.removeNode() self.cannon = None def getCannon(self): return self.cannon.find('**/cannon') def setupWallSphere(self): sphere = CollisionSphere(0.0, 0.0, 0.0, 3.0) node = CollisionNode('DistributedPieTurret.WallSphere') node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.wallCollNode = self.cannon.attachNewNode(node) self.wallCollNode.setZ(2) self.wallCollNode.setY(1.0) def removeWallSphere(self): if self.wallCollNode: self.wallCollNode.removeNode() self.wallCollNode = None def createAndShootGag(self): if not self.readyGag: self.loadGagInTurret() if self.readyGag: self.readyGag.shoot(Point3(0, 200, -90)) self.entities.append(self.readyGag) collideEventName = self.readyGag.getCollideEventName() self.readyGag = None if self.isLocal(): self.acceptOnce(collideEventName, self.handleGagCollision) Sequence(Wait(self.reloadTime), Func(self.loadGagInTurret)).start() def loadGagInTurret(self): if self.cannon and self.gag: self.removeGagInTurret() self.eventId = random.uniform(0, 100000000) self.readyGag = TurretGag(self, self.uniqueName('pieTurretCollision') + str(self.eventId), self.gag) self.readyGag.build() def removeGagInTurret(self): if self.readyGag: self.readyGag.cleanup() self.readyGag = None def makeSplat(self, index, pos): if index >= len(self.entities): return ent = self.entities[index] gagClass = ent.gagClass splat = gagClass.buildSplat(gagClass.splatScale, gagClass.splatColor) base.audio3d.attachSoundToObject(gagClass.hitSfx, splat) splat.reparentTo(render) splat.setPos(pos[0], pos[1], pos[2]) gagClass.hitSfx.play() Sequence(Wait(0.5), Func(splat.cleanup)).start() self.hitGag = None def d_makeSplat(self, index, pos): self.sendUpdate('makeSplat', [index, pos]) def b_makeSplat(self, index, pos): self.d_makeSplat(index, pos) self.makeSplat(index, pos) def handleGagCollision(self, entry, ent): x, y, z = ent.getGag().getPos(render) self.b_makeSplat(self.entities.index(ent), [x, y, z]) if self.isLocal(): intoNP = entry.getIntoNodePath() avNP = intoNP.getParent() for key in self.cr.doId2do.keys(): obj = self.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedSuit': if obj.getKey() == avNP.getKey(): if obj.getHealth() > 0: obj.sendUpdate('hitByGag', [ent.getID()]) ent.cleanup() def setHealth(self, hp): DistributedAvatar.setHealth(self, hp) if self.isLocal(): base.localAvatar.getMyBattle().getTurretManager().updateTurretGui() def die(self): self.fsm.requestFinalState() turretPos = self.cannon.getPos(render) self.removeTurret() self.explosion = loader.loadModel("phase_3.5/models/props/explosion.bam") self.explosion.setScale(0.5) self.explosion.reparentTo(render) self.explosion.setBillboardPointEye() self.explosion.setPos(turretPos + (0, 0, 5)) sfx = base.audio3d.loadSfx("phase_3.5/audio/sfx/ENC_cogfall_apart.ogg") base.audio3d.attachSoundToObject(sfx, self) base.playSfx(sfx) messenger.send(self.deathEvent) def isLocal(self): return self.getOwner() == base.localAvatar.doId def getDeathEvent(self): return self.deathEvent
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
class DistributedPartyGate(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory( "DistributedPartyGate") def __init__(self, cr): """__init__(cr) """ DistributedObject.DistributedObject.__init__(self, cr) self.publicPartyChooseGuiDoneEvent = "doneChoosingPublicParty" self.publicPartyGui = PublicPartyGui( self.publicPartyChooseGuiDoneEvent) self.publicPartyGui.stash() self.loadClockSounds() self.hourSoundInterval = Sequence() self.accept('stoppedAsleep', self.handleSleep) def loadClockSounds(self): self.clockSounds = [] for i in range(1, 13): if i < 10: si = "0%d" % i else: si = "%d" % i self.clockSounds.append( base.loader.loadSfx("phase_4/audio/sfx/clock%s.mp3" % si)) def generate(self): """generate(self) This method is called when the DistributedObject is reintroduced to the world, either for the first time or from the cache. """ DistributedObject.DistributedObject.generate(self) loader = self.cr.playGame.hood.loader partyGate = loader.geom.find('**/partyGate_grp') if partyGate.isEmpty(): self.notify.warning('Could not find partyGate_grp in loader.geom') return self.clockFlat = partyGate.find("**/clock_flat") collSphere = CollisionSphere(0, 0, 0, 6.9) collSphere.setTangible(1) self.partyGateSphere = CollisionNode("PartyGateSphere") self.partyGateSphere.addSolid(collSphere) self.partyGateCollNodePath = partyGate.find( "**/partyGate_stepsLocator").attachNewNode(self.partyGateSphere) self.__enableCollisions() # self.tunnelOrigin = NodePath("PartyGateTunnelOrigin") # self.tunnelOrigin.reparentTo(partyGate) # self.tunnelOrigin.setPos(partyGate.find("**/clockText_locator").getPos() + Point3(0.0, 0.0, -12.0)) self.toontownTimeGui = ServerTimeGui(partyGate, hourCallback=self.hourChange) self.toontownTimeGui.setPos( partyGate.find("**/clockText_locator").getPos() + Point3(0.0, 0.0, -0.2)) self.toontownTimeGui.setHpr( partyGate.find("**/clockText_locator").getHpr()) self.toontownTimeGui.setScale(12.0, 1.0, 26.0) self.toontownTimeGui.amLabel.setPos(-0.035, 0, -0.032) self.toontownTimeGui.amLabel.setScale(0.5) self.toontownTimeGui.updateTime() self.setupSignText() def setupSignText(self): """Attach text to the left and right signs""" loader = self.cr.playGame.hood.loader partyGate = loader.geom.find('**/partyGateSignGroup') if partyGate.isEmpty(): self.notify.warning('Could not find partyGate_grp in loader.geom') return gateFont = ToontownGlobals.getMinnieFont() leftSign = partyGate.find("**/signTextL_locatorBack") signScale = 0.35 wordWrap = 8 leftText = DirectLabel.DirectLabel( parent=leftSign, pos=(0, 0.0, 0.0), relief=None, text=TTLocalizer.PartyGateLeftSign, text_align=TextNode.ACenter, text_font=gateFont, text_wordwrap=wordWrap, text_fg=Vec4(0.7, 0.3, 0.3, 1.0), scale=signScale, ) rightSign = partyGate.find("**/signTextR_locatorFront") rightText = DirectLabel.DirectLabel( parent=rightSign, pos=(0, 0.0, 0.0), relief=None, text=TTLocalizer.PartyGateRightSign, text_align=TextNode.ACenter, text_font=gateFont, text_wordwrap=wordWrap, text_fg=Vec4(0.7, 0.3, 0.3, 1.0), scale=signScale, ) def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) if self.zoneId in ToontownGlobals.dnaMap: playground = ToontownGlobals.dnaMap[self.zoneId] else: playground = ToontownGlobals.dnaMap[2000] self.toontownTimeGui.hourLabel[ "text_fg"] = PartyGlobals.PlayGroundToPartyClockColors[playground] self.toontownTimeGui.colonLabel[ "text_fg"] = PartyGlobals.PlayGroundToPartyClockColors[playground] self.toontownTimeGui.minutesLabel[ "text_fg"] = PartyGlobals.PlayGroundToPartyClockColors[playground] self.toontownTimeGui.amLabel[ "text_fg"] = PartyGlobals.PlayGroundToPartyClockColors[playground] def disable(self): DistributedObject.DistributedObject.disable(self) self.__disableCollisions() self.toontownTimeGui.ival.finish() self.hourSoundInterval.finish() if self.publicPartyGui: self.publicPartyGui.stash() self.publicPartyGui.destroy() self.publicPartyGui = None def delete(self): DistributedObject.DistributedObject.delete(self) self.toontownTimeGui.destroy() del self.toontownTimeGui self.hourSoundInterval.finish() del self.hourSoundInterval del self.clockFlat if self.publicPartyGui: self.publicPartyGui.destroy() del self.publicPartyGui self.partyGateCollNodePath.removeNode() del self.partyGateCollNodePath self.ignoreAll() def showMessage(self, message): self.messageDoneEvent = self.uniqueName("messageDoneEvent") self.acceptOnce(self.messageDoneEvent, self.__handleMessageDone) self.messageGui = TTDialog.TTGlobalDialog( doneEvent=self.messageDoneEvent, message=message, style=TTDialog.Acknowledge, ) def __handleMessageDone(self): self.ignore(self.messageDoneEvent) self.freeAvatar() self.messageGui.cleanup() self.messageGui = None def __handleAskDone(self): DistributedPartyGate.notify.debug("__handleAskDone") self.ignore(self.publicPartyChooseGuiDoneEvent) doneStatus = self.publicPartyGui.doneStatus self.publicPartyGui.stash() if doneStatus is None: # They don't want to party... just let them walk away from the hat self.freeAvatar() return self.sendUpdate("partyChoiceRequest", [base.localAvatar.doId, doneStatus[0], doneStatus[1]]) def partyRequestDenied(self, reason): """ Called by the AI when the player's request to join a public party was denied. """ DistributedPartyGate.notify.debug( "partyRequestDenied( reason=%s )" % PartyGlobals.PartyGateDenialReasons.getString(reason)) # let the local toon know that they were denied # TODO-parties: tell player through gui if reason == PartyGlobals.PartyGateDenialReasons.Unavailable: self.showMessage(TTLocalizer.PartyGatePartyUnavailable) elif reason == PartyGlobals.PartyGateDenialReasons.Full: self.showMessage(TTLocalizer.PartyGatePartyFull) def setParty(self, partyInfoTuple): """ Gets called by the AI server with the approved partyId. """ DistributedPartyGate.notify.debug("setParty") self.freeAvatar() if partyInfoTuple[0] == 0: DistributedPartyGate.notify.debug( "Public Party closed before toon could get to it.") return # We now need to enter the party with the given partyId, that is, move # our toon toward the hat entrance and do the appropriate state transition shardId, zoneId, numberOfGuests, hostName, activityIds, lane = partyInfoTuple if base.localAvatar.defaultShard == shardId: shardId = None base.cr.playGame.getPlace().requestLeave({ "loader": "safeZoneLoader", "where": "party", "how": "teleportIn", "hoodId": ToontownGlobals.PartyHood, "zoneId": zoneId, "shardId": shardId, "avId": -1, # "partyHat" : True, # "tunnelOrigin" : self.tunnelOrigin, }) def freeAvatar(self): base.localAvatar.posCamera(0, 0) base.cr.playGame.getPlace().setState("walk") def hourChange(self, currentHour): currentHour = currentHour % 12 if currentHour == 0: currentHour = 12 self.hourSoundInterval = Parallel() # Make a sequence with all the clock sounds seq1 = Sequence() for i in range(currentHour): seq1.append(SoundInterval(self.clockSounds[i])) seq1.append(Wait(0.2)) # Now make a sequence that will deform the clock face timeForEachDeformation = seq1.getDuration() / currentHour seq2 = Sequence() for i in range(currentHour): seq2.append( self.clockFlat.scaleInterval(timeForEachDeformation / 2.0, Vec3(0.9, 1.0, 1.2), blendType='easeInOut')) seq2.append( self.clockFlat.scaleInterval(timeForEachDeformation / 2.0, Vec3(1.2, 1.0, 0.9), blendType='easeInOut')) seq2.append( self.clockFlat.scaleInterval(timeForEachDeformation / 2.0, Vec3(1.0, 1.0, 1.0), blendType='easeInOut')) # Now parallel the two together self.hourSoundInterval.append(seq1) self.hourSoundInterval.append(seq2) self.hourSoundInterval.start() def handleEnterGateSphere(self, collEntry): self.notify.debug("Entering steps Sphere....") # Freeze the toon, don't let him walk away... base.cr.playGame.getPlace().fsm.request('stopped') self.sendUpdate("getPartyList", [base.localAvatar.doId]) def listAllPublicParties(self, publicPartyInfo): """ Called from DistributedPartyGateAI with a tuple of all the public party information as told to it by the DistributedPartyManagerAI in order of newest party to oldest party. ( shardId, zoneId, numberOfGuests, hostName, activityIds, minLeft ) """ self.notify.debug("listAllPublicParties : publicPartyInfo = %s" % publicPartyInfo) self.acceptOnce(self.publicPartyChooseGuiDoneEvent, self.__handleAskDone) self.publicPartyGui.refresh(publicPartyInfo) self.publicPartyGui.unstash() def __enableCollisions(self): # start listening for toons to enter. self.accept('enterPartyGateSphere', self.handleEnterGateSphere) self.partyGateSphere.setCollideMask(OTPGlobals.WallBitmask) def __disableCollisions(self): # stop listening for toons. self.ignore('enterPartyGateSphere') self.partyGateSphere.setCollideMask(BitMask32(0)) def handleSleep(self): if hasattr(self, 'messageGui'): self.__handleMessageDone()
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()
class PairingGameCard(PlayingCardNodePath): DoIntervalDefault = True FlipTime = 0.25 UseDifferentCardColors = True CardColors = [(0.933594, 0.265625, 0.28125, 1.0), (0.550781, 0.824219, 0.324219, 1.0), (0.347656, 0.820312, 0.953125, 1.0), (0.460938, 0.378906, 0.824219, 1.0), (0.710938, 0.234375, 0.4375, 1.0), (0.285156, 0.328125, 0.726562, 1.0), (0.242188, 0.742188, 0.515625, 1.0), (0.96875, 0.691406, 0.699219, 1.0), (0.996094, 0.957031, 0.597656, 1.0), (0.992188, 0.480469, 0.167969, 1.0)] def __init__(self, value): style = PlayingCardGlobals.Styles[0] PlayingCardNodePath.__init__(self, style, value) self.enterCallback = None self.exitCallback = None return def load(self): oneCard = loader.loadModel( 'phase_4/models/minigames/garden_sign_memory') prop = self.attachNewNode('prop') PlayingCardGlobals.getImage(self.style, self.suit, self.rank).copyTo(prop) prop.setScale(7) oneCard.find('**/glow').removeNode() cs = oneCard.find('**/collision') for solidIndex in range(cs.node().getNumSolids()): cs.node().modifySolid(solidIndex).setTangible(False) cs.node().setName('cardCollision-%d' % self.value) sign = oneCard.find('**/sign1') if self.UseDifferentCardColors: index = self.rank % len(self.CardColors) color = self.CardColors[index] sign.setColorScale(*color) prop.setPos(0.0, 0.0, 0.08) prop.setP(-90) prop.reparentTo(oneCard) oneCard.reparentTo(self) cardBack = oneCard.find('**/sign2') cardBack.setColorScale(0.12, 0.35, 0.5, 1.0) cardModel = loader.loadModel('phase_3.5/models/gui/playingCard') logo = cardModel.find('**/logo') logo.reparentTo(self) logo.setScale(0.45) logo.setP(90) logo.setZ(0.025) logo.setX(-0.05) logo.setH(180) cardModel.removeNode() self.setR(0) self.setScale(2.5) self.flipIval = None self.turnUpSound = base.loader.loadSfx( 'phase_4/audio/sfx/MG_pairing_card_flip_face_up.ogg') self.turnDownSound = base.loader.loadSfx( 'phase_4/audio/sfx/MG_pairing_card_flip_face_down.ogg') return def unload(self): self.clearFlipIval() self.removeNode() del self.turnUpSound del self.turnDownSound def turnUp(self, doInterval=DoIntervalDefault): self.faceUp = 1 if doInterval: self.clearFlipIval() self.flipIval = Parallel( LerpHprInterval(self, self.FlipTime, Vec3(0, 0, 0)), SoundInterval(self.turnUpSound, node=self, listenerNode=base.localAvatar, cutOff=240)) self.flipIval.start() else: self.setR(0) def clearFlipIval(self): if self.flipIval: self.flipIval.finish() self.flipIval = None return def turnDown(self, doInterval=DoIntervalDefault): self.faceUp = 0 if doInterval: self.clearFlipIval() self.flipIval = Parallel( LerpHprInterval(self, self.FlipTime, Vec3(0, 0, 180)), SoundInterval(self.turnDownSound, node=self, listenerNode=base.localAvatar, cutOff=240)) self.flipIval.start() else: self.setR(180)
class IceTreasure(DirectObject): __module__ = __name__ notify = DirectNotifyGlobal.directNotify.newCategory('IceTreasure') RADIUS = 1.0 def __init__(self, model, pos, serialNum, gameId, penalty=False): self.serialNum = serialNum self.penalty = penalty center = model.getBounds().getCenter() center = Point3(0, 0, 0) self.nodePath = model.copyTo(render) self.nodePath.setPos(pos[0] - center[0], pos[1] - center[1], pos[2] - center[2]) self.nodePath.setZ(0) self.notify.debug('newPos = %s' % self.nodePath.getPos()) if self.penalty: self.sphereName = 'penaltySphere-%s-%s' % (gameId, self.serialNum) else: self.sphereName = 'treasureSphere-%s-%s' % (gameId, self.serialNum) self.collSphere = CollisionSphere(center[0], center[1], center[2], self.RADIUS) self.collSphere.setTangible(0) self.collNode = CollisionNode(self.sphereName) self.collNode.setIntoCollideMask(ToontownGlobals.PieBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = render.attachNewNode(self.collNode) self.collNodePath.setPos(pos[0] - center[0], pos[1] - center[1], pos[2] - center[2]) self.collNodePath.hide() self.track = None if self.penalty: self.tip = self.nodePath.find('**/fusetip') sparks = BattleParticles.createParticleEffect(file='icetnt') self.sparksEffect = sparks sparks.start(self.tip) self.penaltyGrabSound = loader.loadSfx( 'phase_4/audio/sfx/MG_cannon_fire_alt.mp3') self.penaltyGrabSound.setVolume(0.75) kaboomAttachPoint = self.nodePath.attachNewNode('kaboomAttach') kaboomAttachPoint.setZ(3) self.kaboom = loader.loadModel( 'phase_4/models/minigames/ice_game_kaboom') self.kaboom.reparentTo(kaboomAttachPoint) self.kaboom.setScale(2.0) self.kaboom.setBillboardPointEye() return def destroy(self): self.ignoreAll() if self.penalty: self.sparksEffect.cleanup() if self.track: self.track.finish() self.nodePath.removeNode() del self.nodePath del self.collSphere self.collNodePath.removeNode() del self.collNodePath del self.collNode def showGrab(self): self.nodePath.hide() self.collNodePath.hide() self.collNode.setIntoCollideMask(BitMask32(0)) if self.penalty: self.track = Parallel( SoundInterval(self.penaltyGrabSound), Sequence( Func(self.kaboom.showThrough), LerpScaleInterval(self.kaboom, duration=0.5, scale=Point3(10, 10, 10), blendType='easeOut'), Func(self.kaboom.hide))) self.track.start()
class DistributedBanquetTable(DistributedObject.DistributedObject, FSM.FSM, BanquetTableBase.BanquetTableBase): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedBanquetTable') rotationsPerSeatIndex = [90, 90, 0, 0, -90, -90, 180, 180] pitcherMinH = -360 pitcherMaxH = 360 rotateSpeed = 30 waterPowerSpeed = base.config.GetDouble('water-power-speed', 15) waterPowerExponent = base.config.GetDouble('water-power-exponent', 0.75) useNewAnimations = True TugOfWarControls = False OnlyUpArrow = True if OnlyUpArrow: BASELINE_KEY_RATE = 3 else: BASELINE_KEY_RATE = 6 UPDATE_KEY_PRESS_RATE_TASK = 'BanquetTableUpdateKeyPressRateTask' YELLOW_POWER_THRESHOLD = 0.75 RED_POWER_THRESHOLD = 0.97 def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) FSM.FSM.__init__(self, 'DistributedBanquetTable') self.boss = None self.index = -1 self.diners = {} self.dinerStatus = {} self.serviceLocs = {} self.chairLocators = {} self.sitLocators = {} self.activeIntervals = {} self.dinerStatusIndicators = {} self.preparedForPhaseFour = False self.avId = 0 self.toon = None self.pitcherSmoother = SmoothMover() self.pitcherSmoother.setSmoothMode(SmoothMover.SMOn) self.smoothStarted = 0 self.__broadcastPeriod = 0.2 self.changeSeq = 0 self.lastChangeSeq = 0 self.pitcherAdviceLabel = None self.fireLength = 250 self.fireTrack = None self.hitObject = None self.setupPowerBar() self.aimStart = None self.toonPitcherPosition = Point3(0, -2, 0) self.allowLocalRequestControl = True self.fadeTrack = None self.grabTrack = None self.gotHitByBoss = False self.keyTTL = [] self.keyRate = 0 self.buttons = [0, 1] self.lastPowerFired = 0 self.moveSound = None self.releaseTrack = None return def disable(self): DistributedObject.DistributedObject.disable(self) taskMgr.remove(self.triggerName) taskMgr.remove(self.smoothName) taskMgr.remove(self.watchControlsName) taskMgr.remove(self.pitcherAdviceName) taskMgr.remove(self.posHprBroadcastName) taskMgr.remove(self.waterPowerTaskName) if self.releaseTrack: self.releaseTrack.finish() self.releaseTrack = None if self.fireTrack: self.fireTrack.finish() self.fireTrack = None self.cleanupIntervals() return def delete(self): DistributedObject.DistributedObject.delete(self) self.boss = None self.ignoreAll() for indicator in self.dinerStatusIndicators.values(): indicator.delete() self.dinerStatusIndicators = {} for diner in self.diners.values(): diner.delete() self.diners = {} self.powerBar.destroy() self.powerBar = None self.pitcherMoveSfx.stop() return def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) self.loadAssets() self.smoothName = self.uniqueName('pitcherSmooth') self.pitcherAdviceName = self.uniqueName('pitcherAdvice') self.posHprBroadcastName = self.uniqueName('pitcherBroadcast') self.waterPowerTaskName = self.uniqueName('updateWaterPower') self.triggerName = self.uniqueName('trigger') self.watchControlsName = self.uniqueName('watchControls') def setBossCogId(self, bossCogId): self.bossCogId = bossCogId self.boss = base.cr.doId2do[bossCogId] self.boss.setTable(self, self.index) def setIndex(self, index): self.index = index def setState(self, state, avId, extraInfo): self.gotHitByBoss = extraInfo if state == 'F': self.demand('Off') elif state == 'N': self.demand('On') elif state == 'I': self.demand('Inactive') elif state == 'R': self.demand('Free') elif state == 'C': self.demand('Controlled', avId) elif state == 'L': self.demand('Flat', avId) else: self.notify.error('Invalid state from AI: %s' % state) def setNumDiners(self, numDiners): self.numDiners = numDiners def setDinerInfo(self, hungryDurations, eatingDurations, dinerLevels): self.dinerInfo = {} for i in xrange(len(hungryDurations)): hungryDur = hungryDurations[i] eatingDur = eatingDurations[i] dinerLevel = dinerLevels[i] self.dinerInfo[i] = (hungryDur, eatingDur, dinerLevel) def loadAssets(self): self.tableGroup = loader.loadModel( 'phase_12/models/bossbotHQ/BanquetTableChairs') tableLocator = self.boss.geom.find('**/TableLocator_%d' % (self.index + 1)) if tableLocator.isEmpty(): self.tableGroup.reparentTo(render) self.tableGroup.setPos(0, 75, 0) else: self.tableGroup.reparentTo(tableLocator) self.tableGeom = self.tableGroup.find('**/Geometry') self.setupDiners() self.setupChairCols() self.squirtSfx = loader.loadSfx( 'phase_4/audio/sfx/AA_squirt_seltzer_miss.ogg') self.hitBossSfx = loader.loadSfx( 'phase_5/audio/sfx/SA_watercooler_spray_only.ogg') self.hitBossSoundInterval = SoundInterval(self.hitBossSfx, node=self.boss, volume=1.0) self.serveFoodSfx = loader.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_bell_for_trolley.ogg') self.pitcherMoveSfx = base.loader.loadSfx( 'phase_4/audio/sfx/MG_cannon_adjust.ogg') def setupDiners(self): for i in xrange(self.numDiners): newDiner = self.createDiner(i) self.diners[i] = newDiner self.dinerStatus[i] = self.HUNGRY def createDiner(self, i): diner = Suit.Suit() diner.dna = SuitDNA.SuitDNA() level = self.dinerInfo[i][2] level -= 4 diner.dna.newSuitRandom(level=level, dept='c') diner.setDNA(diner.dna) diner.nametag3d.stash() diner.nametag.destroy() if self.useNewAnimations: diner.loop('sit', fromFrame=i) else: diner.pose('landing', 0) locator = self.tableGroup.find('**/chair_%d' % (i + 1)) locatorScale = locator.getNetTransform().getScale()[0] correctHeadingNp = locator.attachNewNode('correctHeading') self.chairLocators[i] = correctHeadingNp heading = self.rotationsPerSeatIndex[i] correctHeadingNp.setH(heading) sitLocator = correctHeadingNp.attachNewNode('sitLocator') base.sitLocator = sitLocator pos = correctHeadingNp.getPos(render) if SuitDNA.getSuitBodyType(diner.dna.name) == 'c': sitLocator.setPos(0.5, 3.65, -3.75) else: sitLocator.setZ(-2.4) sitLocator.setY(2.5) sitLocator.setX(0.5) self.sitLocators[i] = sitLocator diner.setScale(1.0 / locatorScale) diner.reparentTo(sitLocator) newLoc = NodePath('serviceLoc-%d-%d' % (self.index, i)) newLoc.reparentTo(correctHeadingNp) newLoc.setPos(0, 3.0, 1) self.serviceLocs[i] = newLoc base.serviceLoc = newLoc head = diner.find('**/joint_head') newIndicator = DinerStatusIndicator.DinerStatusIndicator(parent=head, pos=Point3( 0, 0, 3.5), scale=5.0) newIndicator.wrtReparentTo(diner) self.dinerStatusIndicators[i] = newIndicator return diner def setupChairCols(self): for i in xrange(self.numDiners): chairCol = self.tableGroup.find('**/collision_chair_%d' % (i + 1)) colName = 'ChairCol-%d-%d' % (self.index, i) chairCol.setTag('chairIndex', str(i)) chairCol.setName(colName) chairCol.setCollideMask(ToontownGlobals.WallBitmask) self.accept('enter' + colName, self.touchedChair) def touchedChair(self, colEntry): chairIndex = int(colEntry.getIntoNodePath().getTag('chairIndex')) if chairIndex in self.dinerStatus: status = self.dinerStatus[chairIndex] if status in (self.HUNGRY, self.ANGRY): self.boss.localToonTouchedChair(self.index, chairIndex) def serveFood(self, food, chairIndex): self.removeFoodModel(chairIndex) serviceLoc = self.serviceLocs.get(chairIndex) if not food or food.isEmpty(): foodModel = loader.loadModel('phase_12/models/bossbotHQ/canoffood') foodModel.setScale(ToontownGlobals.BossbotFoodModelScale) foodModel.reparentTo(serviceLoc) else: food.wrtReparentTo(serviceLoc) tray = food.find('**/tray') if not tray.isEmpty(): tray.hide() ivalDuration = 1.5 foodMoveIval = Parallel( SoundInterval(self.serveFoodSfx, node=food), ProjectileInterval(food, duration=ivalDuration, startPos=food.getPos(serviceLoc), endPos=serviceLoc.getPos(serviceLoc)), LerpHprInterval(food, ivalDuration, Point3(0, -360, 0))) intervalName = 'serveFood-%d-%d' % (self.index, chairIndex) foodMoveIval.start() self.activeIntervals[intervalName] = foodMoveIval def setDinerStatus(self, chairIndex, status): if chairIndex in self.dinerStatus: oldStatus = self.dinerStatus[chairIndex] self.dinerStatus[chairIndex] = status if oldStatus != status: if status == self.EATING: self.changeDinerToEating(chairIndex) elif status == self.HUNGRY: self.changeDinerToHungry(chairIndex) elif status == self.ANGRY: self.changeDinerToAngry(chairIndex) elif status == self.DEAD: self.changeDinerToDead(chairIndex) elif status == self.HIDDEN: self.changeDinerToHidden(chairIndex) def removeFoodModel(self, chairIndex): serviceLoc = self.serviceLocs.get(chairIndex) if serviceLoc: for i in xrange(serviceLoc.getNumChildren()): serviceLoc.getChild(0).removeNode() def changeDinerToEating(self, chairIndex): indicator = self.dinerStatusIndicators.get(chairIndex) eatingDuration = self.dinerInfo[chairIndex][1] if indicator: indicator.request('Eating', eatingDuration) diner = self.diners[chairIndex] intervalName = 'eating-%d-%d' % (self.index, chairIndex) eatInTime = 32.0 / 24.0 eatOutTime = 21.0 / 24.0 eatLoopTime = 19 / 24.0 rightHand = diner.getRightHand() waitTime = 5 loopDuration = eatingDuration - eatInTime - eatOutTime - waitTime serviceLoc = self.serviceLocs[chairIndex] def foodAttach(self=self, diner=diner): if self.serviceLocs[chairIndex].getNumChildren() < 1: return foodModel = self.serviceLocs[chairIndex].getChild(0) (foodModel.reparentTo(diner.getRightHand()), ) (foodModel.setHpr(Point3(0, -94, 0)), ) (foodModel.setPos(Point3(-0.15, -0.7, -0.4)), ) scaleAdj = 1 if SuitDNA.getSuitBodyType(diner.dna.name) == 'c': scaleAdj = 0.6 (foodModel.setPos(Point3(0.1, -0.25, -0.31)), ) else: scaleAdj = 0.8 (foodModel.setPos(Point3(-0.25, -0.85, -0.34)), ) oldScale = foodModel.getScale() newScale = oldScale * scaleAdj foodModel.setScale(newScale) def foodDetach(self=self, diner=diner): if diner.getRightHand().getNumChildren() < 1: return foodModel = diner.getRightHand().getChild(0) (foodModel.reparentTo(serviceLoc), ) (foodModel.setPosHpr(0, 0, 0, 0, 0, 0), ) scaleAdj = 1 if SuitDNA.getSuitBodyType(diner.dna.name) == 'c': scaleAdj = 0.6 else: scakeAdj = 0.8 oldScale = foodModel.getScale() newScale = oldScale / scaleAdj foodModel.setScale(newScale) eatIval = Sequence( ActorInterval(diner, 'sit', duration=waitTime), ActorInterval(diner, 'sit-eat-in', startFrame=0, endFrame=6), Func(foodAttach), ActorInterval(diner, 'sit-eat-in', startFrame=6, endFrame=32), ActorInterval(diner, 'sit-eat-loop', duration=loopDuration, loop=1), ActorInterval(diner, 'sit-eat-out', startFrame=0, endFrame=12), Func(foodDetach), ActorInterval(diner, 'sit-eat-out', startFrame=12, endFrame=21)) eatIval.start() self.activeIntervals[intervalName] = eatIval def changeDinerToHungry(self, chairIndex): intervalName = 'eating-%d-%d' % (self.index, chairIndex) if intervalName in self.activeIntervals: self.activeIntervals[intervalName].finish() self.removeFoodModel(chairIndex) indicator = self.dinerStatusIndicators.get(chairIndex) if indicator: indicator.request('Hungry', self.dinerInfo[chairIndex][0]) diner = self.diners[chairIndex] if random.choice([0, 1]): diner.loop('sit-hungry-left') else: diner.loop('sit-hungry-right') def changeDinerToAngry(self, chairIndex): self.removeFoodModel(chairIndex) indicator = self.dinerStatusIndicators.get(chairIndex) if indicator: indicator.request('Angry') diner = self.diners[chairIndex] diner.loop('sit-angry') def changeDinerToDead(self, chairIndex): def removeDeathSuit(suit, deathSuit): if not deathSuit.isEmpty(): deathSuit.detachNode() suit.cleanupLoseActor() self.removeFoodModel(chairIndex) indicator = self.dinerStatusIndicators.get(chairIndex) if indicator: indicator.request('Dead') diner = self.diners[chairIndex] deathSuit = diner locator = self.tableGroup.find('**/chair_%d' % (chairIndex + 1)) deathSuit = diner.getLoseActor() ival = Sequence( Func(self.notify.debug, 'before actorinterval sit-lose'), ActorInterval(diner, 'sit-lose'), Func(self.notify.debug, 'before deathSuit.setHpr'), Func(deathSuit.setHpr, diner.getHpr()), Func(self.notify.debug, 'before diner.hide'), Func(diner.hide), Func(self.notify.debug, 'before deathSuit.reparentTo'), Func(deathSuit.reparentTo, self.chairLocators[chairIndex]), Func(self.notify.debug, 'befor ActorInterval lose'), ActorInterval(deathSuit, 'lose', duration=MovieUtil.SUIT_LOSE_DURATION), Func(self.notify.debug, 'before remove deathsuit'), Func(removeDeathSuit, diner, deathSuit, name='remove-death-suit-%d-%d' % (chairIndex, self.index)), Func(self.notify.debug, 'diner.stash'), Func(diner.stash)) spinningSound = base.loader.loadSfx( 'phase_3.5/audio/sfx/Cog_Death.ogg') deathSound = base.loader.loadSfx( 'phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) deathSoundTrack = Sequence( Wait(0.8), SoundInterval(spinningSound, duration=1.2, startTime=1.5, volume=0.2, node=deathSuit), SoundInterval(spinningSound, duration=3.0, startTime=0.6, volume=0.8, node=deathSuit), SoundInterval(deathSound, volume=0.32, node=deathSuit)) intervalName = 'dinerDie-%d-%d' % (self.index, chairIndex) deathIval = Parallel(ival, deathSoundTrack) deathIval.start() self.activeIntervals[intervalName] = deathIval def changeDinerToHidden(self, chairIndex): self.removeFoodModel(chairIndex) indicator = self.dinerStatusIndicators.get(chairIndex) if indicator: indicator.request('Inactive') diner = self.diners[chairIndex] diner.hide() def setAllDinersToSitNeutral(self): startFrame = 0 for diner in self.diners.values(): if not diner.isHidden(): diner.loop('sit', fromFrame=startFrame) startFrame += 1 def cleanupIntervals(self): for interval in self.activeIntervals.values(): interval.finish() self.activeIntervals = {} def clearInterval(self, name, finish=1): if name in self.activeIntervals: ival = self.activeIntervals[name] if finish: ival.finish() else: ival.pause() if name in self.activeIntervals: del self.activeIntervals[name] else: self.notify.debug('interval: %s already cleared' % name) def finishInterval(self, name): if name in self.activeIntervals: interval = self.activeIntervals[name] interval.finish() def getNotDeadInfo(self): notDeadList = [] for i in xrange(self.numDiners): if self.dinerStatus[i] != self.DEAD: notDeadList.append((self.index, i, 12)) return notDeadList def enterOn(self): pass def exitOn(self): pass def enterInactive(self): for chairIndex in xrange(self.numDiners): indicator = self.dinerStatusIndicators.get(chairIndex) if indicator: indicator.request('Inactive') self.removeFoodModel(chairIndex) def exitInactive(self): pass def enterFree(self): self.resetPowerBar() if self.fadeTrack: self.fadeTrack.finish() self.fadeTrack = None self.prepareForPhaseFour() if self.avId == localAvatar.doId: self.tableGroup.setAlphaScale(0.3) self.tableGroup.setTransparency(1) taskMgr.doMethodLater(5, self.__allowDetect, self.triggerName) self.fadeTrack = Sequence( Func(self.tableGroup.setTransparency, 1), self.tableGroup.colorScaleInterval(0.2, VBase4(1, 1, 1, 0.3))) self.fadeTrack.start() self.allowLocalRequestControl = False else: self.allowLocalRequestControl = True self.avId = 0 return def exitFree(self): pass def touchedTable(self, colEntry): tableIndex = int(colEntry.getIntoNodePath().getTag('tableIndex')) if self.state == 'Free' and self.avId == 0 and self.allowLocalRequestControl: self.d_requestControl() def prepareForPhaseFour(self): if not self.preparedForPhaseFour: for i in xrange(8): chair = self.tableGroup.find('**/chair_%d' % (i + 1)) if not chair.isEmpty(): chair.hide() colChairs = self.tableGroup.findAllMatches('**/ChairCol*') for i in xrange(colChairs.getNumPaths()): col = colChairs.getPath(i) col.stash() colChairs = self.tableGroup.findAllMatches( '**/collision_chair*') for i in xrange(colChairs.getNumPaths()): col = colChairs.getPath(i) col.stash() tableCol = self.tableGroup.find('**/collision_table') colName = 'TableCol-%d' % self.index tableCol.setTag('tableIndex', str(self.index)) tableCol.setName(colName) tableCol.setCollideMask(ToontownGlobals.WallBitmask | ToontownGlobals.BanquetTableBitmask) self.accept('enter' + colName, self.touchedTable) self.preparedForPhaseFour = True self.waterPitcherModel = loader.loadModel( 'phase_12/models/bossbotHQ/tt_m_ara_bhq_seltzerBottle') lampNode = self.tableGroup.find('**/lamp_med_5') pos = lampNode.getPos(self.tableGroup) lampNode.hide() bottleLocator = self.tableGroup.find('**/bottle_locator') pos = bottleLocator.getPos(self.tableGroup) self.waterPitcherNode = self.tableGroup.attachNewNode( 'pitcherNode') self.waterPitcherNode.setPos(pos) self.waterPitcherModel.reparentTo(self.waterPitcherNode) self.nozzle = self.waterPitcherModel.find('**/nozzle_tip') self.handLocator = self.waterPitcherModel.find('**/hand_locator') self.handPos = self.handLocator.getPos() def d_requestControl(self): self.sendUpdate('requestControl') def d_requestFree(self, gotHitByBoss): self.sendUpdate('requestFree', [gotHitByBoss]) def enterControlled(self, avId): self.prepareForPhaseFour() self.avId = avId toon = base.cr.doId2do.get(avId) if not toon: return self.toon = toon self.grabTrack = self.makeToonGrabInterval(toon) self.notify.debug('grabTrack=%s' % self.grabTrack) self.pitcherCamPos = Point3(0, -50, 40) self.pitcherCamHpr = Point3(0, -21, 0) if avId == localAvatar.doId: self.boss.toMovieMode() self.__enableControlInterface() self.startPosHprBroadcast() self.grabTrack = Sequence( self.grabTrack, Func(camera.wrtReparentTo, localAvatar), LerpPosHprInterval(camera, 1, self.pitcherCamPos, self.pitcherCamHpr), Func(self.boss.toCraneMode)) if self.TugOfWarControls: self.__spawnUpdateKeyPressRateTask() self.accept('exitCrane', self.gotBossZapped) else: self.startSmooth() toon.stopSmooth() self.grabTrack.start() def exitControlled(self): self.ignore('exitCrane') if self.grabTrack: self.grabTrack.finish() self.grabTrack = None nextState = self.getCurrentOrNextState() self.notify.debug('nextState=%s' % nextState) if nextState == 'Flat': place = base.cr.playGame.getPlace() self.notify.debug('%s' % place.fsm) if self.avId == localAvatar.doId: self.__disableControlInterface() else: if self.toon and not self.toon.isDisabled(): self.toon.loop('neutral') self.toon.startSmooth() self.releaseTrack = self.makeToonReleaseInterval(self.toon) self.stopPosHprBroadcast() self.stopSmooth() if self.avId == localAvatar.doId: localAvatar.wrtReparentTo(render) self.__disableControlInterface() camera.reparentTo(base.localAvatar) camera.setPos(base.localAvatar.cameraPositions[0][0]) camera.setHpr(0, 0, 0) self.goToFinalBattle() self.safeBossToFinalBattleMode() else: toon = base.cr.doId2do.get(self.avId) if toon: toon.wrtReparentTo(render) self.releaseTrack.start() return def safeBossToFinalBattleMode(self): if self.boss: self.boss.toFinalBattleMode() def goToFinalBattle(self): if self.cr: place = self.cr.playGame.getPlace() if place and hasattr(place, 'fsm'): if place.fsm.getCurrentState().getName() == 'crane': place.setState('finalBattle') def makeToonGrabInterval(self, toon): toon.pose('leverNeutral', 0) toon.update() rightHandPos = toon.rightHand.getPos(toon) self.toonPitcherPosition = Point3(self.handPos[0] - rightHandPos[0], self.handPos[1] - rightHandPos[1], 0) destZScale = rightHandPos[2] / self.handPos[2] grabIval = Sequence( Func(toon.wrtReparentTo, self.waterPitcherNode), Func(toon.loop, 'neutral'), Parallel( ActorInterval(toon, 'jump'), Sequence( Wait(0.43), Parallel( ProjectileInterval(toon, duration=0.9, startPos=toon.getPos( self.waterPitcherNode), endPos=self.toonPitcherPosition), LerpHprInterval(toon, 0.9, Point3(0, 0, 0)), LerpScaleInterval(self.waterPitcherModel, 0.9, Point3(1, 1, destZScale))))), Func(toon.setPos, self.toonPitcherPosition), Func(toon.loop, 'leverNeutral')) return grabIval def makeToonReleaseInterval(self, toon): temp1 = self.waterPitcherNode.attachNewNode('temp1') temp1.setPos(self.toonPitcherPosition) temp2 = self.waterPitcherNode.attachNewNode('temp2') temp2.setPos(0, -10, -self.waterPitcherNode.getZ()) startPos = temp1.getPos(render) endPos = temp2.getPos(render) temp1.removeNode() temp2.removeNode() def getSlideToPos(toon=toon): return render.getRelativePoint(toon, Point3(0, -10, 0)) if self.gotHitByBoss: self.notify.debug('creating zap interval instead') grabIval = Sequence( Func(toon.loop, 'neutral'), Func(toon.wrtReparentTo, render), Parallel(ActorInterval(toon, 'slip-backward'), toon.posInterval(0.5, getSlideToPos, fluid=1))) else: grabIval = Sequence( Func(toon.loop, 'neutral'), Func(toon.wrtReparentTo, render), Parallel( ActorInterval(toon, 'jump'), Sequence( Wait(0.43), ProjectileInterval(toon, duration=0.9, startPos=startPos, endPos=endPos)))) return grabIval def b_clearSmoothing(self): self.d_clearSmoothing() self.clearSmoothing() def d_clearSmoothing(self): self.sendUpdate('clearSmoothing', [0]) def clearSmoothing(self, bogus=None): self.pitcherSmoother.clearPositions(1) def doSmoothTask(self, task): self.pitcherSmoother.computeAndApplySmoothHpr(self.waterPitcherNode) return Task.cont def startSmooth(self): if not self.smoothStarted: taskName = self.smoothName taskMgr.remove(taskName) self.reloadPosition() taskMgr.add(self.doSmoothTask, taskName) self.smoothStarted = 1 def stopSmooth(self): if self.smoothStarted: taskName = self.smoothName taskMgr.remove(taskName) self.forceToTruePosition() self.smoothStarted = 0 def __enableControlInterface(self): gui = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui') self.closeButton = DirectButton(image=(gui.find('**/CloseBtn_UP'), gui.find('**/CloseBtn_DN'), gui.find('**/CloseBtn_Rllvr'), gui.find('**/CloseBtn_UP')), relief=None, scale=2, text=TTLocalizer.BossbotPitcherLeave, text_scale=0.04, text_pos=(0, -0.07), text_fg=VBase4(1, 1, 1, 1), pos=(1.05, 0, -0.82), command=self.__exitPitcher) self.accept('escape', self.__exitPitcher) self.accept('control', self.__controlPressed) self.accept('control-up', self.__controlReleased) self.accept('InputState-forward', self.__upArrow) self.accept('InputState-reverse', self.__downArrow) self.accept('InputState-turnLeft', self.__leftArrow) self.accept('InputState-turnRight', self.__rightArrow) self.accept('arrow_up', self.__upArrowKeyPressed) self.accept('arrow_down', self.__downArrowKeyPressed) taskMgr.add(self.__watchControls, self.watchControlsName) taskMgr.doMethodLater(5, self.__displayPitcherAdvice, self.pitcherAdviceName) self.arrowVert = 0 self.arrowHorz = 0 self.powerBar.show() return def __disableControlInterface(self): if self.closeButton: self.closeButton.destroy() self.closeButton = None self.__cleanupPitcherAdvice() self.ignore('escape') self.ignore('control') self.ignore('control-up') self.ignore('InputState-forward') self.ignore('InputState-reverse') self.ignore('InputState-turnLeft') self.ignore('InputState-turnRight') self.ignore('arrow_up') self.ignore('arrow_down') self.arrowVert = 0 self.arrowHorz = 0 taskMgr.remove(self.watchControlsName) taskMgr.remove(self.waterPowerTaskName) self.resetPowerBar() self.aimStart = None self.powerBar.hide() if self.TugOfWarControls: self.__killUpdateKeyPressRateTask() self.keyTTL = [] self.__setMoveSound(None) return def __displayPitcherAdvice(self, task): if self.pitcherAdviceLabel == None: self.pitcherAdviceLabel = DirectLabel( text=TTLocalizer.BossbotPitcherAdvice, text_fg=VBase4(1, 1, 1, 1), text_align=TextNode.ACenter, relief=None, pos=(0, 0, 0.69), scale=0.1) return def __cleanupPitcherAdvice(self): if self.pitcherAdviceLabel: self.pitcherAdviceLabel.destroy() self.pitcherAdviceLabel = None taskMgr.remove(self.pitcherAdviceName) return def showExiting(self): if self.closeButton: self.closeButton.destroy() self.closeButton = DirectLabel( relief=None, text=TTLocalizer.BossbotPitcherLeaving, pos=(1.05, 0, -0.88), text_pos=(0, 0), text_scale=0.06, text_fg=VBase4(1, 1, 1, 1)) self.__cleanupPitcherAdvice() return def __exitPitcher(self): self.showExiting() self.d_requestFree(False) def __controlPressed(self): self.__cleanupPitcherAdvice() if self.TugOfWarControls: if self.power: self.aimStart = 1 self.__endFireWater() elif self.state == 'Controlled': self.__beginFireWater() def __controlReleased(self): if self.TugOfWarControls: pass elif self.state == 'Controlled': self.__endFireWater() def __upArrow(self, pressed): self.__incrementChangeSeq() self.__cleanupPitcherAdvice() if pressed: self.arrowVert = 1 elif self.arrowVert > 0: self.arrowVert = 0 def __downArrow(self, pressed): self.__incrementChangeSeq() self.__cleanupPitcherAdvice() if pressed: self.arrowVert = -1 elif self.arrowVert < 0: self.arrowVert = 0 def __rightArrow(self, pressed): self.__incrementChangeSeq() self.__cleanupPitcherAdvice() if pressed: self.arrowHorz = 1 elif self.arrowHorz > 0: self.arrowHorz = 0 def __leftArrow(self, pressed): self.__incrementChangeSeq() self.__cleanupPitcherAdvice() if pressed: self.arrowHorz = -1 elif self.arrowHorz < 0: self.arrowHorz = 0 def __incrementChangeSeq(self): self.changeSeq = self.changeSeq + 1 & 255 def stopPosHprBroadcast(self): taskName = self.posHprBroadcastName taskMgr.remove(taskName) def startPosHprBroadcast(self): taskName = self.posHprBroadcastName self.b_clearSmoothing() self.d_sendPitcherPos() taskMgr.remove(taskName) taskMgr.doMethodLater(self.__broadcastPeriod, self.__posHprBroadcast, taskName) def __posHprBroadcast(self, task): self.d_sendPitcherPos() taskName = self.posHprBroadcastName taskMgr.doMethodLater(self.__broadcastPeriod, self.__posHprBroadcast, taskName) return Task.done def d_sendPitcherPos(self): timestamp = globalClockDelta.getFrameNetworkTime() self.sendUpdate( 'setPitcherPos', [self.changeSeq, self.waterPitcherNode.getH(), timestamp]) def setPitcherPos(self, changeSeq, h, timestamp): self.changeSeq = changeSeq if self.smoothStarted: now = globalClock.getFrameTime() local = globalClockDelta.networkToLocalTime(timestamp, now) self.pitcherSmoother.setH(h) self.pitcherSmoother.setTimestamp(local) self.pitcherSmoother.markPosition() else: self.waterPitcherNode.setH(h) def __watchControls(self, task): if self.arrowHorz: self.__movePitcher(self.arrowHorz) else: self.__setMoveSound(None) return Task.cont def __movePitcher(self, xd): dt = globalClock.getDt() h = self.waterPitcherNode.getH() - xd * self.rotateSpeed * dt h %= 360 self.notify.debug( 'rotSpeed=%.2f curH=%.2f xd =%.2f, dt = %.2f, h=%.2f' % (self.rotateSpeed, self.waterPitcherNode.getH(), xd, dt, h)) limitH = h self.waterPitcherNode.setH(limitH) if xd: self.__setMoveSound(self.pitcherMoveSfx) def reloadPosition(self): self.pitcherSmoother.clearPositions(0) self.pitcherSmoother.setHpr(self.waterPitcherNode.getHpr()) self.pitcherSmoother.setPhonyTimestamp() def forceToTruePosition(self): if self.pitcherSmoother.getLatestPosition(): self.pitcherSmoother.applySmoothHpr(self.waterPitcherNode) self.pitcherSmoother.clearPositions(1) def getSprayTrack(self, color, origin, target, dScaleUp, dHold, dScaleDown, horizScale=1.0, vertScale=1.0, parent=render): track = Sequence() SPRAY_LEN = 1.5 sprayProp = MovieUtil.globalPropPool.getProp('spray') sprayScale = hidden.attachNewNode('spray-parent') sprayRot = hidden.attachNewNode('spray-rotate') spray = sprayRot spray.setColor(color) if color[3] < 1.0: spray.setTransparency(1) def showSpray(sprayScale, sprayRot, sprayProp, origin, target, parent): if callable(origin): origin = origin() if callable(target): target = target() sprayRot.reparentTo(parent) sprayRot.clearMat() sprayScale.reparentTo(sprayRot) sprayScale.clearMat() sprayProp.reparentTo(sprayScale) sprayProp.clearMat() sprayRot.setPos(origin) sprayRot.lookAt(Point3(target)) track.append( Func(showSpray, sprayScale, sprayRot, sprayProp, origin, target, parent)) def calcTargetScale(target=target, origin=origin, horizScale=horizScale, vertScale=vertScale): if callable(target): target = target() if callable(origin): origin = origin() distance = Vec3(target - origin).length() yScale = distance / SPRAY_LEN targetScale = Point3(yScale * horizScale, yScale, yScale * vertScale) return targetScale track.append( LerpScaleInterval(sprayScale, dScaleUp, calcTargetScale, startScale=Point3(0.01, 0.01, 0.01))) track.append(Func(self.checkHitObject)) track.append(Wait(dHold)) def prepareToShrinkSpray(spray, sprayProp, origin, target): if callable(target): target = target() if callable(origin): origin = origin() sprayProp.setPos(Point3(0.0, -SPRAY_LEN, 0.0)) spray.setPos(target) track.append( Func(prepareToShrinkSpray, spray, sprayProp, origin, target)) track.append( LerpScaleInterval(sprayScale, dScaleDown, Point3(0.01, 0.01, 0.01))) def hideSpray(spray, sprayScale, sprayRot, sprayProp, propPool): sprayProp.detachNode() MovieUtil.removeProp(sprayProp) sprayRot.removeNode() sprayScale.removeNode() track.append( Func(hideSpray, spray, sprayScale, sprayRot, sprayProp, MovieUtil.globalPropPool)) return track def checkHitObject(self): if not self.hitObject: return if self.avId != base.localAvatar.doId: return tag = self.hitObject.getNetTag('pieCode') pieCode = int(tag) if pieCode == ToontownGlobals.PieCodeBossCog: self.hitBossSoundInterval.start() self.sendUpdate('waterHitBoss', [self.index]) if self.TugOfWarControls: damage = 1 if self.lastPowerFired < self.YELLOW_POWER_THRESHOLD: damage = 1 elif self.lastPowerFired < self.RED_POWER_THRESHOLD: damage = 2 else: damage = 3 self.boss.d_hitBoss(damage) else: damage = 1 if self.lastPowerFired < self.YELLOW_POWER_THRESHOLD: damage = 1 elif self.lastPowerFired < self.RED_POWER_THRESHOLD: damage = 2 else: damage = 3 self.boss.d_hitBoss(damage) def waterHitBoss(self, tableIndex): if self.index == tableIndex: self.hitBossSoundInterval.start() def setupPowerBar(self): self.powerBar = DirectWaitBar(pos=(0.0, 0, -0.94), relief=DGG.SUNKEN, frameSize=(-2.0, 2.0, -0.2, 0.2), borderWidth=(0.02, 0.02), scale=0.25, range=1, sortOrder=50, frameColor=(0.5, 0.5, 0.5, 0.5), barColor=(0.75, 0.75, 1.0, 0.8), text='', text_scale=0.26, text_fg=(1, 1, 1, 1), text_align=TextNode.ACenter, text_pos=(0, -0.05)) self.power = 0 self.powerBar['value'] = self.power self.powerBar.hide() def resetPowerBar(self): self.power = 0 self.powerBar['value'] = self.power self.powerBar['text'] = '' self.keyTTL = [] def __beginFireWater(self): if self.fireTrack and self.fireTrack.isPlaying(): return if self.aimStart != None: return if not self.state == 'Controlled': return if not self.avId == localAvatar.doId: return time = globalClock.getFrameTime() self.aimStart = time messenger.send('wakeup') taskMgr.add(self.__updateWaterPower, self.waterPowerTaskName) return def __endFireWater(self): if self.aimStart == None: return if not self.state == 'Controlled': return if not self.avId == localAvatar.doId: return taskMgr.remove(self.waterPowerTaskName) messenger.send('wakeup') self.aimStart = None origin = self.nozzle.getPos(render) target = self.boss.getPos(render) angle = deg2Rad(self.waterPitcherNode.getH() + 90) x = math.cos(angle) y = math.sin(angle) fireVector = Point3(x, y, 0) if self.power < 0.001: self.power = 0.001 self.lastPowerFired = self.power fireVector *= self.fireLength * self.power target = origin + fireVector segment = CollisionSegment(origin[0], origin[1], origin[2], target[0], target[1], target[2]) fromObject = render.attachNewNode(CollisionNode('pitcherColNode')) fromObject.node().addSolid(segment) fromObject.node().setFromCollideMask(ToontownGlobals.PieBitmask | ToontownGlobals.CameraBitmask | ToontownGlobals.FloorBitmask) fromObject.node().setIntoCollideMask(BitMask32.allOff()) queue = CollisionHandlerQueue() base.cTrav.addCollider(fromObject, queue) base.cTrav.traverse(render) queue.sortEntries() self.hitObject = None if queue.getNumEntries(): entry = queue.getEntry(0) target = entry.getSurfacePoint(render) self.hitObject = entry.getIntoNodePath() base.cTrav.removeCollider(fromObject) fromObject.removeNode() self.d_firingWater(origin, target) self.fireWater(origin, target) self.resetPowerBar() return def __updateWaterPower(self, task): if not self.powerBar: print '### no power bar!!!' return task.done newPower = self.__getWaterPower(globalClock.getFrameTime()) self.power = newPower self.powerBar['value'] = newPower if self.power < self.YELLOW_POWER_THRESHOLD: self.powerBar['barColor'] = VBase4(0.75, 0.75, 1.0, 0.8) elif self.power < self.RED_POWER_THRESHOLD: self.powerBar['barColor'] = VBase4(1.0, 1.0, 0.0, 0.8) else: self.powerBar['barColor'] = VBase4(1.0, 0.0, 0.0, 0.8) return task.cont def __getWaterPower(self, time): elapsed = max(time - self.aimStart, 0.0) t = elapsed / self.waterPowerSpeed exponent = self.waterPowerExponent if t > 1: t = t % 1 power = 1 - math.pow(1 - t, exponent) if power > 1.0: power = 1.0 return power def d_firingWater(self, origin, target): self.sendUpdate( 'firingWater', [origin[0], origin[1], origin[2], target[0], target[1], target[2]]) def firingWater(self, startX, startY, startZ, endX, endY, endZ): origin = Point3(startX, startY, startZ) target = Point3(endX, endY, endZ) self.fireWater(origin, target) def fireWater(self, origin, target): color = VBase4(0.75, 0.75, 1, 0.8) dScaleUp = 0.1 dHold = 0.3 dScaleDown = 0.1 horizScale = 0.1 vertScale = 0.1 sprayTrack = self.getSprayTrack(color, origin, target, dScaleUp, dHold, dScaleDown, horizScale, vertScale) duration = self.squirtSfx.length() if sprayTrack.getDuration() < duration: duration = sprayTrack.getDuration() soundTrack = SoundInterval(self.squirtSfx, node=self.waterPitcherModel, duration=duration) self.fireTrack = Parallel(sprayTrack, soundTrack) self.fireTrack.start() def getPos(self, wrt=render): return self.tableGroup.getPos(wrt) def getLocator(self): return self.tableGroup def enterFlat(self, avId): self.prepareForPhaseFour() self.resetPowerBar() self.notify.debug('enterFlat %d' % self.index) if self.avId: toon = base.cr.doId2do.get(self.avId) if toon: toon.wrtReparentTo(render) toon.setZ(0) self.tableGroup.setScale(1, 1, 0.01) if self.avId and self.avId == localAvatar.doId: localAvatar.b_squish(ToontownGlobals.BossCogDamageLevels[ ToontownGlobals.BossCogMoveAttack]) def exitFlat(self): self.tableGroup.setScale(1.0) if self.avId: toon = base.cr.doId2do.get(self.avId) if toon: if toon == localAvatar: self.boss.toCraneMode() toon.b_setAnimState('neutral') toon.setAnimState('neutral') toon.loop('leverNeutral') def __allowDetect(self, task): if self.fadeTrack: self.fadeTrack.finish() self.fadeTrack = Sequence( self.tableGroup.colorScaleInterval(0.2, VBase4(1, 1, 1, 1)), Func(self.tableGroup.clearColorScale), Func(self.tableGroup.clearTransparency)) self.fadeTrack.start() self.allowLocalRequestControl = True def gotBossZapped(self): self.showExiting() self.d_requestFree(True) def __upArrowKeyPressed(self): if self.TugOfWarControls: self.__pressHandler(0) def __downArrowKeyPressed(self): if self.TugOfWarControls: self.__pressHandler(1) def __pressHandler(self, index): if index == self.buttons[0]: self.keyTTL.insert(0, 1.0) if not self.OnlyUpArrow: self.buttons.reverse() def __spawnUpdateKeyPressRateTask(self): taskMgr.remove(self.taskName(self.UPDATE_KEY_PRESS_RATE_TASK)) taskMgr.doMethodLater(0.1, self.__updateKeyPressRateTask, self.taskName(self.UPDATE_KEY_PRESS_RATE_TASK)) def __killUpdateKeyPressRateTask(self): taskMgr.remove(self.taskName(self.UPDATE_KEY_PRESS_RATE_TASK)) def __updateKeyPressRateTask(self, task): if self.state not in 'Controlled': return Task.done for i in xrange(len(self.keyTTL)): self.keyTTL[i] -= 0.1 for i in xrange(len(self.keyTTL)): if self.keyTTL[i] <= 0: a = self.keyTTL[0:i] del self.keyTTL self.keyTTL = a break self.keyRate = len(self.keyTTL) keyRateDiff = self.keyRate - self.BASELINE_KEY_RATE diffPower = keyRateDiff / 300.0 if self.power < 1 and diffPower > 0: diffPower = diffPower * math.pow(1 - self.power, 1.25) newPower = self.power + diffPower if newPower > 1: newPower = 1 elif newPower < 0: newPower = 0 self.notify.debug('diffPower=%.2f keyRate = %d, newPower=%.2f' % (diffPower, self.keyRate, newPower)) self.power = newPower self.powerBar['value'] = newPower if self.power < self.YELLOW_POWER_THRESHOLD: self.powerBar['barColor'] = VBase4(0.75, 0.75, 1.0, 0.8) elif self.power < self.RED_POWER_THRESHOLD: self.powerBar['barColor'] = VBase4(1.0, 1.0, 0.0, 0.8) else: self.powerBar['barColor'] = VBase4(1.0, 0.0, 0.0, 0.8) self.__spawnUpdateKeyPressRateTask() return Task.done def __setMoveSound(self, sfx): if sfx != self.moveSound: if self.moveSound: self.moveSound.stop() self.moveSound = sfx if self.moveSound: base.playSfx(self.moveSound, looping=1, volume=0.5)
class DistributedPartyCatchActivity(DistributedPartyActivity, DistributedPartyCatchActivityBase): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyCatchActivity') DropTaskName = 'dropSomething' DropObjectPlurals = {'apple': TTLocalizer.PartyCatchActivityApples, 'orange': TTLocalizer.PartyCatchActivityOranges, 'pear': TTLocalizer.PartyCatchActivityPears, 'coconut': TTLocalizer.PartyCatchActivityCoconuts, 'watermelon': TTLocalizer.PartyCatchActivityWatermelons, 'pineapple': TTLocalizer.PartyCatchActivityPineapples, 'anvil': TTLocalizer.PartyCatchActivityAnvils} class Generation: def __init__(self, generation, startTime, startNetworkTime, numPlayers): self.generation = generation self.startTime = startTime self.startNetworkTime = startNetworkTime self.numPlayers = numPlayers self.hasBeenScheduled = False self.droppedObjNames = [] self.dropSchedule = [] self.numItemsDropped = 0 self.droppedObjCaught = {} def __init__(self, cr): DistributedPartyActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyCatch, PartyGlobals.ActivityTypes.HostInitiated, wantRewardGui=True) self.setUsesSmoothing() self.setUsesLookAround() self._sNumGen = SerialNumGen() def getTitle(self): return TTLocalizer.PartyCatchActivityTitle def getInstructions(self): return TTLocalizer.PartyCatchActivityInstructions % {'badThing': self.DropObjectPlurals['anvil']} def generate(self): DistributedPartyActivity.generate(self) self.notify.info('localAvatar doId: %s' % base.localAvatar.doId) self.notify.info('generate()') self._generateFrame = globalClock.getFrameCount() self._id2gen = {} self._orderedGenerations = [] self._orderedGenerationIndex = None rng = RandomNumGen(self.doId) self._generationSeedBase = rng.randrange(1000) self._lastDropTime = 0.0 return def getCurGeneration(self): if self._orderedGenerationIndex is None: return return self._orderedGenerations[self._orderedGenerationIndex] def _addGeneration(self, generation, startTime, startNetworkTime, numPlayers): self._id2gen[generation] = self.Generation(generation, startTime, startNetworkTime, numPlayers) i = 0 while 1: if i >= len(self._orderedGenerations): break gen = self._orderedGenerations[i] startNetT = self._id2gen[gen].startTime genId = self._id2gen[gen].generation if startNetT > startNetworkTime: break if startNetT == startNetworkTime and genId > generation: break i += 1 self._orderedGenerations = self._orderedGenerations[:i] + [generation] + self._orderedGenerations[i:] if self._orderedGenerationIndex is not None: if self._orderedGenerationIndex >= i: self._orderedGenerationIndex += 1 def _removeGeneration(self, generation): del self._id2gen[generation] i = self._orderedGenerations.index(generation) self._orderedGenerations = self._orderedGenerations[:i] + self._orderedGenerations[i + 1:] if self._orderedGenerationIndex is not None: if len(self._orderedGenerations): if self._orderedGenerationIndex >= i: self._orderedGenerationIndex -= 1 else: self._orderedGenerationIndex = None return def announceGenerate(self): self.notify.info('announceGenerate()') self.catchTreeZoneEvent = 'fence_floor' DistributedPartyActivity.announceGenerate(self) def load(self, loadModels = 1, arenaModel = 'partyCatchTree'): self.notify.info('load()') DistributedPartyCatchActivity.notify.debug('PartyCatch: load') self.activityFSM = CatchActivityFSM(self) if __dev__: for o in xrange(3): print {0: 'SPOTS PER PLAYER', 1: 'DROPS PER MINUTE PER SPOT DURING NORMAL DROP PERIOD', 2: 'DROPS PER MINUTE PER PLAYER DURING NORMAL DROP PERIOD'}[o] for i in xrange(1, self.FallRateCap_Players + 10): self.defineConstants(forceNumPlayers=i) numDropLocations = self.DropRows * self.DropColumns numDropsPerMin = 60.0 / self.DropPeriod if o == 0: spotsPerPlayer = numDropLocations / float(i) print '%2d PLAYERS: %s' % (i, spotsPerPlayer) elif o == 1: numDropsPerMinPerSpot = numDropsPerMin / numDropLocations print '%2d PLAYERS: %s' % (i, numDropsPerMinPerSpot) elif i > 0: numDropsPerMinPerPlayer = numDropsPerMin / i print '%2d PLAYERS: %s' % (i, numDropsPerMinPerPlayer) self.defineConstants() self.treesAndFence = loader.loadModel('phase_13/models/parties/%s' % arenaModel) self.treesAndFence.setScale(0.9) self.treesAndFence.find('**/fence_floor').setPos(0.0, 0.0, 0.1) self.treesAndFence.reparentTo(self.root) ground = self.treesAndFence.find('**/groundPlane') ground.setBin('ground', 1) DistributedPartyActivity.load(self) exitText = TextNode('PartyCatchExitText') exitText.setCardAsMargin(0.1, 0.1, 0.1, 0.1) exitText.setCardDecal(True) exitText.setCardColor(1.0, 1.0, 1.0, 0.0) exitText.setText(TTLocalizer.PartyCatchActivityExit) exitText.setTextColor(0.0, 8.0, 0.0, 0.9) exitText.setAlign(exitText.ACenter) exitText.setFont(ToontownGlobals.getBuildingNametagFont()) exitText.setShadowColor(0, 0, 0, 1) exitText.setBin('fixed') if TTLocalizer.BuildingNametagShadow: exitText.setShadow(*TTLocalizer.BuildingNametagShadow) exitTextLoc = self.treesAndFence.find('**/loc_exitSignText') exitTextNp = exitTextLoc.attachNewNode(exitText) exitTextNp.setDepthWrite(0) exitTextNp.setScale(4) exitTextNp.setZ(-.5) self.sign.reparentTo(self.treesAndFence.find('**/loc_eventSign')) self.sign.wrtReparentTo(self.root) self.avatarNodePath = NodePath('PartyCatchAvatarNodePath') self.avatarNodePath.reparentTo(self.root) self._avatarNodePathParentToken = 3 base.cr.parentMgr.registerParent(self._avatarNodePathParentToken, self.avatarNodePath) self.toonSDs = {} self.dropShadow = loader.loadModelOnce('phase_3/models/props/drop_shadow') self.dropObjModels = {} if loadModels: self.__loadDropModels() self.sndGoodCatch = base.loadSfx('phase_4/audio/sfx/SZ_DD_treasure.ogg') self.sndOof = base.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') self.sndAnvilLand = base.loadSfx('phase_4/audio/sfx/AA_drop_anvil_miss.ogg') self.sndPerfect = base.loadSfx('phase_4/audio/sfx/ring_perfect.ogg') self.__textGen = TextNode('partyCatchActivity') self.__textGen.setFont(ToontownGlobals.getSignFont()) self.__textGen.setAlign(TextNode.ACenter) self.activityFSM.request('Idle') def __loadDropModels(self): for objType in PartyGlobals.DropObjectTypes: model = loader.loadModel(objType.modelPath) self.dropObjModels[objType.name] = model modelScales = {'apple': 0.7, 'orange': 0.7, 'pear': 0.5, 'coconut': 0.7, 'watermelon': 0.6, 'pineapple': 0.45} if objType.name in modelScales: model.setScale(modelScales[objType.name]) if objType == PartyGlobals.Name2DropObjectType['pear']: model.setZ(-.6) if objType == PartyGlobals.Name2DropObjectType['coconut']: model.setP(180) if objType == PartyGlobals.Name2DropObjectType['watermelon']: model.setH(135) model.setZ(-.5) if objType == PartyGlobals.Name2DropObjectType['pineapple']: model.setZ(-1.7) if objType == PartyGlobals.Name2DropObjectType['anvil']: model.setZ(-self.ObjRadius) model.flattenStrong() def unload(self): DistributedPartyCatchActivity.notify.debug('unload') self.finishAllDropIntervals() self.destroyOrthoWalk() DistributedPartyActivity.unload(self) self.stopDropTask() del self.activityFSM del self.__textGen for avId in self.toonSDs.keys(): if avId in self.toonSDs: toonSD = self.toonSDs[avId] toonSD.unload() del self.toonSDs self.treesAndFence.removeNode() del self.treesAndFence self.dropShadow.removeNode() del self.dropShadow base.cr.parentMgr.unregisterParent(self._avatarNodePathParentToken) for model in self.dropObjModels.values(): model.removeNode() del self.dropObjModels del self.sndGoodCatch del self.sndOof del self.sndAnvilLand del self.sndPerfect def setStartTimestamp(self, timestamp32): self.notify.info('setStartTimestamp(%s)' % (timestamp32,)) self._startTimestamp = globalClockDelta.networkToLocalTime(timestamp32, bits=32) def getCurrentCatchActivityTime(self): return globalClock.getFrameTime() - self._startTimestamp def getObjModel(self, objName): return self.dropObjModels[objName].copyTo(hidden) def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) base.cr.playGame.getPlace().fsm.request('walk') def handleToonJoined(self, toonId): if toonId not in self.toonSDs: toonSD = PartyCatchActivityToonSD(toonId, self) self.toonSDs[toonId] = toonSD toonSD.load() self.notify.debug('handleToonJoined : currentState = %s' % self.activityFSM.state) self.cr.doId2do[toonId].useLOD(500) if self.activityFSM.state == 'Active': if toonId in self.toonSDs: self.toonSDs[toonId].enter() if base.localAvatar.doId == toonId: base.localAvatar.b_setParent(self._avatarNodePathParentToken) self.putLocalAvatarInActivity() if toonId in self.toonSDs: self.toonSDs[toonId].fsm.request('rules') def handleToonExited(self, toonId): self.notify.debug('handleToonExited( toonId=%s )' % toonId) if toonId in self.cr.doId2do: self.cr.doId2do[toonId].resetLOD() if toonId in self.toonSDs: self.toonSDs[toonId].fsm.request('notPlaying') self.toonSDs[toonId].exit() self.toonSDs[toonId].unload() del self.toonSDs[toonId] if base.localAvatar.doId == toonId: base.localAvatar.b_setParent(ToontownGlobals.SPRender) def takeLocalAvatarOutOfActivity(self): self.notify.debug('localToon has left the circle') base.camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) DistributedSmoothNode.activateSmoothing(1, 0) def _enableCollisions(self): DistributedPartyActivity._enableCollisions(self) self._enteredTree = False self.accept('enter' + self.catchTreeZoneEvent, self._toonMayHaveEnteredTree) self.accept('again' + self.catchTreeZoneEvent, self._toonMayHaveEnteredTree) self.accept('exit' + self.catchTreeZoneEvent, self._toonExitedTree) self.accept(DistributedPartyCannonActivity.LOCAL_TOON_LANDED_EVENT, self._handleCannonLanded) def _disableCollisions(self): self.ignore(DistributedPartyCannonActivity.LOCAL_TOON_LANDED_EVENT) self.ignore('enter' + self.catchTreeZoneEvent) self.ignore('again' + self.catchTreeZoneEvent) self.ignore('exit' + self.catchTreeZoneEvent) DistributedPartyActivity._disableCollisions(self) def _handleCannonLanded(self): x = base.localAvatar.getX() y = base.localAvatar.getY() if x > self.x - self.StageHalfWidth and x < self.x + self.StageHalfWidth and y > self.y - self.StageHalfHeight and y < self.y + self.StageHalfHeight: self._toonEnteredTree(None) return def _toonMayHaveEnteredTree(self, collEntry): if self._enteredTree: return if base.localAvatar.controlManager.currentControls.getIsAirborne(): return self._toonEnteredTree(collEntry) def _toonEnteredTree(self, collEntry): self.notify.debug('_toonEnteredTree : avid = %s' % base.localAvatar.doId) self.notify.debug('_toonEnteredTree : currentState = %s' % self.activityFSM.state) if self.isLocalToonInActivity(): return if self.activityFSM.state == 'Active': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() elif self.activityFSM.state == 'Idle': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() self._enteredTree = True def _toonExitedTree(self, collEntry): self.notify.debug('_toonExitedTree : avid = %s' % base.localAvatar.doId) self._enteredTree = False if hasattr(base.cr.playGame.getPlace(), 'fsm') and self.activityFSM.state == 'Active' and self.isLocalToonInActivity(): if base.localAvatar.doId in self.toonSDs: self.takeLocalAvatarOutOfActivity() self.toonSDs[base.localAvatar.doId].fsm.request('notPlaying') self.d_toonExitDemand() def setToonsPlaying(self, toonIds): self.notify.info('setToonsPlaying(%s)' % (toonIds,)) DistributedPartyActivity.setToonsPlaying(self, toonIds) if self.isLocalToonInActivity() and base.localAvatar.doId not in toonIds: if base.localAvatar.doId in self.toonSDs: self.takeLocalAvatarOutOfActivity() self.toonSDs[base.localAvatar.doId].fsm.request('notPlaying') def __genText(self, text): self.__textGen.setText(text) return self.__textGen.generate() def getNumPlayers(self): return len(self.toonIds) def defineConstants(self, forceNumPlayers = None): DistributedPartyCatchActivity.notify.debug('defineConstants') self.ShowObjSpheres = 0 self.ShowToonSpheres = 0 self.useGravity = True self.trickShadows = True if forceNumPlayers is None: numPlayers = self.getNumPlayers() else: numPlayers = forceNumPlayers self.calcDifficultyConstants(numPlayers) DistributedPartyCatchActivity.notify.debug('ToonSpeed: %s' % self.ToonSpeed) DistributedPartyCatchActivity.notify.debug('total drops: %s' % self.totalDrops) DistributedPartyCatchActivity.notify.debug('numFruits: %s' % self.numFruits) DistributedPartyCatchActivity.notify.debug('numAnvils: %s' % self.numAnvils) self.ObjRadius = 1.0 dropRegionTable = PartyRegionDropPlacer.getDropRegionTable(numPlayers) self.DropRows, self.DropColumns = len(dropRegionTable), len(dropRegionTable[0]) for objType in PartyGlobals.DropObjectTypes: DistributedPartyCatchActivity.notify.debug('*** Object Type: %s' % objType.name) objType.onscreenDuration = objType.onscreenDurMult * self.BaselineOnscreenDropDuration DistributedPartyCatchActivity.notify.debug('onscreenDuration=%s' % objType.onscreenDuration) v_0 = 0.0 t = objType.onscreenDuration x_0 = self.MinOffscreenHeight x = 0.0 g = 2.0 * (x - x_0 - v_0 * t) / (t * t) DistributedPartyCatchActivity.notify.debug('gravity=%s' % g) objType.trajectory = Trajectory(0, Vec3(0, 0, x_0), Vec3(0, 0, v_0), gravMult=abs(g / Trajectory.gravity)) objType.fallDuration = objType.onscreenDuration + self.OffscreenTime return def grid2world(self, column, row): x = column / float(self.DropColumns - 1) y = row / float(self.DropRows - 1) x = x * 2.0 - 1.0 y = y * 2.0 - 1.0 x *= self.StageHalfWidth y *= self.StageHalfHeight return (x, y) def showPosts(self): self.hidePosts() self.posts = [Toon.Toon(), Toon.Toon(), Toon.Toon(), Toon.Toon()] for i in xrange(len(self.posts)): tree = self.posts[i] tree.reparentTo(render) x = self.StageHalfWidth y = self.StageHalfHeight if i > 1: x = -x if i % 2: y = -y tree.setPos(x + self.x, y + self.y, 0) def hidePosts(self): if hasattr(self, 'posts'): for tree in self.posts: tree.removeNode() del self.posts def showDropGrid(self): self.hideDropGrid() self.dropMarkers = [] for row in xrange(self.DropRows): self.dropMarkers.append([]) rowList = self.dropMarkers[row] for column in xrange(self.DropColumns): toon = Toon.Toon() toon.setDNA(base.localAvatar.getStyle()) toon.reparentTo(self.root) toon.setScale(1.0 / 3) x, y = self.grid2world(column, row) toon.setPos(x, y, 0) rowList.append(toon) def hideDropGrid(self): if hasattr(self, 'dropMarkers'): for row in self.dropMarkers: for marker in row: marker.removeNode() del self.dropMarkers def handleToonDisabled(self, avId): DistributedPartyCatchActivity.notify.debug('handleToonDisabled') DistributedPartyCatchActivity.notify.debug('avatar ' + str(avId) + ' disabled') if avId in self.toonSDs: self.toonSDs[avId].exit(unexpectedExit=True) del self.toonSDs[avId] def turnOffSmoothingOnGuests(self): pass def setState(self, newState, timestamp): self.notify.info('setState(%s, %s)' % (newState, timestamp)) DistributedPartyCatchActivity.notify.debug('setState( newState=%s, ... )' % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) if newState == 'Active': if base.localAvatar.doId != self.party.partyInfo.hostId: if globalClock.getFrameCount() > self._generateFrame: if base.localAvatar.getX() > self.x - self.StageHalfWidth and base.localAvatar.getX() < self.x + self.StageHalfWidth and base.localAvatar.getY() > self.y - self.StageHalfHeight and base.localAvatar.getY() < self.y + self.StageHalfHeight: self._toonEnteredTree(None) return def putLocalAvatarInActivity(self): if base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(), 'fsm'): base.cr.playGame.getPlace().fsm.request('activity', [False]) else: self.notify.info("Avoided crash: toontown.parties.DistributedPartyCatchActivity:632, toontown.parties.DistributedPartyCatchActivity:1198, toontown.parties.activityFSMMixins:49, direct.fsm.FSM:423, AttributeError: 'NoneType' object has no attribute 'fsm'") base.localAvatar.stopUpdateSmartCamera() base.camera.reparentTo(self.treesAndFence) base.camera.setPosHpr(0.0, -63.0, 30.0, 0.0, -20.0, 0.0) if not hasattr(self, 'ltLegsCollNode'): self.createCatchCollisions() 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 destroyCatchCollisions(self): if not hasattr(self, 'ltLegsCollNode'): return for collNode in self.toonCollNodes: while collNode.node().getNumSolids(): collNode.node().removeSolid(0) base.localAvatar.cTrav.removeCollider(collNode) del self.toonCollNodes del self.ltLegsCollNode del self.ltHeadCollNode del self.ltLHandCollNode del self.ltRHandCollNode def timerExpired(self): pass def __handleCatch(self, generation, objNum): DistributedPartyCatchActivity.notify.debug('catch: %s' % [generation, objNum]) if base.localAvatar.doId not in self.toonIds: return self.showCatch(base.localAvatar.doId, generation, objNum) objName = self._id2gen[generation].droppedObjNames[objNum] objTypeId = PartyGlobals.Name2DOTypeId[objName] self.sendUpdate('claimCatch', [generation, objNum, objTypeId]) self.finishDropInterval(generation, objNum) def showCatch(self, avId, generation, objNum): if avId not in self.toonSDs: return isLocal = avId == base.localAvatar.doId if generation not in self._id2gen: return if not self._id2gen[generation].hasBeenScheduled: return objName = self._id2gen[generation].droppedObjNames[objNum] objType = PartyGlobals.Name2DropObjectType[objName] if objType.good: if objNum not in self._id2gen[generation].droppedObjCaught: if isLocal: base.playSfx(self.sndGoodCatch) fruit = self.getObjModel(objName) toon = self.getAvatar(avId) rHand = toon.getRightHands()[1] self.toonSDs[avId].eatFruit(fruit, rHand) else: self.toonSDs[avId].fsm.request('fallForward') self._id2gen[generation].droppedObjCaught[objNum] = 1 def setObjectCaught(self, avId, generation, objNum): self.notify.info('setObjectCaught(%s, %s, %s)' % (avId, generation, objNum)) if self.activityFSM.state != 'Active': DistributedPartyCatchActivity.notify.warning('ignoring msg: object %s caught by %s' % (objNum, avId)) return isLocal = avId == base.localAvatar.doId if not isLocal: DistributedPartyCatchActivity.notify.debug('AI: avatar %s caught %s' % (avId, objNum)) self.finishDropInterval(generation, objNum) self.showCatch(avId, generation, objNum) self._scheduleGenerations() gen = self._id2gen[generation] if gen.hasBeenScheduled: objName = gen.droppedObjNames[objNum] if PartyGlobals.Name2DropObjectType[objName].good: if hasattr(self, 'fruitsCaught'): self.fruitsCaught += 1 def finishDropInterval(self, generation, objNum): if hasattr(self, 'dropIntervals'): if (generation, objNum) in self.dropIntervals: self.dropIntervals[generation, objNum].finish() def finishAllDropIntervals(self): if hasattr(self, 'dropIntervals'): for dropInterval in self.dropIntervals.values(): dropInterval.finish() def setGenerations(self, generations): self.notify.info('setGenerations(%s)' % (generations,)) gen2t = {} gen2nt = {} gen2np = {} for id, timestamp32, numPlayers in generations: gen2t[id] = globalClockDelta.networkToLocalTime(timestamp32, bits=32) - self._startTimestamp gen2nt[id] = timestamp32 gen2np[id] = numPlayers ids = self._id2gen.keys() for id in ids: if id not in gen2t: self._removeGeneration(id) for id in gen2t: if id not in self._id2gen: self._addGeneration(id, gen2t[id], gen2nt[id], gen2np[id]) def scheduleDrops(self, genId = None): if genId is None: genId = self.getCurGeneration() gen = self._id2gen[genId] if gen.hasBeenScheduled: return fruitIndex = int((gen.startTime + 0.5 * self.DropPeriod) / PartyGlobals.CatchActivityDuration) fruitNames = ['apple', 'orange', 'pear', 'coconut', 'watermelon', 'pineapple'] fruitName = fruitNames[fruitIndex % len(fruitNames)] rng = RandomNumGen(genId + self._generationSeedBase) gen.droppedObjNames = [fruitName] * self.numFruits + ['anvil'] * self.numAnvils rng.shuffle(gen.droppedObjNames) dropPlacer = PartyRegionDropPlacer(self, gen.numPlayers, genId, gen.droppedObjNames, startTime=gen.startTime) gen.numItemsDropped = 0 tIndex = gen.startTime % PartyGlobals.CatchActivityDuration tPercent = float(tIndex) / PartyGlobals.CatchActivityDuration gen.numItemsDropped += dropPlacer.skipPercent(tPercent) while not dropPlacer.doneDropping(continuous=True): nextDrop = dropPlacer.getNextDrop() gen.dropSchedule.append(nextDrop) gen.hasBeenScheduled = True return def startDropTask(self): taskMgr.add(self.dropTask, self.DropTaskName) def stopDropTask(self): taskMgr.remove(self.DropTaskName) def _scheduleGenerations(self): curT = self.getCurrentCatchActivityTime() genIndex = self._orderedGenerationIndex newGenIndex = genIndex while genIndex is None or genIndex < len(self._orderedGenerations) - 1: if genIndex is None: nextGenIndex = 0 else: nextGenIndex = genIndex + 1 nextGenId = self._orderedGenerations[nextGenIndex] nextGen = self._id2gen[nextGenId] startT = nextGen.startTime if curT >= startT: newGenIndex = nextGenIndex if not nextGen.hasBeenScheduled: self.defineConstants(forceNumPlayers=nextGen.numPlayers) self.scheduleDrops(genId=self._orderedGenerations[nextGenIndex]) genIndex = nextGenIndex self._orderedGenerationIndex = newGenIndex return def dropTask(self, task): self._scheduleGenerations() curT = self.getCurrentCatchActivityTime() if self._orderedGenerationIndex is not None: i = self._orderedGenerationIndex genIndex = self._orderedGenerations[i] gen = self._id2gen[genIndex] while len(gen.dropSchedule) > 0 and gen.dropSchedule[0][0] < curT: drop = gen.dropSchedule[0] gen.dropSchedule = gen.dropSchedule[1:] dropTime, objName, dropCoords = drop objNum = gen.numItemsDropped x, y = self.grid2world(*dropCoords) dropIval = self.getDropIval(x, y, objName, genIndex, objNum) def cleanup(generation, objNum, self = self): del self.dropIntervals[generation, objNum] dropIval.append(Func(Functor(cleanup, genIndex, objNum))) self.dropIntervals[genIndex, objNum] = dropIval gen.numItemsDropped += 1 dropIval.start(curT - dropTime) self._lastDropTime = dropTime return Task.cont def getDropIval(self, x, y, dropObjName, generation, num): objType = PartyGlobals.Name2DropObjectType[dropObjName] id = (generation, num) dropNode = hidden.attachNewNode('catchDropNode%s' % (id,)) dropNode.setPos(x, y, 0) shadow = self.dropShadow.copyTo(dropNode) shadow.setZ(PartyGlobals.CatchDropShadowHeight) shadow.setColor(1, 1, 1, 1) object = self.getObjModel(dropObjName) object.reparentTo(hidden) if dropObjName in ['watermelon', 'anvil']: objH = object.getH() absDelta = {'watermelon': 12, 'anvil': 15}[dropObjName] delta = (self.randomNumGen.random() * 2.0 - 1.0) * absDelta newH = objH + delta else: newH = self.randomNumGen.random() * 360.0 object.setH(newH) sphereName = 'FallObj%s' % (id,) radius = self.ObjRadius if objType.good: radius *= lerp(1.0, 1.3, 0.5) collSphere = CollisionSphere(0, 0, 0, radius) collSphere.setTangible(0) collNode = CollisionNode(sphereName) collNode.setCollideMask(PartyGlobals.CatchActivityBitmask) collNode.addSolid(collSphere) collNodePath = object.attachNewNode(collNode) collNodePath.hide() if self.ShowObjSpheres: collNodePath.show() catchEventName = 'ltCatch' + sphereName def eatCollEntry(forward, collEntry): forward() self.accept(catchEventName, Functor(eatCollEntry, Functor(self.__handleCatch, id[0], id[1]))) def cleanup(self = self, dropNode = dropNode, id = id, event = catchEventName): self.ignore(event) dropNode.removeNode() duration = objType.fallDuration onscreenDuration = objType.onscreenDuration targetShadowScale = 0.3 if self.trickShadows: intermedScale = targetShadowScale * (self.OffscreenTime / self.BaselineDropDuration) shadowScaleIval = Sequence(LerpScaleInterval(shadow, self.OffscreenTime, intermedScale, startScale=0)) shadowScaleIval.append(LerpScaleInterval(shadow, duration - self.OffscreenTime, targetShadowScale, startScale=intermedScale)) else: shadowScaleIval = LerpScaleInterval(shadow, duration, targetShadowScale, startScale=0) targetShadowAlpha = 0.4 shadowAlphaIval = LerpColorScaleInterval(shadow, self.OffscreenTime, Point4(1, 1, 1, targetShadowAlpha), startColorScale=Point4(1, 1, 1, 0)) shadowIval = Parallel(shadowScaleIval, shadowAlphaIval) if self.useGravity: def setObjPos(t, objType = objType, object = object): z = objType.trajectory.calcZ(t) object.setZ(z) setObjPos(0) dropIval = LerpFunctionInterval(setObjPos, fromData=0, toData=onscreenDuration, duration=onscreenDuration) else: startPos = Point3(0, 0, self.MinOffscreenHeight) object.setPos(startPos) dropIval = LerpPosInterval(object, onscreenDuration, Point3(0, 0, 0), startPos=startPos, blendType='easeIn') ival = Sequence(Func(Functor(dropNode.reparentTo, self.root)), Parallel(Sequence(WaitInterval(self.OffscreenTime), Func(Functor(object.reparentTo, dropNode)), dropIval), shadowIval), Func(cleanup), name='drop%s' % (id,)) if objType == PartyGlobals.Name2DropObjectType['anvil']: ival.append(Func(self.playAnvil)) return ival def playAnvil(self): if base.localAvatar.doId in self.toonIds: base.playSfx(self.sndAnvilLand) def initOrthoWalk(self): DistributedPartyCatchActivity.notify.debug('startOrthoWalk') def doCollisions(oldPos, newPos, self = self): x = bound(newPos[0], self.StageHalfWidth, -self.StageHalfWidth) y = bound(newPos[1], self.StageHalfHeight, -self.StageHalfHeight) newPos.setX(x) newPos.setY(y) return newPos orthoDrive = OrthoDrive(self.ToonSpeed, instantTurn=True) self.orthoWalk = OrthoWalk(orthoDrive, broadcast=True) def destroyOrthoWalk(self): DistributedPartyCatchActivity.notify.debug('destroyOrthoWalk') if hasattr(self, 'orthoWalk'): self.orthoWalk.stop() self.orthoWalk.destroy() del self.orthoWalk def startIdle(self): DistributedPartyCatchActivity.notify.debug('startIdle') def finishIdle(self): DistributedPartyCatchActivity.notify.debug('finishIdle') def startActive(self): DistributedPartyCatchActivity.notify.debug('startActive') for avId in self.toonIds: if avId in self.toonSDs: toonSD = self.toonSDs[avId] toonSD.enter() toonSD.fsm.request('normal') self.fruitsCaught = 0 self.dropIntervals = {} self.startDropTask() if base.localAvatar.doId in self.toonIds: self.putLocalAvatarInActivity() def finishActive(self): DistributedPartyCatchActivity.notify.debug('finishActive') self.stopDropTask() if hasattr(self, 'finishIval'): self.finishIval.pause() del self.finishIval if base.localAvatar.doId in self.toonIds: self.takeLocalAvatarOutOfActivity() for ival in self.dropIntervals.values(): ival.finish() del self.dropIntervals def startConclusion(self): DistributedPartyCatchActivity.notify.debug('startConclusion') for avId in self.toonIds: if avId in self.toonSDs: toonSD = self.toonSDs[avId] toonSD.fsm.request('notPlaying') self.destroyCatchCollisions() if base.localAvatar.doId not in self.toonIds: return else: self.localToonExiting() if self.fruitsCaught >= self.numFruits: finishText = TTLocalizer.PartyCatchActivityFinishPerfect else: finishText = TTLocalizer.PartyCatchActivityFinish perfectTextSubnode = hidden.attachNewNode(self.__genText(finishText)) 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() 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)) soundTrack = SoundInterval(self.sndPerfect) self.finishIval = Parallel(textTrack, soundTrack) self.finishIval.start() def finishConclusion(self): DistributedPartyCatchActivity.notify.debug('finishConclusion') if base.localAvatar.doId in self.toonIds: self.takeLocalAvatarOutOfActivity() base.cr.playGame.getPlace().fsm.request('walk') def showJellybeanReward(self, earnedAmount, jarAmount, message): if earnedAmount > 0: DistributedPartyActivity.showJellybeanReward(self, earnedAmount, jarAmount, message) else: base.cr.playGame.getPlace().fsm.request('walk')
def getDropIval(self): shadow = self.shadow drop = self.drop id = self.id hangTime = Globals.ShadowTime dropTime = Globals.DropTime dropHeight = Globals.DropHeight targetShadowScale = 0.5 targetShadowAlpha = 0.4 shadowScaleIval = LerpScaleInterval(shadow, dropTime, targetShadowScale, startScale=0) shadowAlphaIval = LerpColorScaleInterval( shadow, hangTime, Point4(1, 1, 1, targetShadowAlpha), startColorScale=Point4(1, 1, 1, 0)) shadowIval = Parallel(shadowScaleIval, shadowAlphaIval) startPos = Point3(0, 0, dropHeight) drop.setPos(startPos) dropIval = LerpPosInterval(drop, dropTime, Point3(0, 0, 0), startPos=startPos, blendType='easeIn') dropSoundIval = self._dropSfx dropSoundIval.node = self self.drop.setTransparency(1) def _setRandScale(t): self.drop.setScale(self, 1 - random.random() / 16, 1 - random.random() / 16, 1 - random.random() / 4) scaleChange = 0.4 + random.random() / 4 dropShakeSeq = Sequence( LerpScaleInterval(self.drop, 0.25, Vec3(1.0 + scaleChange, 1.0 + scaleChange / 2, 1.0 - scaleChange), blendType='easeInOut'), LerpScaleInterval(self.drop, 0.25, Vec3(1.0, 1.0, 1.0), blendType='easeInOut'), Func(self.disableCollisionDamage), LerpScaleInterval(self.drop, 0.2, Vec3(1.0 + scaleChange / 8, 1.0 + scaleChange / 8, 1.0 - scaleChange / 8), blendType='easeInOut'), LerpScaleInterval(self.drop, 0.2, Vec3(1.0, 1.0, 1.0), blendType='easeInOut'), LerpScaleInterval(self.drop, 0.15, Vec3(1.0 + scaleChange / 16, 1.0 + scaleChange / 16, 1.0 - scaleChange / 16), blendType='easeInOut'), LerpScaleInterval(self.drop, 0.15, Vec3(1.0, 1.0, 1.0), blendType='easeInOut'), LerpScaleInterval(self.drop, 0.1, Vec3(1.0 + scaleChange / 16, 1.0 + scaleChange / 8, 1.0 - scaleChange / 16), blendType='easeInOut'), LerpColorScaleInterval(self.drop, Globals.DropFadeTime, Vec4(1.0, 1.0, 1.0, 0.0))) ival = Sequence(Func(self.reparentTo, render), Parallel(Sequence(WaitInterval(hangTime), dropIval), shadowIval), Parallel(Func(self.game.dropHit, self, id), dropSoundIval, dropShakeSeq), Func(self.game.cleanupDrop, id), name='drop%s' % id) self.ival = ival return ival
def getDropIval(self, x, y, dropObjName, generation, num): objType = PartyGlobals.Name2DropObjectType[dropObjName] id = (generation, num) dropNode = hidden.attachNewNode('catchDropNode%s' % (id,)) dropNode.setPos(x, y, 0) shadow = self.dropShadow.copyTo(dropNode) shadow.setZ(PartyGlobals.CatchDropShadowHeight) shadow.setColor(1, 1, 1, 1) object = self.getObjModel(dropObjName) object.reparentTo(hidden) if dropObjName in ['watermelon', 'anvil']: objH = object.getH() absDelta = {'watermelon': 12, 'anvil': 15}[dropObjName] delta = (self.randomNumGen.random() * 2.0 - 1.0) * absDelta newH = objH + delta else: newH = self.randomNumGen.random() * 360.0 object.setH(newH) sphereName = 'FallObj%s' % (id,) radius = self.ObjRadius if objType.good: radius *= lerp(1.0, 1.3, 0.5) collSphere = CollisionSphere(0, 0, 0, radius) collSphere.setTangible(0) collNode = CollisionNode(sphereName) collNode.setCollideMask(PartyGlobals.CatchActivityBitmask) collNode.addSolid(collSphere) collNodePath = object.attachNewNode(collNode) collNodePath.hide() if self.ShowObjSpheres: collNodePath.show() catchEventName = 'ltCatch' + sphereName def eatCollEntry(forward, collEntry): forward() self.accept(catchEventName, Functor(eatCollEntry, Functor(self.__handleCatch, id[0], id[1]))) def cleanup(self = self, dropNode = dropNode, id = id, event = catchEventName): self.ignore(event) dropNode.removeNode() duration = objType.fallDuration onscreenDuration = objType.onscreenDuration targetShadowScale = 0.3 if self.trickShadows: intermedScale = targetShadowScale * (self.OffscreenTime / self.BaselineDropDuration) shadowScaleIval = Sequence(LerpScaleInterval(shadow, self.OffscreenTime, intermedScale, startScale=0)) shadowScaleIval.append(LerpScaleInterval(shadow, duration - self.OffscreenTime, targetShadowScale, startScale=intermedScale)) else: shadowScaleIval = LerpScaleInterval(shadow, duration, targetShadowScale, startScale=0) targetShadowAlpha = 0.4 shadowAlphaIval = LerpColorScaleInterval(shadow, self.OffscreenTime, Point4(1, 1, 1, targetShadowAlpha), startColorScale=Point4(1, 1, 1, 0)) shadowIval = Parallel(shadowScaleIval, shadowAlphaIval) if self.useGravity: def setObjPos(t, objType = objType, object = object): z = objType.trajectory.calcZ(t) object.setZ(z) setObjPos(0) dropIval = LerpFunctionInterval(setObjPos, fromData=0, toData=onscreenDuration, duration=onscreenDuration) else: startPos = Point3(0, 0, self.MinOffscreenHeight) object.setPos(startPos) dropIval = LerpPosInterval(object, onscreenDuration, Point3(0, 0, 0), startPos=startPos, blendType='easeIn') ival = Sequence(Func(Functor(dropNode.reparentTo, self.root)), Parallel(Sequence(WaitInterval(self.OffscreenTime), Func(Functor(object.reparentTo, dropNode)), dropIval), shadowIval), Func(cleanup), name='drop%s' % (id,)) if objType == PartyGlobals.Name2DropObjectType['anvil']: ival.append(Func(self.playAnvil)) return ival
def __init__(self, gameObject=None): base.loadingScreen.beginStep('LegendaryGameGUI', 4, 20) self.gameObject = gameObject self.guiImage = loader.loadModel( 'models/minigames/pir_m_gam_fsh_legendaryGui') self.UICompoments = {} self.uiBaseNode = NodePath('baseNode') self.uiBaseNode.reparentTo(aspect2d) self.uiBaseNode.show() self.leftBaseNode = NodePath('leftBaseNode') self.leftBaseNode.reparentTo(base.a2dLeftCenter) self.leftBaseNode.show() self.fishActor = None self.actorAnim = {} self.scaleSize = { InventoryType.Collection_Set11_Part1: 0.059999999999999998, InventoryType.Collection_Set11_Part2: 0.055, InventoryType.Collection_Set11_Part3: 0.12, InventoryType.Collection_Set11_Part4: 0.086999999999999994, InventoryType.Collection_Set11_Part5: 0.080000000000000002 } self.meterFrame = DirectFrame( parent=self.leftBaseNode, frameSize=(-0.29999999999999999, 0.29999999999999999, -1.0, 0.0), frameColor=(1.0, 1.0, 1.0, 0.0), relief=None, state=DGG.DISABLED, pos=(1.0, 0.0, -0.45000000000000001), hpr=(0, 0, 0), scale=(1.3, 0.0, 1.3), image=self.guiImage.find('**/pir_t_gui_fsh_meter'), image_scale=(0.20000000000000001, 0.0, 0.80000000000000004), image_pos=(0, 0, 0), text='', textMayChange=1, text_scale=PiratesGuiGlobals.TextScaleTitleLarge, text_pos=(-0.55000000000000004, 0.10000000000000001), text_shadow=PiratesGuiGlobals.TextShadow) self.UICompoments['meterFrame'] = self.meterFrame self.fishingRod = DirectFrame( parent=self.meterFrame, frameSize=(-0.29999999999999999, 0.29999999999999999, -1.0, 0.0), relief=None, state=DGG.DISABLED, pos=FishingGlobals.fishingRodScreenPosition, image=self.guiImage.find('**/pir_t_gui_fsh_fullRod'), image_scale=(1.0, 0.0, 0.125), image_pos=(0.20000000000000001, 0, 0)) self.fishingRod.setR(FishingGlobals.fishingRodInitSlope) self.UICompoments['fishingRod'] = self.fishingRod base.loadingScreen.tick() self.fishingHandleBaseFrame = DirectFrame( parent=self.uiBaseNode, frameSize=(-0.29999999999999999, 0.29999999999999999, -1.5, 1.5), frameColor=(1.0, 1.0, 1.0, 0.0), relief=None, state=DGG.DISABLED, pos=(0.0, 0.0, 0.0), hpr=(0, 0, 0), scale=(0.71999999999999997, 0.0, 0.71999999999999997), image=self.guiImage.find('**/pir_t_gui_fsh_partialRod'), image_scale=(3.7999999999999998, 0.0, 1.8999999999999999), image_pos=(0, 0, 0), image_hpr=(0.0, 0.0, 0)) self.fishingHandleBaseFrame.hide() self.UICompoments[ 'fishingHandleBaseFrame'] = self.fishingHandleBaseFrame self.fishingHandle = DirectFrame( parent=self.fishingHandleBaseFrame, frameSize=(-0.080000000000000002, 0.080000000000000002, -0.20000000000000001, 0.20000000000000001), relief=None, state=DGG.DISABLED, pos=(-0.10000000000000001, 0.0, -0.050000000000000003), hpr=(0, 0, 0), image=self.guiImage.find('**/pir_t_gui_fsh_handleArm'), image_scale=(1.0, 0.0, 1.0), image_pos=(-0.042000000000000003, 0, -0.115), image_hpr=(0.0, 0.0, 0)) self.UICompoments['fishingHandle'] = self.fishingHandle self.arrowImage = DirectFrame( parent=self.fishingHandleBaseFrame, frameSize=(-0.40000000000000002, 0.40000000000000002, -0.40000000000000002, 0.40000000000000002), relief=None, state=DGG.DISABLED, pos=(0.0, 0.0, 0.0), hpr=(0, 0, 0), scale=(1.2, 0.0, 1.2), image=self.guiImage.find('**/pir_t_gui_fsh_arrow'), image_scale=(1.0, 0.0, 1.0), image_pos=(0.0, 0, 0.0), image_hpr=(0.0, 0.0, 0.0)) self.arrowImage.hide() self.UICompoments['arrowImage'] = self.arrowImage btnGeom = (self.guiImage.find('**/pir_t_gui_fsh_handle'), self.guiImage.find('**/pir_t_gui_fsh_handle'), self.guiImage.find('**/pir_t_gui_fsh_handleOn')) self.fishingHandleButton = GuiButton(pos=(-0.29999999999999999, 0, -0.55000000000000004), hpr=(0, 0, 0), scale=0.45000000000000001, image=btnGeom, image_pos=(0, 0, 0), image_scale=1.0, sortOrder=2) self.fishingHandleButton.bind(DGG.B1PRESS, self.handleButtonClicked) self.fishingHandleButton.reparentTo(self.fishingHandle) self.UICompoments['fishingHandleButton'] = self.fishingHandleButton self.fishingHandleBaseFrame.setTransparency(TransparencyAttrib.MAlpha) self.meterFrame.setTransparency(TransparencyAttrib.MAlpha) self.lineOneTransitTextNode = TextNode('lineOneTransitText') self.lineOneTransitTextNode.setFont(PiratesGlobals.getPirateFont()) self.lineOneTransitTextNode.setText('') self.lineOneTransitTextNode.setAlign(TextNode.ACenter) self.lineOneTransitTextNode.setTextColor(1.0, 1.0, 1.0, 0.5) self.lineOneTransitTextNodePath = NodePath(self.lineOneTransitTextNode) self.lineOneTransitTextNodePath.setPos(0.0, 0.0, -0.80000000000000004) self.lineOneTransitTextNodePath.setScale(0.34999999999999998, 0.34999999999999998, 0.34999999999999998) self.lineOneTransitTextNodePath.reparentTo(self.uiBaseNode) self.lineOneTransitTextNodePath.hide() self.UICompoments[ 'lineOneTransitText'] = self.lineOneTransitTextNodePath self.lineTwoTransitTextNode = TextNode('lineTwoTransitText') self.lineTwoTransitTextNode.setFont(PiratesGlobals.getPirateFont()) self.lineTwoTransitTextNode.setText('') self.lineTwoTransitTextNode.setAlign(TextNode.ACenter) self.lineTwoTransitTextNode.setTextColor(1.0, 1.0, 1.0, 0.5) self.lineTwoTransitTextNodePath = NodePath(self.lineTwoTransitTextNode) self.lineTwoTransitTextNodePath.setPos(-0.40000000000000002, 0.0, -0.94999999999999996) self.lineTwoTransitTextNodePath.setScale(0.12, 0.12, 0.12) self.lineTwoTransitTextNodePath.reparentTo(self.uiBaseNode) self.lineTwoTransitTextNodePath.hide() self.UICompoments[ 'lineTwoTransitText'] = self.lineTwoTransitTextNodePath base.loadingScreen.tick() self.test_guiImage = loader.loadModel('models/gui/toplevel_gui') self.buttonIcon = ( self.test_guiImage.find('**/treasure_chest_closed'), self.test_guiImage.find('**/treasure_chest_closed'), self.test_guiImage.find('**/treasure_chest_closed_over')) self.winImagePanel = GuiPanel.GuiPanel('', 2.6000000000000001, 1.8999999999999999, True) self.winImagePanel.setPos(-1.3, 0.0, -0.94999999999999996) self.winImagePanel.reparentTo(self.uiBaseNode) self.winImagePanel.background = OnscreenImage( parent=self.winImagePanel, scale=(2.3999999999999999, 0, 1.8), image=self.guiImage.find('**/pir_t_gui_fsh_posterBackground'), hpr=(0, 0, 0), pos=(1.3, 0, 0.94999999999999996)) self.winImagePanel.setBin('gui-popup', -4) self.winTitleTextNode = TextNode('winTitleTextNode') self.winTitleTextNode.setText('Congratulations!') self.winTitleTextNode.setAlign(TextNode.ACenter) self.winTitleTextNode.setFont(PiratesGlobals.getPirateFont()) self.winTitleTextNode.setTextColor(0.23000000000000001, 0.089999999999999997, 0.029999999999999999, 1.0) self.winTitleTextNodePath = NodePath(self.winTitleTextNode) self.winTitleTextNodePath.setPos(1.3500000000000001, 0.0, 1.6699999999999999) self.winTitleTextNodePath.setScale(0.17999999999999999) self.winTitleTextNodePath.reparentTo(self.winImagePanel) self.wholeStoryTextNode = TextNode('storyTextNode') self.wholeStoryTextNode.setText('') self.wholeStoryTextNode.setWordwrap(19.0) self.wholeStoryTextNode.setTextColor(0.23000000000000001, 0.089999999999999997, 0.029999999999999999, 1.0) self.wholeStoryTextNodePath = NodePath(self.wholeStoryTextNode) self.wholeStoryTextNodePath.setPos(0.33000000000000002, 0.0, 1.6399999999999999) self.wholeStoryTextNodePath.setScale(0.050000000000000003) self.wholeStoryTextNodePath.reparentTo(self.winImagePanel) self.winImagePanel.closeButton[ 'command'] = self.closeDialogGotNextState self.winImagePanel.closeButton['extraArgs'] = [ 'winImagePanel', 'FarewellLegendaryFish', False ] self.UICompoments['winImagePanel'] = self.winImagePanel self.winImagePanel.hide() self.luiCloseDialogSequence = Sequence() self.arrowImageRotationInterval = LerpHprInterval( self.arrowImage, 2.2000000000000002, self.arrowImage.getHpr() + Point3(0.0, 0.0, 280.0), self.arrowImage.getHpr()) self.luiArrowRotatingSequence = Sequence( Func(self.showGui, ['arrowImage']), Parallel(Func(self.arrowImageRotationInterval.start), Wait(2.2000000000000002)), Func(self.hideGui, ['arrowImage']), Func(self.arrowImage.setHpr, self.arrowImage.getHpr() + Point3(0.0, 0.0, 5.0)), name=self.gameObject.distributedFishingSpot.uniqueName( 'luiArrowRotatingSequence')) self.lineOneColorChange = LerpColorScaleInterval( self.lineOneTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (1.0, 1.0, 1.0, 0.0), (1.0, 1.0, 1.0, 1.0), blendType='easeOut') self.lineOnePosChange = LerpPosInterval( self.lineOneTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (0.0, 0.0, -0.20000000000000001), (0.0, 0.0, -0.80000000000000004), blendType='easeOut') self.lineTwoCholorChange = LerpColorScaleInterval( self.lineTwoTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (1.0, 1.0, 1.0, 1.0), (1.0, 1.0, 1.0, 1.0), blendType='easeOut') self.lineTwoPosChange = LerpPosInterval( self.lineTwoTransitTextNodePath, FishingGlobals.legendaryTransitionTextDuration, (0.0, 0.0, -0.32000000000000001), (0.0, 0.0, -0.94999999999999996), blendType='easeOut') self.transitionTextMovingSequence = Sequence( Func(self.lineOneTransitTextNodePath.show), Func(self.lineTwoTransitTextNodePath.show), Parallel(self.lineOnePosChange, self.lineTwoPosChange, self.lineOneColorChange, self.lineTwoCholorChange), Func(self.lineOneTransitTextNodePath.hide), Func(self.lineTwoTransitTextNodePath.hide), name=self.gameObject.distributedFishingSpot.uniqueName( 'transitionTextMovingSequence')) self.meterFadeInInterval = Sequence( Func(self.meterFrame.show), LerpColorScaleInterval( self.meterFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale=(1.0, 1.0, 1.0, 1.0), startColorScale=(1.0, 1.0, 1.0, 0.0), blendType='easeOut'), name='FadeInLegendaryMeter') self.meterFadeOutInterval = Sequence(LerpColorScaleInterval( self.meterFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale=(1.0, 1.0, 1.0, 0.0), startColorScale=(1.0, 1.0, 1.0, 1.0), blendType='easeOut'), Func(self.meterFrame.hide), name='FadeOutLegendaryMeter') self.rodFadeInInterval = Sequence( Func(self.fishingHandleBaseFrame.show), LerpColorScaleInterval( self.fishingHandleBaseFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale=(1.0, 1.0, 1.0, 1.0), startColorScale=(1.0, 1.0, 1.0, 0.0), blendType='easeOut'), name='FadeInLegendaryRodInterface') self.rodFadeOutInterval = Sequence( LerpColorScaleInterval( self.fishingHandleBaseFrame, FishingGlobals.legendaryTransitionTextDuration, colorScale=(1.0, 1.0, 1.0, 0.0), startColorScale=(1.0, 1.0, 1.0, 1.0), blendType='easeOut'), Func(self.fishingHandleBaseFrame.hide), name='FadeOutLegendaryRodInterface') base.loadingScreen.tick() smallScale = self.fishingHandleButton['scale'] bigScale = self.fishingHandleButton['scale'] * 1.2 self.buttonGrowUpInterval = LerpScaleInterval(self.fishingHandleButton, 1.0, bigScale, smallScale) self.luiFightTransitSequence = Sequence( Parallel(Func(self.fishingHandleBaseFrame.show), Func(self.meterFadeOutInterval.start), Func(self.rodFadeInInterval.start), Func(self.buttonGrowUpInterval.start)), Wait(1.0), Func(self.meterFrame.hide), name=self.gameObject.distributedFishingSpot.uniqueName( 'luiFightTransitSequence')) self.luiReelTransitSequence = Sequence( Parallel(Func(self.fishingHandleBaseFrame.show), Func(self.meterFadeOutInterval.start), Func(self.rodFadeInInterval.start)), Wait(1.0), Func(self.meterFrame.hide), name=self.gameObject.distributedFishingSpot.uniqueName( 'luiReelTransitSequence')) self.luiStruggleTransitSequence = Sequence( Parallel(Func(self.meterFrame.show), Func(self.resetFishingRod), self.meterFadeInInterval, self.rodFadeOutInterval), Wait(1.0), Func(self.fishingHandleBaseFrame.hide), name=self.gameObject.distributedFishingSpot.uniqueName( 'luiStruggleTransitSequence')) self.meterFadeOutInterval.start() self.rodFadeOutInterval.start() self.hideAllGUI() base.loadingScreen.endStep('LegendaryGameGUI')
class DistributedBoat(DistributedObject): notify = directNotify.newCategory("DistributedBoat") def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM('DistributedBoat', [ State('off', self.enterOff, self.exitOff), State('eastToWest', self.enterEastToWest, self.exitEastToWest), State('westToEast', self.enterWestToEast, self.exitWestToEast) ], 'off', 'off') self.boat = None self.eastPier = None self.eastPierPath = 'east_pier' self.westPier = None self.westPierPath = 'west_pier' self.pierUpP = 0.0 self.pierDownP = -45.0 self.fogHorn = 'phase_5/audio/sfx/SZ_DD_foghorn.ogg' self.shipBell = 'phase_6/audio/sfx/SZ_DD_shipbell.ogg' self.waterLap = 'phase_6/audio/sfx/SZ_DD_waterlap.ogg' self.dockCreak = 'phase_6/audio/sfx/SZ_DD_dockcreak.ogg' self.eastWest = 'phase_6/paths/dd-e-w.bam' self.westEast = 'phase_6/paths/dd-w-e.bam' self.boatPath = '*donalds_boat*' self.track = None self.state = None def __handleOnBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPDonaldsBoat) base.playSfx(self.soundWaterLap, looping=1) def __handleOffBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPRender) self.soundWaterLap.stop() def __pollBoat(self, task): try: self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) except: return task.cont self.generated() return task.done def generate(self): DistributedObject.generate(self) self.soundFogHorn = base.loadSfx(self.fogHorn) self.soundShipBell = base.loadSfx(self.shipBell) self.soundWaterLap = base.loadSfx(self.waterLap) self.soundDockCreak = base.loadSfx(self.dockCreak) #try: # self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) #except: # base.taskMgr.add(self.__pollBoat, self.uniqueName('__pollBoat')) # return self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) self.generated() def generated(self): self.eastPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.eastPierPath) self.westPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.westPierPath) base.cr.parentMgr.registerParent(CIGlobals.SPDonaldsBoat, self.boat) self.accept('enterdonalds_boat_floor', self.__handleOnBoat) self.accept('exitdonalds_boat_floor', self.__handleOffBoat) self.d_requestCurrentStateAndTimestamp() self.fsm.enterInitialState() def disable(self): base.taskMgr.remove(self.uniqueName('__pollBoat')) base.cr.parentMgr.unregisterParent(CIGlobals.SPDonaldsBoat) self.ignore('enterdonalds_boat_floor') self.ignore('exitdonalds_boat_floor') self.fsm.requestFinalState() del self.fsm del self.soundFogHorn del self.soundShipBell del self.soundWaterLap del self.soundDockCreak self.fogHorn = None self.shipBell = None self.waterLap = None self.dockCreak = None self.boat = None self.track = None self.pierDownP = None self.pierUpP = None self.eastPier = None self.eastPierPath = None self.westPier = None self.westPierPath = None self.boatPath = None self.westEast = None self.eastWest = None DistributedObject.disable(self) def currentStateAndTimestamp(self, state, timestamp): self.setState(state, timestamp) def d_requestCurrentStateAndTimestamp(self): self.sendUpdate('requestCurrentStateAndTimestamp', []) def setState(self, state, timestamp=None): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.state = state if self.boat: self.fsm.request(state, [ts]) def enterEastToWest(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.eastWest) moIval = MopathInterval(moPath, self.boat) self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.eastPier), moIval, LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierDownP, 0), startHpr=(90, self.pierUpP, 0)), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierUpP, 0), startHpr=(-90, self.pierDownP, 0)), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.westPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitEastToWest(self): if self.track: self.track.finish() self.track = None def enterWestToEast(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.westEast) moIval = MopathInterval(moPath, self.boat) self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.westPier), moIval, LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierDownP, 0), startHpr=(-90, self.pierUpP, 0)), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierUpP, 0), startHpr=(90, self.pierDownP, 0)), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.eastPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitWestToEast(self): if self.track: self.track.finish() self.track = None def enterOff(self): pass def exitOff(self): pass