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 self.timeout = 5.0 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() def cleanupGag(self): if self.gag: self.gag.removeNode() self.gag = None
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
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
class JugglingBalls(ToonUpGag): name = GagGlobals.JugglingBalls model = 'phase_5/models/props/cubes-mod.bam' minHeal = 90 maxHeal = 120 efficiency = 100 hitSfxPath = GagGlobals.JUGGLE_SFX anim = 'phase_5/models/props/cubes-chan.bam' def __init__(self): ToonUpGag.__init__(self) self.setImage('phase_3.5/maps/juggling-cubes.png') self.track = None self.soundInterval = None self.timeout = 8.0 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) BSPUtility.applyUnlitOverride(self.gag) 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): # self.gag returns the juggling balls. super(JugglingBalls, self).equip() def unEquip(self): if self.track: self.soundInterval.finish() self.track.finish() self.track = None self.reset()
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 self.timeout = 8.0 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
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
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
class PairingGameCard(PlayingCardNodePath): """ The specifc class used for the pairing game """ DoIntervalDefault = True FlipTime = 0.25 UseDifferentCardColors = True # these color values were taken from ToonDNA.py CardColors = [ (0.933594, 0.265625, 0.28125, 1.0), # bright red (0.550781, 0.824219, 0.324219, 1.0), # light green (0.347656, 0.820312, 0.953125, 1.0), # light blue (0.460938, 0.378906, 0.824219, 1.0), # purple blue (0.710938, 0.234375, 0.4375, 1.0), # plum (0.285156, 0.328125, 0.726562, 1.0), # blue (0.242188, 0.742188, 0.515625, 1.0), # seafoam (0.96875, 0.691406, 0.699219, 1.0), # light pink (0.996094, 0.957031, 0.597656, 1.0), # light yellow (0.992188, 0.480469, 0.167969, 1.0), # orange ] def __init__(self, value): """Constructor, value should be [0..51].""" style = PlayingCardGlobals.Styles[0] PlayingCardNodePath.__init__(self, style, value) self.enterCallback = None self.exitCallback = None def load(self): """Load the assets.""" # these are just temp assets oneCard = loader.loadModel( "phase_4/models/minigames/garden_sign_memory") # grab the gag icon prop = self.attachNewNode('prop') PlayingCardGlobals.getImage(self.style, self.suit, self.rank).copyTo(prop) prop.setScale(7) # remove the bits we don't want oneCard.find('**/glow').removeNode() #oneCard.find('**/shadow').removeNode() # munge the collision to fit just the sign cs = oneCard.find('**/collision') #cs.setScale(1, 1.0, 0.5) #cs.setPos(0,0, 0.9) for solidIndex in range(cs.node().getNumSolids()): cs.node().modifySolid(solidIndex).setTangible(False) cs.node().setName('cardCollision-%d' % self.value) # munge the sign to fit the rank sign = oneCard.find('**/sign1') if self.UseDifferentCardColors: index = self.rank % len(self.CardColors) color = self.CardColors[index] sign.setColorScale(*color) # set up the prop that shows which tree it is prop.setPos(0.0, 0.0, 0.08) prop.setP(-90) prop.reparentTo(oneCard) oneCard.reparentTo(self) #set up the back of the card 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.remove() self.setR(0) # the default value is face Up self.setScale(2.5) self.flipIval = None self.turnUpSound = base.loadSfx( "phase_4/audio/sfx/MG_pairing_card_flip_face_up.mp3") self.turnDownSound = base.loadSfx( "phase_4/audio/sfx/MG_pairing_card_flip_face_down.mp3") def unload(self): """Unload the assets.""" self.clearFlipIval() self.removeNode() del self.turnUpSound del self.turnDownSound def turnUp(self, doInterval=DoIntervalDefault): """Turn up the card. doInterval -- if true do a sound and flip up animation """ assert self.value != PlayingCardGlobals.Unknown 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): """Clear any flip intervals on this card.""" if self.flipIval: self.flipIval.finish() self.flipIval = None def turnDown(self, doInterval=DoIntervalDefault): """Turn up the card. doInterval -- if true do a sound and flip up animation """ 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 DistributedDodgeballGame(DistributedToonFPSGame, TeamMinigame): notify = directNotify.newCategory('DistributedDodgeballGame') TreeData = [ [ 'prop_snow_tree_small_ur', Point3(23.23, 66.52, 7.46)], [ 'prop_snow_tree_small_ul', Point3(-34.03, 88.02, 24.17)], [ 'prop_snow_tree_small_ur', Point3(-54.8, 0, 4.19)], [ 'prop_snow_tree_small_ul', Point3(54.8, -5, 4.19)], [ 'prop_snow_tree_small_ur', Point3(62.71, 62.66, 16.8)], [ 'prop_snow_tree_small_ul', Point3(-23.23, -66.52, 6)], [ 'prop_snow_tree_small_ur', Point3(34.03, -88.02, 23)], [ 'prop_snow_tree_small_ul', Point3(-62.71, -62.66, 16)]] SnowballData = [ Point3(30, 0, 0.75), Point3(22.5, 0, 0.75), Point3(15, 0, 0.75), Point3(7.5, 0, 0.75), Point3(0, 0, 0.75), Point3(-7.5, 0, 0.75), Point3(-15, 0, 0.75), Point3(-22.5, 0, 0.75), Point3(-30, 0, 0.75)] GameSong = 'phase_4/audio/bgm/MG_Dodgeball.ogg' GameDesc = 'Welcome to the north! You have been invited to play dodgeball with the penguins!\n\nHow To Play\nWASD to Move and use the mouse to aim.\nLeft click to Throw!\nThrow a snowball at a teammate to unfreeze them!\n\nObjective\nThe first team to freeze everyone!' InitCamTrans = [ Point3(25, 45, 19.5317), Vec3(154.001, -15, 0)] SnowBallDmg = 25 GetSnowBalls = 'Pick up a snowball from the center!' Team2OtherBarrier = {BLUE: 'red_barrier_coll', RED: 'blue_barrier_coll'} def __init__(self, cr): try: self.DistributedDodgeballGame_initialized return except: self.DistributedDodgeballGame_initialized = 1 DistributedToonFPSGame.__init__(self, cr) TeamMinigame.__init__(self, 'BlueSnow', ('phase_4/maps/db_blue_neutral.png', 'phase_4/maps/db_blue_hover.png', 'phase_4/maps/db_blue_hover.png'), 'RedIce', ('phase_4/maps/db_red_neutral.png', 'phase_4/maps/db_red_hover.png', 'phase_4/maps/db_red_hover.png')) self.fsm.addState(State('chooseTeam', self.enterChooseTeam, self.exitChooseTeam, ['waitForOthers'])) self.fsm.addState(State('scrollBy', self.enterScrollBy, self.exitScrollBy, ['countdown'])) self.fsm.addState(State('countdown', self.enterCountdown, self.exitCountdown, ['play'])) self.fsm.addState(State('announceGameOver', self.enterAnnGameOver, self.exitAnnGameOver, ['displayWinners'])) self.fsm.addState(State('displayWinners', self.enterDisplayWinners, self.exitDisplayWinners, ['gameOver'])) self.fsm.getStateNamed('waitForOthers').addTransition('chooseTeam') self.fsm.getStateNamed('waitForOthers').addTransition('scrollBy') self.fsm.getStateNamed('play').addTransition('announceGameOver') self.firstPerson = DodgeballFirstPerson(self) self.scrollBySeq = None self.infoText = None self.redScoreLbl = None self.blueScoreLbl = None self.infoText = getAlertText() self.spawnPointsByTeam = {BLUE: [ [ Point3(5, 15, 0), Vec3(180, 0, 0)], [ Point3(15, 15, 0), Vec3(180, 0, 0)], [ Point3(-5, 15, 0), Vec3(180, 0, 0)], [ Point3(-15, 15, 0), Vec3(180, 0, 0)]], RED: [ [ Point3(5, -15, 0), Vec3(0, 0, 0)], [ Point3(15, -15, 0), Vec3(0, 0, 0)], [ Point3(-5, -15, 0), Vec3(0, 0, 0)], [ Point3(-15, -15, 0), Vec3(0, 0, 0)]]} self.winnerMusic = base.loadMusic('phase_9/audio/bgm/encntr_hall_of_fame.mid') self.loserMusic = base.loadMusic('phase_9/audio/bgm/encntr_sting_announce.mid') self.danceSound = base.loadSfx('phase_3.5/audio/sfx/ENC_Win.ogg') self.sky = None self.arena = None self.fog = None self.snow = None self.snowRender = None self.trees = [] self.snowballs = [] return def getTeamDNAColor(self, team): print 'getTeamDNAColor' if team == TEAM1: print 'blue' return ToonDNA.colorName2DNAcolor['blue'] if team == TEAM2: print 'bright red' return ToonDNA.colorName2DNAcolor['bright red'] def enterDisplayWinners(self): base.localAvatar.stopLookAround() base.localAvatar.resetHeadHpr() base.localAvatar.getGeomNode().show() camera.reparentTo(render) camera.setPos((-2.5, 12, 3.5)) camera.setHpr((-175.074, -5.47218, 0)) base.transitions.fadeIn() base.playSfx(self.danceSound, looping=1) if self.winnerTeam == self.team: base.playMusic(self.winnerMusic, volume=0.8) else: base.playMusic(self.loserMusic, volume=0.8) winnerPositions = [(-2, 0, 0), (2, 0, 0), (6, 0, 0), (-6, 0, 0)] loserPositions = [(-3.5, -10, 0), (-1.5, -15, 0), (3.0, -8, 0), (5.5, -12, 0)] for team in [RED, BLUE]: for avId in self.playerListByTeam[team]: av = self.cr.doId2do.get(avId) if av: av.stopSmooth() av.setHpr(0, 0, 0) if team == self.winnerTeam: posList = winnerPositions av.setAnimState('off') av.stop() if not self.getRemoteAvatar(avId).isFrozen: av.loop('win') else: posList = loserPositions av.setAnimState('off') av.stop() if not self.getRemoteAvatar(avId).isFrozen: av.loop('pout') pos = random.choice(posList) posList.remove(pos) av.setPos(pos) if self.winnerTeam == team: text = 'YOU WIN!' else: text = 'YOU LOSE!' self.gameOverLbl.setText(text) self.track = Sequence(Wait(2.0), Func(self.gameOverLbl.setScale, 0.01), Func(self.gameOverLbl.show), getAlertPulse(self.gameOverLbl, 0.27, 0.25)) self.track.start() def exitDisplayWinners(self): base.transitions.noTransitions() self.danceSound.stop() if hasattr(self, 'track'): self.track.finish() self.track = None self.gameOverLbl.hide() return def enterAnnGameOver(self, timeRanOut=0): self.firstPerson.vModel.hide() text = 'GAME\nOVER' if timeRanOut: text = "TIME's\nUP" self.gameOverLbl.setText(text) self.gameOverLbl.show() base.transitions.fadeScreen() taskMgr.doMethodLater(3.0, self.__annGameOverTask, self.uniqueName('annGameOverTask')) def __annGameOverTask(self, task): self.gameOverLbl.hide() self.ival = Sequence(base.transitions.getFadeOutIval(), Func(self.fsm.request, 'displayWinners')) self.ival.start() return task.done def exitAnnGameOver(self): taskMgr.remove(self.uniqueName('annGameOverTask')) if hasattr(self, 'ival'): self.ival.finish() del self.ival self.gameOverLbl.hide() def teamWon(self, team): self.winnerTeam = team base.localAvatar.disableAvatarControls() self.firstPerson.end() self.deleteTimer() self.fsm.request('announceGameOver') def incrementTeamScore(self, team): TeamMinigame.incrementTeamScore(self, team) if team == BLUE: self.blueScoreLbl.setText('BLUE: ' + str(self.scoreByTeam[team])) ToontownIntervals.start(ToontownIntervals.getPulseLargerIval(self.blueScoreLbl, 'blueScorePulse')) else: if team == RED: self.redScoreLbl.setText('RED: ' + str(self.scoreByTeam[team])) ToontownIntervals.start(ToontownIntervals.getPulseLargerIval(self.redScoreLbl, 'redScorePulse')) def getWinterDodgeballScoreText(self, color): text = OnscreenText(fg=color, font=CIGlobals.getMinnieFont(), scale=0.15, shadow=(0, 0, 0, 1)) return text def snowballHitWall(self, snowballIndex): snowball = self.snowballs[snowballIndex] snowball.handleHitWallOrPlayer() base.playSfx(snowball.impactSound, node=snowball, volume=1.5) def snowballHitGround(self, snowballIndex): snowball = self.snowballs[snowballIndex] snowball.handleHitGround() base.playSfx(snowball.impactSound, node=snowball, volume=1.5) def snowballHitPlayer(self, damagedPlayer, throwerTeam, snowballIndex): av = self.getRemoteAvatar(damagedPlayer) if av: if throwerTeam == av.team: if av.unFreeze(): if damagedPlayer == base.localAvatar.doId: self.showAlert('A team member has unfroze you!') self.firstPerson.camFSM.request('unfrozen') self.sendUpdate('teamMateUnfrozeMe', [self.team]) elif av.freeze(): if damagedPlayer == base.localAvatar.doId: self.showAlert("You've been frozen by an enemy!") self.firstPerson.camFSM.request('frozen') self.sendUpdate('enemyFrozeMe', [self.team, throwerTeam]) snowball = self.snowballs[snowballIndex] snowball.handleHitWallOrPlayer() base.playSfx(snowball.impactSound, node=snowball, volume=1.5) def playerCaughtSnowball(self, snowballIndex, catcherId): av = self.getRemoteAvatar(catcherId) if av: snowball = self.snowballs[snowballIndex] snowball.pauseThrowIval() snowball.pickup(av) def setupRemoteAvatar(self, avId): av = RemoteDodgeballAvatar(self, self.cr, avId) if avId == self.cr.localAvId: self.myRemoteAvatar = av self.remoteAvatars.append(av) def __getSnowTree(self, path): trees = loader.loadModel('phase_8/models/props/snow_trees.bam') tree = trees.find('**/' + path) tree.find('**/*shadow*').removeNode() return tree def load(self): self.setMinigameMusic(DistributedDodgeballGame.GameSong) self.setDescription(DistributedDodgeballGame.GameDesc) self.setWinnerPrize(200) self.setLoserPrize(0) self.createWorld() self.blueScoreLbl = self.getWinterDodgeballScoreText(VBase4(0, 0, 1, 1)) self.blueScoreLbl.reparentTo(base.a2dTopLeft) self.blueScoreLbl['align'] = TextNode.ALeft self.blueScoreLbl.setText('Blue: 0') self.blueScoreLbl.setZ(-0.17) self.blueScoreLbl.setX(0.05) self.blueScoreLbl.hide() self.redScoreLbl = self.getWinterDodgeballScoreText(VBase4(1, 0, 0, 1)) self.redScoreLbl.reparentTo(base.a2dTopLeft) self.redScoreLbl['align'] = TextNode.ALeft self.redScoreLbl.setText('Red: 0') self.redScoreLbl.setZ(-0.35) self.redScoreLbl.setX(0.05) self.redScoreLbl.hide() trans = DistributedDodgeballGame.InitCamTrans camera.setPos(trans[0]) camera.setHpr(trans[1]) DistributedToonFPSGame.load(self) def createWorld(self): self.deleteWorld() self.sky = loader.loadModel('phase_3.5/models/props/BR_sky.bam') self.sky.reparentTo(render) self.sky.setZ(-40) self.sky.setFogOff() self.arena = loader.loadModel('phase_4/models/minigames/dodgeball_arena.egg') self.arena.reparentTo(render) self.arena.setScale(0.75) self.arena.find('**/team_divider').setBin('ground', 18) self.arena.find('**/floor').setBin('ground', 18) self.arena.find('**/team_divider_coll').setCollideMask(CIGlobals.FloorBitmask) for data in DistributedDodgeballGame.TreeData: code = data[0] pos = data[1] tree = self.__getSnowTree(code) tree.reparentTo(self.arena) tree.setPos(pos) self.trees.append(tree) for i in xrange(len(DistributedDodgeballGame.SnowballData)): snowdata = DistributedDodgeballGame.SnowballData[i] snowball = Snowball(self, i) snowball.load() snowball.reparentTo(render) snowball.setPos(snowdata) self.snowballs.append(snowball) self.snow = ParticleLoader.loadParticleEffect('phase_8/etc/snowdisk.ptf') self.snow.setPos(0, 0, 5) self.snowRender = self.arena.attachNewNode('snowRender') self.snowRender.setDepthWrite(0) self.snowRender.setBin('fixed', 1) self.snow.start(camera, self.snowRender) self.fog = Fog('snowFog') self.fog.setColor(0.486, 0.784, 1) self.fog.setExpDensity(0.003) render.setFog(self.fog) def throw(self, snowballIndex, p): snowball = self.snowballs[snowballIndex] snowball.throw(p) def snowballPickup(self, snowballIndex, pickerUpperAvId): remoteAv = self.getRemoteAvatar(pickerUpperAvId) if remoteAv: snowball = self.snowballs[snowballIndex] snowball.pickup(remoteAv) def deleteWorld(self): if self.redScoreLbl: self.redScoreLbl.destroy() self.redScoreLbl = None if self.blueScoreLbl: self.blueScoreLbl.destroy() self.blueScoreLbl = None for snowball in self.snowballs: snowball.removeNode() self.snowballs = [] for tree in self.trees: tree.removeNode() self.trees = [] if self.snow: self.snow.cleanup() self.snow = None if self.snowRender: self.snowRender.removeNode() self.snowRender = None self.fog = None if self.sky: self.sky.removeNode() self.sky = None if self.arena: self.arena.removeNode() self.arena = None render.clearFog() return def enterPlay(self): self.createTimer() self.redScoreLbl.show() self.blueScoreLbl.show() self.firstPerson.camFSM.request('unfrozen') self.arena.find('**/' + self.Team2OtherBarrier[self.team]).stash() def exitPlay(self): self.firstPerson.crosshair.destroy() self.firstPerson.crosshair = None self.firstPerson.camFSM.request('off') DistributedToonFPSGame.exitPlay(self) return def enterCountdown(self): self.firstPerson.start() self.firstPerson.disableMouse() self.infoText.setText(DistributedDodgeballGame.GetSnowBalls) self.countdownText = getGameText() self.countdownIval = Parallel(Sequence(Func(self.countdownText.setText, '5'), getCountdownIval(self.countdownText), Func(self.countdownText.setText, '4'), getCountdownIval(self.countdownText), Func(self.countdownText.setText, '3'), getCountdownIval(self.countdownText), Func(self.countdownText.setText, '2'), getCountdownIval(self.countdownText), Func(self.countdownText.setText, '1'), getCountdownIval(self.countdownText)), getAlertPulse(self.infoText), name='COUNTDOWNIVAL') self.countdownIval.setDoneEvent(self.countdownIval.getName()) self.acceptOnce(self.countdownIval.getDoneEvent(), self.__handleCountdownDone) self.countdownIval.start() def __handleCountdownDone(self): self.fsm.request('play') def exitCountdown(self): if hasattr(self, 'countdownText'): self.countdownText.destroy() del self.countdownText if hasattr(self, 'countdownIval'): self.ignore(self.countdownIval.getDoneEvent()) self.countdownIval.finish() del self.countdownIval def enterScrollBy(self): BLUE_START_POS = Point3(-20, 0, 4) BLUE_END_POS = Point3(20, 0, 4) BLUE_HPR = Vec3(0, 0, 0) RED_START_POS = Point3(20, 0, 4) RED_END_POS = Point3(-20, 0, 4) RED_HPR = Vec3(180, 0, 0) self.playMinigameMusic() self.scrollBySeq = Sequence(Func(camera.setHpr, BLUE_HPR), LerpPosInterval(camera, duration=5.0, pos=BLUE_END_POS, startPos=BLUE_START_POS, blendType='easeOut'), Func(base.transitions.fadeOut, 0.4), Wait(0.5), Func(base.transitions.fadeIn, 0.4), Func(camera.setHpr, RED_HPR), LerpPosInterval(camera, duration=5.0, pos=RED_END_POS, startPos=RED_START_POS, blendType='easeOut'), name='SCROLLBYSEQ') self.scrollBySeq.setDoneEvent(self.scrollBySeq.getName()) self.acceptOnce(self.scrollBySeq.getDoneEvent(), self.__handleScrollByDone) self.scrollBySeq.start() def __handleScrollByDone(self): self.fsm.request('countdown') def exitScrollBy(self): if self.scrollBySeq: self.ignore(self.scrollBySeq.getDoneEvent()) self.scrollBySeq.finish() self.scrollBySeq = None return def allPlayersReady(self): self.fsm.request('scrollBy') def chooseUrTeam(self): self.fsm.request('chooseTeam') def enterChooseTeam(self): self.makeSelectionGUI() def acceptedIntoTeam(self, spawnPoint): TeamMinigame.acceptedIntoTeam(self) self.sendUpdate('readyToStart') self.fsm.request('waitForOthers') pos, hpr = self.spawnPointsByTeam[self.team][spawnPoint] base.localAvatar.setPos(pos) base.localAvatar.setHpr(hpr) def exitChooseTeam(self): self.destroySelectionGUI() def announceGenerate(self): DistributedToonFPSGame.announceGenerate(self) base.camLens.setMinFov(CIGlobals.GunGameFOV / (4.0 / 3.0)) self.load() def disable(self): base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4.0 / 3.0)) self.fsm.requestFinalState() self.deleteWorld() self.trees = None self.snowballs = None self.spawnPointsByTeam = None if self.firstPerson: self.firstPerson.reallyEnd() self.firstPerson.cleanup() self.firstPerson = None self.scrollBySeq = None self.winnerMusic = None self.loserMusic = None self.danceSound = None self.infoText = None base.localAvatar.setWalkSpeedNormal() DistributedToonFPSGame.disable(self) return
class Suit(Avatar): notify = directNotify.newCategory('Suit') audio3d = Audio3DManager(base.sfxManagerList[0], camera) audio3d.setDistanceFactor(25) audio3d.setDropOffFactor(audio3d.getDistanceFactor() / 1000) def __init__(self): Avatar.__init__(self) self.dept = None self.suit = None self.head = None self.headModel = None self.variant = None self.handColor = None self.voice = None self.chat = None self.chatDial = None self.shadow = None self.propeller = None self.smallExp = None self.largeExp = None self.explosion = None self.hasSpawned = False self.suitTrack = None self.timestampAnimTrack = None self.propellerSounds = {} self.healthBar = None self.healthBarGlow = None self.condition = 0 self.avatarType = CIGlobals.Suit self.suitPlan = None self.animFSM = ClassicFSM('Suit', [ State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('die', self.enterDie, self.exitDie), State('win', self.enterWin, self.exitWin), State('attack', self.enterAttack, self.exitAttack), State('flail', self.enterFlail, self.exitFlail), State('flyDown', self.enterFlyDown, self.exitFlyDown), State('flyAway', self.enterFlyAway, self.exitFlyAway), State('flyNeutral', self.enterFlyNeutral, self.exitFlyNeutral), State('trayWalk', self.enterTrayWalk, self.exitTrayWalk), State('trayNeutral', self.enterTrayNeutral, self.exitTrayNeutral) ], 'off', 'off') self.animFSM.enterInitialState() self.initializeBodyCollisions() def getNametagJoints(self): return [] # BEGIN STATES def enterOff(self, ts=0): self.anim = None return def exitOff(self): pass def exitGeneral(self): self.stop() def enterTrayWalk(self, ts=0): self.show() self.loop('tray-walk') def exitTrayWalk(self): self.exitGeneral() def enterTrayNeutral(self, ts=0): self.loop('tray-neutral') def exitTrayNeutral(self): self.stop() def enterNeutral(self, ts=0): self.show() self.loop("neutral") def exitNeutral(self): self.exitTimestampAnimTrack() self.exitGeneral() def enterWalk(self, ts=0): self.show() self.loop("walk") self.disableShadowRay() def exitWalk(self): self.exitTimestampAnimTrack() self.exitGeneral() self.enableShadowRay() def enterFlail(self, ts=0): self.pingpong('flail', fromFrame=30, toFrame=35) def exitFlail(self): self.stop() def exitTimestampAnimTrack(self): if self.timestampAnimTrack: self.timestampAnimTrack.pause() self.timestampAnimTrack = None def enterAttack(self, attack, target, ts=0): self.show() if hasattr(self, 'uniqueName'): doneEvent = self.uniqueName('suitAttackDone') else: doneEvent = 'suitAttackDone' self.suitAttackState = SuitAttacks(doneEvent, self, target) self.suitAttackState.load(attack) self.suitAttackState.enter(ts) self.headsUp(target) self.acceptOnce(doneEvent, self.handleSuitAttackDone) def handleSuitAttackDone(self): self.exitAttack() def exitAttack(self): if hasattr(self, 'uniqueName'): self.ignore(self.uniqueName('suitAttackDone')) else: self.ignore('suitAttackDone') if hasattr(self, 'suitAttackState'): self.suitAttackState.exit() if hasattr(self, 'suitAttackState'): self.suitAttackState.unload() if hasattr(self, 'suitAttackState'): del self.suitAttackState def interruptAttack(self): if hasattr(self, 'suitAttackState'): self.suitAttackState.currentAttack.interruptAttack() self.clearChatbox() def handleWeaponTouch(self): if hasattr(self, 'suitAttackState'): currentAttack = self.suitAttackState.currentAttack if hasattr(currentAttack, 'handleWeaponTouch'): currentAttack.handleWeaponTouch() def enterFlyNeutral(self, ts=0): self.disableRay() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['neutral'] sfx.setLoop(True) base.playSfx(sfx, node=self) self.propeller.loop('chan', fromFrame=0, toFrame=3) self.setPlayRate(0.8, 'land') self.pingpong('land', fromFrame=0, toFrame=10) def exitFlyNeutral(self): self.cleanupPropeller() def enterFlyDown(self, ts=0): self.disableRay() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['in'] base.playSfx(sfx, node=self) groundF = 28 dur = self.getDuration('land') fr = self.getFrameRate('land') if fr: animTimeInAir = groundF / fr else: animTimeInAir = groundF impactLength = dur - animTimeInAir timeTillLanding = 6.5 - impactLength waitTime = timeTillLanding - animTimeInAir lastSpinFrame = 8 propDur = self.propeller.getDuration('chan') fr = self.propeller.getFrameRate('chan') spinTime = lastSpinFrame / fr openTime = (lastSpinFrame + 1) / fr if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyDown') else: name = 'enterFlyDown' animTrack = Sequence(Func(self.pose, 'land', 0), Wait(waitTime), ActorInterval(self, 'land', duration=dur)) propTrack = Parallel( SoundInterval(sfx, duration=waitTime + dur, node=self), Sequence( ActorInterval(self.propeller, 'chan', constrainedLoop=1, duration=waitTime + spinTime, startTime=0.0, endTime=spinTime), ActorInterval(self.propeller, 'chan', duration=propDur - openTime, startTime=openTime))) self.suitTrack = Parallel(animTrack, propTrack, name=self.taskName('flyDown')) if not self.hasSpawned: self.show() fadeInTrack = Sequence( Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 1), startColorScale=VBase4(1, 1, 1, 0)), Func(self.clearColorScale), Func(self.clearTransparency)) self.hasSpawned = True self.suitTrack.append(fadeInTrack) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyDown) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) def exitFlyDown(self): self.initializeRay(self.avatarType, 2) if self.suitTrack != None: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.exitGeneral() self.cleanupPropeller() def enterFlyAway(self, ts=0, doFadeOut=0): self.show() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['out'] if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyAway') else: name = 'enterFlyAway' dur = self.getDuration('land') actInt = ActorInterval(self, 'land', loop=0, startTime=dur, endTime=0.0) lastSpinFrame = 8 propDur = self.propeller.getDuration('chan') fr = self.propeller.getFrameRate('chan') spinTime = lastSpinFrame / fr openTime = (lastSpinFrame + 1) / fr propTrack = Parallel( SoundInterval(sfx, node=self), Sequence( Func(self.propeller.show), ActorInterval(self.propeller, 'chan', endTime=openTime, startTime=propDur), ActorInterval(self.propeller, 'chan', constrainedLoop=1, duration=propDur - openTime, startTime=spinTime, endTime=0.0))) self.suitTrack = Parallel(actInt, propTrack, name=self.taskName('trackName')) if doFadeOut: fadeOut = Sequence( Wait(4.0), Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, hidden)) self.suitTrack.append(fadeOut) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyAway) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) self.disableRay() def exitFlyAway(self): if self.suitTrack: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.cleanupPropeller() self.exitGeneral() def enterDie(self, ts=0): self.show() self.generateCog(isLose=1) self.nametag.clearChatText() self.deleteNameTag() deathSound = base.audio3d.loadSfx( "phase_3.5/audio/sfx/Cog_Death_Full.ogg") base.audio3d.attachSoundToObject(deathSound, self) trackName = self.uniqueName('enterDie') smallGears = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosionSmall.ptf') smallGears.getParticlesNamed('particles-1').setPoolSize(30) singleGear = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosion.ptf') singleGear.getParticlesNamed('particles-1').setPoolSize(1) smallGearExplosion = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosion.ptf') smallGearExplosion.getParticlesNamed('particles-1').setPoolSize(10) bigGearExplosion = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosionBig.ptf') bigGearExplosion.getParticlesNamed('particles-1').setPoolSize(30) smallGears.setDepthWrite(False) singleGear.setDepthWrite(False) smallGearExplosion.setDepthWrite(False) bigGearExplosion.setDepthWrite(False) self.smallGears = smallGears self.smallGears.setPos(self.find('**/joint_head').getPos() + (0, 0, 2)) self.singleGear = singleGear self.smallGearExp = smallGearExplosion self.bigGearExp = bigGearExplosion gearTrack = Sequence(Wait(0.7), Func(self.doSingleGear), Wait(1.5), Func(self.doSmallGears), Wait(3.0), Func(self.doBigExp)) self.suitTrack = Parallel(Sequence( Wait(0.8), SoundInterval(deathSound, node=self, duration=deathSound.length() / 2)), Sequence(Wait(0.7), Func(self.doSingleGear), Wait(4.3), Func(self.suitExplode), Wait(1.0), Func(self.disableBodyCollisions), Func(self.__cleanupExplosion)), gearTrack, Sequence( ActorInterval(self, 'lose', duration=6), Func(self.getGeomNode().hide)), name=trackName) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getName(), self.exitDie) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, trackName) self.suitTrack.start(ts) del deathSound def doSingleGear(self): self.singleGear.start(self.getGeomNode()) def doSmallGears(self): self.smallGears.start(self.getGeomNode()) def doSmallExp(self): self.smallGearExp.start(self.getGeomNode()) def doBigExp(self): self.bigGearExp.start(self.getGeomNode()) def suitExplode(self): self.explosion = loader.loadModel( 'phase_3.5/models/props/explosion.bam') self.explosion.setScale(0.5) self.explosion.reparentTo(render) self.explosion.setBillboardPointEye() if self.variant == Variant.SKELETON: self.explosion.setPos( self.getPart('body').find('**/joint_head').getPos(render) + (0, 0, 2)) else: self.explosion.setPos(self.headModel.getPos(render) + (0, 0, 2)) def __cleanupExplosion(self): if self.explosion: self.explosion.removeNode() self.explosion = None def exitDie(self): if self.suitTrack != None: self.ignore(self.suitTrack.getName()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None if hasattr(self, 'singleGear'): self.singleGear.cleanup() del self.singleGear if hasattr(self, 'smallGears'): self.smallGears.cleanup() del self.smallGears if hasattr(self, 'smallGearExp'): self.smallGearExp.cleanup() del self.smallGearExp if hasattr(self, 'bigGearExp'): self.bigGearExp.cleanup() del self.bigGearExp self.__cleanupExplosion() def enterWin(self, ts=0): self.play('win') def exitWin(self): self.exitGeneral() # END STATES def generate(self, suitPlan, variant, voice=None, hideFirst=True): self.suitPlan = suitPlan self.suit = suitPlan.getSuitType() self.head = suitPlan.getHead() self.dept = suitPlan.getDept() self.handColor = suitPlan.getHandColor() self.variant = variant self.setVoice(voice) self.generateCog() if hideFirst: self.hide() def __blinkRed(self, task): self.healthBar.setColor(SuitGlobals.healthColors[3], 1) self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[3], 1) if self.condition == 5: self.healthBar.setScale(1.17) return Task.done def __blinkGray(self, task): if not self.healthBar: return self.healthBar.setColor(SuitGlobals.healthColors[4], 1) self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[4], 1) if self.condition == 5: self.healthBar.setScale(1.0) return Task.done def generateHealthBar(self): self.removeHealthBar() button = loader.loadModel('phase_3.5/models/gui/matching_game_gui.bam' ).find('**/minnieCircle') button.setScale(3.0) button.setH(180) button.setColor(SuitGlobals.healthColors[0]) chestNull = self.find('**/def_joint_attachMeter') if chestNull.isEmpty(): chestNull = self.find('**/joint_attachMeter') button.reparentTo(chestNull) self.healthBar = button self.healthBarGlow = loader.loadModel( 'phase_3.5/models/props/glow.bam') self.healthBarGlow.reparentTo(self.healthBar) self.healthBarGlow.setScale(0.28) self.healthBarGlow.setPos(-0.005, 0.01, 0.015) self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[0]) button.flattenLight() self.condition = 0 if hasattr(self, 'getHealth'): self.updateHealthBar(self.getHealth()) def updateHealthBar(self, hp): if not self.healthBar: return if hp > self.health: self.health = hp health = 0.0 try: health = float(hp) / float(self.maxHealth) except: pass if health > 0.95: condition = 0 elif health > 0.7: condition = 1 elif health > 0.3: condition = 2 elif health > 0.05: condition = 3 elif health > 0.0: condition = 4 else: condition = 5 if self.condition != condition: if condition == 4: blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.75), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) elif condition == 5: if self.condition == 4: taskMgr.remove(self.taskName('blink-task')) blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.25), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) else: self.healthBar.setColor(SuitGlobals.healthColors[condition], 1) self.healthBarGlow.setColor( SuitGlobals.healthGlowColors[condition], 1) self.condition = condition def removeHealthBar(self): if self.healthBar: self.healthBar.removeNode() self.healthBar = None if self.condition == 4 or self.condition == 5: taskMgr.remove(self.taskName('blink-task')) self.healthCondition = 0 return def initializeLocalCollisions(self, name): self.notify.info('Initializing Local Collisions!') Avatar.initializeLocalCollisions(self, 1, 3, name) def initializeBodyCollisions(self): self.notify.info('Initializing Body Collisions!') Avatar.initializeBodyCollisions(self, self.avatarType, 6, 2) self.initializeRay(self.avatarType, 2) def hideSuit(self): self.hide() def showSuit(self): self.show() fadeIn = Sequence( Func(self.setTransparency, 1), self.colorScaleInterval(0.6, colorScale=Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, render)) fadeIn.start() def generateCog(self, isLose=0): self.cleanup() if not isLose: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.loadModel( 'phase_5/models/char/cog%s_robot-zero.bam' % (str(self.suit)), 'body') else: self.loadModel( 'phase_3.5/models/char/suit%s-mod.bam' % (str(self.suit)), 'body') animations = SuitGlobals.animations anims = {} for anim in animations: if not self.suit in anim.getSuitTypes(): continue path = 'phase_%s/models/char/suit%s-%s.bam' % ( anim.getPhase(), self.suit, anim.getFile()) anims[anim.getName()] = path self.loadAnims(anims, 'body') self.generateHealthBar() self.generatePropeller() else: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.loadModel( 'phase_5/models/char/cog%s_robot-lose-mod.bam' % (str(self.suit)), 'body') else: self.loadModel( 'phase_4/models/char/suit%s-lose-mod.bam' % (str(self.suit)), 'body') self.loadAnims( { 'lose': 'phase_4/models/char/suit%s-lose.bam' % (str(self.suit)) }, 'body') if self.variant != Variant.SKELETON: self.headModel = self.head.generate() self.headModel.reparentTo(self.find('**/joint_head')) if self.suitPlan.getName() == SuitGlobals.VicePresident: self.headModel.setScale(0.35) self.headModel.setHpr(270, 0, 270) self.headModel.setZ(-0.10) self.headModel.loop('neutral') self.setClothes() self.setAvatarScale(self.suitPlan.getScale() / SuitGlobals.scaleFactors[self.suit]) self.setHeight(self.suitPlan.getHeight()) self.setupNameTag() Avatar.initShadow(self) def cleanup(self): self.cleanupPropeller() self.clearChatbox() if self.shadow: self.deleteShadow() if self.getPart('body'): self.removePart('body') if self.headModel: self.headModel.removeNode() self.headModel = None self.timestampAnimTrack = None def generatePropeller(self): self.cleanupPropeller() self.propeller = Actor( 'phase_4/models/props/propeller-mod.bam', {'chan': 'phase_4/models/props/propeller-chan.bam'}) self.propeller.reparentTo(self.find('**/joint_head')) self.propellerSounds['in'] = self.audio3d.loadSfx( SuitGlobals.propellerInSfx) self.propellerSounds['out'] = self.audio3d.loadSfx( SuitGlobals.propellerOutSfx) self.propellerSounds['neutral'] = self.audio3d.loadSfx( SuitGlobals.propellerNeutSfx) for sound in self.propellerSounds.values(): self.audio3d.attachSoundToObject(sound, self.propeller) def cleanupPropeller(self): for sound in self.propellerSounds.values(): self.audio3d.detachSound(sound) sound.stop() self.propellerSounds = {} if self.propeller: self.propeller.cleanup() self.propeller = None def setVoice(self, voice): if not voice: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.voice = Voice.SKELETON else: self.voice = Voice.NORMAL else: self.voice = voice def setClothes(self): if self.variant == Variant.SKELETON: parts = self.findAllMatches('**/pPlane*') for partNum in range(0, parts.getNumPaths()): bb = parts.getPath(partNum) bb.setTwoSided(1) tie = loader.loadTexture('phase_5/maps/cog_robot_tie_%s.jpg' % self.dept.getTie()) tie.setMinfilter(Texture.FTLinearMipmapLinear) tie.setMagfilter(Texture.FTLinear) self.find('**/tie').setTexture(tie, 1) else: prefix = 'phase_3.5/maps/' + self.dept.getClothingPrefix( ) + '_%s.jpg' if self.variant == Variant.WAITER: prefix = 'phase_3.5/maps/waiter_m_%s.jpg' self.find('**/legs').setTexture(loader.loadTexture(prefix % 'leg'), 1) self.find('**/arms').setTexture( loader.loadTexture(prefix % 'sleeve'), 1) self.find('**/torso').setTexture( loader.loadTexture(prefix % 'blazer'), 1) self.find('**/hands').setColor(self.handColor) def setName(self, nameString, charName): Avatar.setName(self, nameString, avatarType=self.avatarType, charName=charName, createNow=1) def setupNameTag(self, tempName=None): Avatar.setupNameTag(self, tempName=tempName) if self.nametag: if self.level > 0: self.nametag.setText(self.nametag.getText() + '\n%s\nLevel %s' % (self.dept.getName(), self.level)) else: self.nametag.setText(self.nametag.getText() + '\n%s' % (self.dept.getName())) def setChat(self, chat): self.clearChatbox() Avatar.setChat(self, chat) self.chat = chat chatDial = None questionDial = self.voice.getSoundFile('question') question02Dial = None gruntDial = self.voice.getSoundFile('grunt') statementDial = self.voice.getSoundFile('statement') if self.voice == Voice.NORMAL: question02Dial = self.voice.getSoundFile('question_2') if '!' in self.chat: chatDial = self.audio3d.loadSfx(gruntDial) elif '?' in self.chat: questionDials = [questionDial] if self.voice == Voice.NORMAL: questionDials.append(question02Dial) chatDial = self.audio3d.loadSfx(random.choice(questionDials)) else: chatDial = self.audio3d.loadSfx(statementDial) self.chatDial = chatDial if self.variant == Variant.SKELETON: self.audio3d.attachSoundToObject(self.chatDial, self) else: self.audio3d.attachSoundToObject(self.chatDial, self.headModel) base.playSfx(self.chatDial, node=self) def clearChatbox(self): self.clearChat() self.chat = None if self.chatDial: self.chatDial.stop() self.chatDial = None def getDept(self): return self.dept def getVariant(self): return self.variant def disable(self): if self.suitTrack: self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.animFSM.requestFinalState() self.cleanup() Avatar.disable(self) def delete(self): Avatar.delete(self) self.cleanup()
class DistributedTutorial(DistributedObject): notify = directNotify.newCategory('DistributedTutorial') GUIDE_NAME = 'Professor Prepostera' GUIDE_START_POS = (5, 10, -0.5) GUIDE_WATCH_POS = (12.4, 27.92, 0) GUIDE_WATCH_HPR = (41.63, 0, 0) GUIDE_INTRO_SPEECH = ['Hey, looks like you made it!', 'So, welcome to OToontown.', 'OToontown is short for Old Toontown, or Toontown from the past.', 'Not long ago, Toons used to live present day Toontown.', 'Unfortunately, the Cogs planned a mega-invasion that was sure to be a complete takeover of Toontown and make all Toons go sad for good.', "There was no way we could have let that happen, so we built a time machine, and sent every Toon back in time to OToontown, where Cogs didn't exist yet.", 'The Cogs completely took over present day Toontown, and turned it into what they wanted it to be - a business metropolis.', 'Toons happily live and play in OToontown now, but we want to learn about present day Toontown...', ' ...or as we now call it, CogTropolis.', "We've built time machines that send Toons back to CogTropolis to fight Cogs and to see what the Cogs have done.", "We know that the Cogs took over Toontown and turned it into a grey business city, but we don't know how they did it.", 'Shopkeepers around OToontown will reward you for finding evidence that may help solve the mystery of how the Cogs turned Toontown into CogTropolis.', 'Before you are able to head to CogTropolis, you need to be trained for battle.', 'The Cogs have become much more skilled battlers and no longer wait for you to throw a gag before attacking you.', 'This is much more difficult for Toons, and it may take some time to get used to.', "I'm going to give you 4 gags to start...", 'A Toon-Up megaphone, a cupcake, a fruit pie slice, and a cream pie slice.', 'Equip Gags in your loadout to use by pressing the corresponding key on your keyboard.', 'You can use or throw the Gag that you have equipped by pressing the Delete key...', ' ...or by pressing the Throw Gag button at the top of your screen.', 'Also, use the Arrow Keys on your keyboard to move, and press CTRL to jump.', "I'm going to summon one of our dummy bots for you to practice battling.", "Click your mouse when you're ready."] GUIDE_PT2_INFO = ["Now it'll get a tad bit tougher.", 'This next dummy bot will be walking around.', 'This will test your aiming skills.', "Click your mouse when you're ready."] GUIDE_PT3_INFO = ['This final dummy bot will walk around and try to attack you at times.', 'Defeat this Cog, and you should be ready to go.'] GUIDE_DONE = ['Wow, you did great!', "You're definitely ready for battle in CogTropolis.", 'Click your mouse to head to OToontown.'] GUIDE_START_TRAINING = "Alright! Let's do this!" def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM.ClassicFSM('TutorialFSM', [State.State('off', self.enterOff, self.exitOff), State.State('newPlayerEmerge', self.enterPlayerEmerge, self.exitPlayerEmerge, ['off', 'introSpeech']), State.State('introSpeech', self.enterGuideIntroSpeech, self.exitGuideIntroSpeech, ['off', 'introSpeech2Training']), State.State('introSpeech2Training', self.enterIntroSpeech2Training, self.exitIntroSpeech2Training, ['off', 'training1']), State.State('training1', self.enterTrainingPT1, self.exitTrainingPT1, ['off', 'training2info']), State.State('training2info', self.enterTraining2Info, self.exitTraining2Info, ['off', 'training2']), State.State('training2', self.enterTrainingPT2, self.exitTrainingPT2, ['off', 'training3info']), State.State('training3info', self.enterTraining3Info, self.exitTraining3Info, ['off', 'training3']), State.State('training3', self.enterTrainingPT3, self.exitTrainingPT3, ['off', 'trainingDone']), State.State('trainingDone', self.enterTrainingDone, self.exitTrainingDone, ['off', 'leaveTutorial']), State.State('leaveTutorial', self.enterLeaveTutorial, self.exitLeaveTutorial, ['off'])], 'off', 'off') self.fsm.enterInitialState() self.dnaStore = DNAStorage() self.streetGeom = None self.sky = None self.skyUtil = SkyUtil() self.guide = None self.music = None self.battleMusic = None self.playerCamPos = None self.playerCamHpr = None return def enterOff(self): pass def exitOff(self): pass def introStuff(self): base.localAvatar.getGeomNode().hide() base.localAvatar.setPos(0, 0, -0.5) base.localAvatar.setHpr(0, 0, 0) self.guide.setPos(self.GUIDE_START_POS) self.guide.headsUp(base.localAvatar) base.localAvatar.attachCamera() def enterPlayerEmerge(self): self.introStuff() self.guide.loop('neutral') base.transitions.irisIn() base.taskMgr.doMethodLater(1.0, self.__playerEmerge, 'playerEmergeTask') def __playerEmerge(self, task): base.localAvatar.setAnimState('teleportIn', callback=self.__playerEmergeFinished) return Task.done def __playerEmergeFinished(self): base.localAvatar.setAnimState('neutral') self.fsm.request('introSpeech') def exitPlayerEmerge(self): base.localAvatar.detachCamera() base.taskMgr.remove('playerEmergeTask') base.transitions.noTransitions() def enterGuideIntroSpeech(self): base.localAvatar.attachCamera() renderPos = base.camera.getPos(render) renderHpr = base.camera.getHpr(render) base.localAvatar.detachCamera() endPos = base.localAvatar.getPos(render) + (0, 0, 4) base.camera.setPos(endPos) base.camera.lookAt(self.guide, 0, 0, 3) endHpr = base.camera.getHpr(render) base.camera.setPos(renderPos) base.camera.setHpr(renderHpr) self.chatIndex = -1 self.doNextIntroSpeech() self.camMoveTrack = Sequence(Parallel(LerpPosInterval(base.camera, duration=3.0, pos=endPos, startPos=renderPos, blendType='easeOut'), LerpQuatInterval(base.camera, duration=3.0, hpr=endHpr, startHpr=renderHpr, blendType='easeOut')), Func(base.localAvatar.getGeomNode().hide)) self.camMoveTrack.start() def __finishedReadingGuideIntroSpeech(self): self.guide.autoClearChat = True self.guide.setChat(self.GUIDE_START_TRAINING) self.fsm.request('introSpeech2Training') def doNextIntroSpeech(self): self.chatIndex += 1 if self.chatIndex >= len(self.GUIDE_INTRO_SPEECH): self.__finishedReadingGuideIntroSpeech() return self.guide.setChat(self.GUIDE_INTRO_SPEECH[self.chatIndex]) Sequence(Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.doNextIntroSpeech)).start() def exitGuideIntroSpeech(self): self.camMoveTrack.finish() base.localAvatar.getGeomNode().show() del self.camMoveTrack del self.chatIndex def enterIntroSpeech2Training(self): startCamPos = base.camera.getPos(render) startCamHpr = base.camera.getHpr(render) base.camera.setPosHpr(0, 0, 0, 0, 0, 0) base.localAvatar.attachCamera() endCamPos = base.camera.getPos(render) endCamHpr = base.camera.getHpr(render) base.localAvatar.detachCamera() startHpr = self.guide.getHpr(render) self.guide.headsUp(self.GUIDE_WATCH_POS) endHpr = self.guide.getHpr(render) self.guide.loop('run') self.camMoveIval = Parallel(LerpPosInterval(base.camera, duration=2.0, pos=endCamPos, startPos=startCamPos, blendType='easeOut'), LerpQuatInterval(base.camera, duration=2.0, hpr=endCamHpr, startHpr=startCamHpr, blendType='easeOut'), Sequence(LerpPosInterval(self.guide, duration=2.0, pos=self.GUIDE_WATCH_POS, startPos=self.guide.getPos(render)), Func(self.guide.loop, 'walk'), LerpHprInterval(self.guide, duration=1.0, hpr=self.GUIDE_WATCH_HPR, startHpr=endHpr), Func(self.guide.loop, 'neutral')), LerpHprInterval(self.guide, duration=1.0, hpr=endHpr, startHpr=startHpr)) self.camMoveIval.setDoneEvent('introSpeech2TrainingDone') self.acceptOnce('introSpeech2TrainingDone', self.__handleIS2TDone) self.camMoveIval.start() def __handleIS2TDone(self): self.fsm.request('training1') def exitIntroSpeech2Training(self): self.ignore('introSpeech2TrainingDone') self.camMoveIval.finish() del self.camMoveIval def enterTrainingPT1(self): self.music.stop() base.playMusic(self.battleMusic, volume=0.8, looping=1) self.sendUpdate('makeSuit', [0]) base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.startBlink() base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.collisionsOn() base.localAvatar.enableAvatarControls() base.localAvatar.enablePies(1) Whisper().createSystemMessage('This should be pretty simple. Just throw a gag at this dummy bot to defeat it.') def suitNoHealth(self, index): if index == 0: Whisper().createSystemMessage('Good job, {0}!'.format(base.localAvatar.getName())) elif index == 1: Whisper().createSystemMessage("Wow, you're doing very well!") def suitExploded(self, index): if index == 0: Whisper().createSystemMessage('Pick up the jellybean that he dropped. You can use them to buy more gags for your Toon.') self.battleMusic.stop() base.playMusic(self.music, looping=1, volume=0.8) def pickedUpJellybean(self): if self.fsm.getCurrentState().getName() == 'training1': self.fsm.request('training2info') elif self.fsm.getCurrentState().getName() == 'training2': self.fsm.request('training3info') elif self.fsm.getCurrentState().getName() == 'training3': self.fsm.request('trainingDone') def exitTrainingPT1(self): base.localAvatar.lastState = None base.localAvatar.disableAvatarControls() base.localAvatar.detachCamera() base.localAvatar.stopSmartCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.stopBlink() base.localAvatar.collisionsOff() base.localAvatar.controlManager.placeOnFloor() base.localAvatar.disablePies() return def enterTraining2Info(self): base.camera.setPos(3.09, 37.16, 3.93) base.camera.setHpr(225, 0, 0) self.guide.autoClearChat = False self.chatIndex = -1 self.doNextTraining2Speech() def __finishedReadingGuideTraining2Speech(self): self.guide.autoClearChat = True self.guide.clearChat() self.fsm.request('training2') def doNextTraining2Speech(self): self.chatIndex += 1 if self.chatIndex >= len(self.GUIDE_PT2_INFO): self.__finishedReadingGuideTraining2Speech() return self.guide.setChat(self.GUIDE_PT2_INFO[self.chatIndex]) Sequence(Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.doNextTraining2Speech)).start() def exitTraining2Info(self): base.camera.setPosHpr(0, 0, 0, 0, 0, 0) del self.chatIndex def enterTrainingPT2(self): self.music.stop() base.playMusic(self.battleMusic, volume=0.8, looping=1) self.sendUpdate('makeSuit', [1]) base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.startBlink() base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.collisionsOn() base.localAvatar.enableAvatarControls() base.localAvatar.enablePies(1) def exitTrainingPT2(self): base.localAvatar.lastState = None base.localAvatar.disableAvatarControls() base.localAvatar.detachCamera() base.localAvatar.stopSmartCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.stopBlink() base.localAvatar.collisionsOff() base.localAvatar.controlManager.placeOnFloor() base.localAvatar.disablePies() return def enterTraining3Info(self): base.camera.setPos(3.09, 37.16, 3.93) base.camera.setHpr(225, 0, 0) self.guide.autoClearChat = False self.chatIndex = -1 self.doNextTraining3Speech() def __finishedReadingGuideTraining3Speech(self): self.guide.autoClearChat = True self.guide.clearChat() self.fsm.request('training3') def doNextTraining3Speech(self): self.chatIndex += 1 if self.chatIndex >= len(self.GUIDE_PT3_INFO): self.__finishedReadingGuideTraining3Speech() return self.guide.setChat(self.GUIDE_PT3_INFO[self.chatIndex]) Sequence(Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.doNextTraining3Speech)).start() def exitTraining3Info(self): base.camera.setPosHpr(0, 0, 0, 0, 0, 0) del self.chatIndex def enterTrainingPT3(self): self.music.stop() base.playMusic(self.battleMusic, volume=0.8, looping=1) self.sendUpdate('makeSuit', [2]) base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.startBlink() base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.collisionsOn() base.localAvatar.enableAvatarControls() base.localAvatar.enablePies(1) def exitTrainingPT3(self): base.localAvatar.lastState = None base.localAvatar.disableAvatarControls() base.localAvatar.detachCamera() base.localAvatar.stopSmartCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.stopBlink() base.localAvatar.collisionsOff() base.localAvatar.controlManager.placeOnFloor() base.localAvatar.disablePies() return def enterTrainingDone(self): base.camera.setPos(3.09, 37.16, 3.93) base.camera.setHpr(225, 0, 0) self.guide.autoClearChat = False self.chatIndex = -1 self.doNextTrainingDoneSpeech() def __finishedReadingGuideTrainingDoneSpeech(self): self.guide.autoClearChat = True self.guide.clearChat() self.fsm.request('leaveTutorial') def doNextTrainingDoneSpeech(self): self.chatIndex += 1 if self.chatIndex >= len(self.GUIDE_DONE): self.__finishedReadingGuideTrainingDoneSpeech() return self.guide.setChat(self.GUIDE_DONE[self.chatIndex]) Sequence(Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.doNextTrainingDoneSpeech)).start() def exitTrainingDone(self): base.camera.setPosHpr(0, 0, 0, 0, 0, 0) del self.chatIndex def enterLeaveTutorial(self): base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.b_setAnimState('teleportOut', callback=self.__teleOutDone) def __teleOutDone(self): zoneId = CIGlobals.ToontownCentralId hoodId = CIGlobals.ToontownCentral whereName = 'playground' avId = base.localAvatar.doId loaderName = 'safeZoneLoader' self.sendUpdate('finishedTutorial') self.cr.playGame.fsm.request('quietZone', [{'zoneId': zoneId, 'hoodId': hoodId, 'where': whereName, 'how': 'teleportIn', 'avId': avId, 'shardId': None, 'loader': loaderName}]) return def exitLeaveTutorial(self): base.localAvatar.stopSmartCamera() base.localAvatar.detachCamera() def announceGenerate(self): DistributedObject.announceGenerate(self) base.transitions.fadeScreen(0.0) self.guide = Toon(base.cr) self.guide.autoClearChat = False self.guide.parseDNAStrand(NPCGlobals.NPC_DNA[self.GUIDE_NAME]) self.guide.setName(self.GUIDE_NAME) self.guide.generateToon() self.guide.startBlink() self.guide.reparentTo(render) base.localAvatar.reparentTo(render) loader.loadDNAFile(self.dnaStore, 'phase_3.5/dna/storage_tutorial.dna') node = loader.loadDNAFile(self.dnaStore, 'phase_3.5/dna/tutorial_street.dna') if node.getNumParents() == 1: self.streetGeom = NodePath(node.getParent(0)) self.streetGeom.reparentTo(hidden) else: self.streetGeom = hidden.attachNewNode(node) self.streetGeom.flattenMedium() gsg = base.win.getGsg() if gsg: self.streetGeom.prepareScene(gsg) self.streetGeom.reparentTo(render) self.streetGeom.setPos(20.5, -20, 0) self.streetGeom.setH(90) self.sky = loader.loadModel('phase_3.5/models/props/TT_sky.bam') self.skyUtil.startSky(self.sky) self.sky.reparentTo(camera) ce = CompassEffect.make(NodePath(), CompassEffect.PRot | CompassEffect.PZ) self.sky.node().setEffect(ce) self.music = base.loadMusic('phase_3.5/audio/bgm/TC_SZ.mid') base.playMusic(self.music, volume=0.8, looping=1) self.battleMusic = base.loadMusic('phase_3.5/audio/bgm/encntr_general_bg.mid') self.fsm.request('newPlayerEmerge') base.localAvatar.inTutorial = True def disable(self): self.fsm.requestFinalState() del self.fsm if self.guide: self.guide.disable() self.guide.delete() self.guide = None if self.streetGeom: self.streetGeom.removeNode() self.streetGeom = None if self.sky: self.sky.removeNode() self.sky = None if self.music: self.music.stop() self.music = None if self.battleMusic: self.battleMusic.stop() self.battleMusic = None self.dnaStore = None self.skyUtil = None base.localAvatar.inTutorial = False DistributedObject.disable(self) return
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()
class DistributedToon(Toon.Toon, DistributedAvatar, DistributedSmoothNode, DelayDeletable): def __init__(self, cr): try: self.DistributedToon_initialized return except: self.DistributedToon_initialized = 1 Toon.Toon.__init__(self, cr) DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.questManager = QuestManager.QuestManager() self.token = -1 self.ghost = 0 self.puInventory = [] self.equippedPU = -1 self.backpack = None self.animState2animId = {} self.battleMeter = None for index in range(len(self.animFSM.getStates())): self.animState2animId[self.animFSM.getStates() [index].getName()] = index self.animId2animState = { v: k for k, v in self.animState2animId.items() } self.headMeter = None self.firstTimeChangingHP = True self.quests = [] self.tier = None self.questHistory = None self.busy = 1 self.friends = None self.tutDone = 0 self.hoodsDiscovered = [] self.teleportAccess = [] self.lastHood = 0 self.defaultShard = 0 self.dmgFadeIval = None self.tunnelTrack = None return def goThroughTunnel(self, toZone, inOrOut, requestStatus=None): if self.tunnelTrack: self.ignore(self.tunnelTrack.getDoneEvent()) self.tunnelTrack.finish() self.tunnelTrack = None linkTunnel = LinkTunnel.getTunnelThatGoesToZone(toZone) if not linkTunnel: return self.tunnelTrack = Parallel( name=self.uniqueName('Place.goThroughTunnel')) if inOrOut == 0: pivotPoint = linkTunnel.inPivotPoint pivotPointNode = linkTunnel.tunnel.attachNewNode( 'tunnelPivotPoint') pivotPointNode.setPos(pivotPoint) self.stopSmooth() self.wrtReparentTo(pivotPointNode) if linkTunnel.__class__.__name__ == 'SafeZoneLinkTunnel': self.setHpr(180, 0, 0) else: self.setHpr(0, 0, 0) if base.localAvatar.doId == self.doId: doneMethod = self._handleWentInTunnel extraArgs = [requestStatus] self.walkControls.setCollisionsActive(0) camera.wrtReparentTo(linkTunnel.tunnel) currCamPos = camera.getPos() currCamHpr = camera.getHpr() tunnelCamPos = linkTunnel.camPos tunnelCamHpr = linkTunnel.camHpr self.tunnelTrack.append( LerpPosInterval(camera, duration=0.7, pos=tunnelCamPos, startPos=currCamPos, blendType='easeOut')) self.tunnelTrack.append( LerpQuatInterval(camera, duration=0.7, quat=tunnelCamHpr, startHpr=currCamHpr, blendType='easeOut')) exitSeq = Sequence(Func(self.loop, 'run')) if base.localAvatar.doId == self.doId: exitSeq.append(Wait(2.0)) exitSeq.append(Func(base.transitions.irisOut)) self.tunnelTrack.append(exitSeq) self.tunnelTrack.append( Sequence( LerpHprInterval(pivotPointNode, duration=2.0, hpr=linkTunnel.inPivotEndHpr, startHpr=linkTunnel.inPivotStartHpr), LerpPosInterval(pivotPointNode, duration=1.0, pos=(linkTunnel.inPivotEndX, pivotPointNode.getY(), pivotPointNode.getZ()), startPos=(linkTunnel.inPivotStartX, pivotPointNode.getY(), pivotPointNode.getZ())))) else: if inOrOut == 1: pivotPoint = linkTunnel.outPivotPoint pivotPointNode = linkTunnel.tunnel.attachNewNode( 'tunnelPivotPoint') pivotPointNode.setPos(pivotPoint) pivotPointNode.setHpr(linkTunnel.outPivotStartHpr) if base.localAvatar.doId == self.doId: base.localAvatar.walkControls.setCollisionsActive(0) base.localAvatar.detachCamera() camera.reparentTo(linkTunnel.tunnel) tunnelCamPos = linkTunnel.camPos tunnelCamHpr = linkTunnel.camHpr camera.setPos(tunnelCamPos) camera.setHpr(tunnelCamHpr) doneMethod = self._handleCameOutTunnel extraArgs = [] self.reparentTo(pivotPointNode) self.setHpr(linkTunnel.toonOutHpr) self.setPos(linkTunnel.toonOutPos) exitSeq = Sequence( Func(self.loop, 'run'), LerpPosInterval(pivotPointNode, duration=1.0, pos=(linkTunnel.outPivotEndX, pivotPointNode.getY(), pivotPointNode.getZ()), startPos=(linkTunnel.outPivotStartX, pivotPointNode.getY(), pivotPointNode.getZ())), LerpHprInterval(pivotPointNode, duration=2.0, hpr=linkTunnel.outPivotEndHpr, startHpr=linkTunnel.outPivotStartHpr), Func(self.wrtReparentTo, render), Func(self.startSmooth)) self.tunnelTrack.append(exitSeq) if base.localAvatar.doId == self.doId: self.tunnelTrack.setDoneEvent(self.tunnelTrack.getName()) self.acceptOnce(self.tunnelTrack.getDoneEvent(), doneMethod, extraArgs) self.tunnelTrack.start() return def setupNameTag(self, tempName=None): Toon.Toon.setupNameTag(self, tempName) self.nametag.getNametag3d().setClickEvent('toonClicked', [self.doId]) self.nametag.getNametag2d().setClickEvent('toonClicked', [self.doId]) def setDefaultShard(self, shardId): self.defaultShard = shardId def getDefaultShard(self): return self.defaultShard def doSmoothTask(self, task): self.smoother.computeAndApplySmoothPosHpr(self, self) if not hasattr(base, 'localAvatar'): return task.done if self.doId != base.localAvatar.doId: self.setSpeed(self.smoother.getSmoothForwardVelocity(), self.smoother.getSmoothRotationalVelocity(), self.smoother.getSmoothLateralVelocity()) return task.cont def setLastHood(self, zoneId): self.lastHood = zoneId def b_setLastHood(self, zoneId): self.sendUpdate('setLastHood', [zoneId]) self.setLastHood(zoneId) def getLastHood(self): return self.lastHood def setTeleportAccess(self, array): self.teleportAccess = array def getTeleportAccess(self): return self.teleportAccess def setHoodsDiscovered(self, array): self.hoodsDiscovered = array def b_setHoodsDiscovered(self, array): self.sendUpdate('setHoodsDiscovered', [array]) self.setHoodsDiscovered(array) def getHoodsDiscovered(self): return self.hoodsDiscovered def setTutorialCompleted(self, value): self.tutDone = value def getTutorialCompleted(self): return self.tutDone def setFriendsList(self, friends): self.friends = friends def getFriendsList(self): return self.friends def setBusy(self, busy): self.busy = busy def getBusy(self): return self.busy def setTier(self, tier): self.tier = tier def getTier(self): return self.tier def setQuestHistory(self, array): self.questHistory = array def getQuestHistrory(self): return self.questHistory def setQuests(self, questIds, currentObjectives, currentObjectivesProgress): self.quests = [questIds, currentObjectives, currentObjectivesProgress] self.questManager.makeQuestsFromData() def getQuests(self): return self.quests def maybeMakeHeadMeter(self): if base.localAvatar.doId != self.doId: if self.health < self.getMaxHealth(): if not self.headMeter: self.__makeHeadMeter() def __makeHeadMeter(self): self.headMeter = LaffOMeter(forRender=True) r, g, b, _ = self.getHeadColor() animal = self.getAnimal() maxHp = self.getMaxHealth() hp = self.getHealth() self.headMeter.generate(r, g, b, animal, maxHP=maxHp, initialHP=hp) self.headMeter.reparentTo(self) self.headMeter.setZ(self.getHeight() + 2) self.headMeter.setScale(0.4) self.headMeter.setBillboardAxis() self.__updateHeadMeter() def __removeHeadMeter(self): if self.headMeter: self.headMeter.disable() self.headMeter.delete() self.headMeter = None return def __updateHeadMeter(self): if self.headMeter: self.headMeter.updateMeter(self.getHealth()) def setHealth(self, health): if self.doId != base.localAvatar.doId: if not self.firstTimeChangingHP: if health < self.getMaxHealth(): if not self.headMeter: self.__makeHeadMeter() else: self.__updateHeadMeter() else: self.__removeHeadMeter() self.health = health self.firstTimeChangingHP = False def d_createBattleMeter(self): self.sendUpdate('makeBattleMeter', []) def b_createBattleMeter(self): self.makeBattleMeter() self.d_createBattleMeter() def d_cleanupBattleMeter(self): self.sendUpdate('destroyBattleMeter', []) def b_cleanupBattleMeter(self): self.destroyBattleMeter() self.d_cleanupBattleMeter() def makeBattleMeter(self): if self.getHealth() < self.getMaxHealth(): if not self.battleMeter: self.battleMeter = LaffOMeter() r, g, b, _ = self.getHeadColor() animal = self.getAnimal() maxHp = self.getMaxHealth() hp = self.getHealth() self.battleMeter.generate(r, g, b, animal, maxHP=maxHp, initialHP=hp) self.battleMeter.reparentTo(self) self.battleMeter.setZ(self.getHeight() + 5) self.battleMeter.setScale(0.5) self.battleMeter.start() def destroyBattleMeter(self): if self.battleMeter: self.battleMeter.stop() self.battleMeter.disable() self.battleMeter.delete() self.battleMeter = None return def setEquippedPU(self, index): self.equippedPU = index def getEquippedPU(self): return self.equippedPU def setPUInventory(self, array): self.puInventory = array def getPUInventory(self): return self.puInventory def setGhost(self, value): self.ghost = value if value: self.ghostOn() else: self.ghostOff() def d_setGhost(self, value): self.sendUpdate('setGhost', [value]) def b_setGhost(self, value): self.d_setGhost(value) self.setGhost(value) def getGhost(self): return self.ghost def setDNAStrand(self, dnaStrand): Toon.Toon.setDNAStrand(self, dnaStrand) self.maybeMakeHeadMeter() def d_setDNAStrand(self, dnaStrand): self.sendUpdate('setDNAStrand', [dnaStrand]) def b_setDNAStrand(self, dnaStrand): self.setDNAStrand(dnaStrand) self.d_setDNAStrand(dnaStrand) def lookAtObject(self, h, p, r, blink=1): if self.getPart('head').getHpr() == (h, p, r): return Toon.Toon.lerpLookAt(self, self.getPart('head'), tuple((h, p, r))) if blink: self.stopBlink() maxBlinks = random.randint(1, 2) numBlinks = 0 delay = 0 for blink in range(maxBlinks): if numBlinks == 0: taskMgr.add(self.doBlink, self.uniqueName('blinkOnTurn')) else: delay += 0.22 taskMgr.doMethodLater(delay, self.doBlink, self.doBlinkTaskName) numBlinks += 1 taskMgr.doMethodLater(delay, self.__startBlinkAfterLook, self.uniqueName('sBAL')) def __startBlinkAfterLook(self, task): self.startBlink() return task.done def toonUp(self): pass def b_lookAtObject(self, h, p, r, blink=1): self.d_lookAtObject(h, p, r, blink) self.lookAtObject(h, p, r, blink) def d_lookAtObject(self, h, p, r, blink=1): self.sendUpdate('lookAtObject', [h, p, r, blink]) def setChat(self, chat): chat = ChatGlobals.filterChat(chat, self.animal) Toon.Toon.setChat(self, chat) def setTarget(self, gagId, targetId): gag = self.backpack.getGagByID(gagId) target = self.cr.doId2do.get(targetId, None) gag.setTarget(target) return def trapActivate(self, gagId, avId, entityId, suitId): sender = self.cr.doId2do.get(avId, None) suit = self.cr.doId2do.get(suitId, None) if sender: backpack = sender.getBackpack() trapGag = backpack.getGagByID(gagId) if backpack and trapGag: entity = None if hasattr(trapGag, 'getEntities') and 0 <= entityId <= len( trapGag.getEntities()) - 1: entity = trapGag.getEntities()[entityId] trapGag.onActivate(entity, suit) return def b_trapActivate(self, gagId, avId, entityId, suitId): self.trapActivate(gagId, avId, entityId, suitId) self.d_trapActivate(gagId, avId, entityId, suitId) def d_trapActivate(self, gagId, avId, entityId, suitId): self.sendUpdate('trapActivate', [gagId, avId, entityId, suitId]) def gagCollision(self, gagId): gag = self.backpack.getGagByID(gagId) gag.doCollision() def b_gagCollision(self, gagId): self.sendUpdate('gagCollision', [gagId]) self.gagCollision(gagId) def gagActivate(self, gagId): gag = self.backpack.getGagByID(gagId) if hasattr(gag, 'activate'): gag.activate() def b_gagActivate(self, gagId): self.sendUpdate('gagActivate', [gagId]) self.gagActivate(gagId) def setDropLoc(self, gagId, x, y, z): gag = self.backpack.getGagByID(gagId) gag.setEndPos(x, y, z) def setGagPos(self, gagId, x, y, z): pos = Point3(x, y, z) gag = self.backpack.getGagByID(gagId) ent = gag.getGag() if ent: ent.setPos(pos) def setThrowPower(self, gagId, power): gag = self.backpack.getGagByID(gagId) if gag: gag.setPower(power) def gagStart(self, gagId): gag = self.backpack.getGagByID(gagId) if gag: gag.start() def b_gagStart(self, gagId): self.sendUpdate('gagStart', [gagId]) self.gagStart(gagId) def gagThrow(self, gagId): gag = self.backpack.getGagByID(gagId) if gag: gag.throw() def b_gagThrow(self, gagId): self.sendUpdate('gagThrow', [gagId]) self.gagThrow(gagId) def gagRelease(self, gagId): gag = self.backpack.getGagByID(gagId) if gag and hasattr(gag, 'name'): gag.release() def b_gagRelease(self, gagId): self.sendUpdate('gagRelease', [gagId]) self.gagRelease(gagId) def setSplatPos(self, gagId, x, y, z): splatGag = self.backpack.getGagByID(gagId) if splatGag: splatGag.setSplatPos(x, y, z) def d_setSplatPos(self, gagId, x, y, z): self.sendUpdate('setSplatPos', [gagId, x, y, z]) def gagBuild(self, gagId): gag = self.backpack.getGagByID(gagId) if gag: gag.build() def b_gagBuild(self, gagId): self.gagBuild(gagId) self.sendUpdate('gagBuild', [gagId]) def handleSuitAttack(self, attack_id, suit_id): attack = SuitAttacks.SuitAttackLengths.keys()[attack_id] if attack == 'canned': sfx = base.audio3d.loadSfx( 'phase_5/audio/sfx/SA_canned_impact_only.ogg') base.audio3d.attachSoundToObject(sfx, self) SoundInterval(sfx, node=self).start() else: if attack == 'playhardball': sfx = base.audio3d.loadSfx( 'phase_5/audio/sfx/SA_hardball_impact_only_alt.ogg') base.audio3d.attachSoundToObject(sfx, self) SoundInterval(sfx, node=self).start() else: if attack == 'clipontie': sfx = base.audio3d.loadSfx( 'phase_5/audio/sfx/SA_powertie_impact.ogg') base.audio3d.attachSoundToObject(sfx, self) SoundInterval(sfx, node=self).start() if not self.isDead(): if attack in ('fountainpen', ): self.getPart('head').setColorScale(0, 0, 0, 1) Sequence(Wait(3.0), Func(self.resetHeadColor)).start() if self.dmgFadeIval: self.dmgFadeIval.finish() self.dmgFadeIval = None geomNode = self.getGeomNode() self.dmgFadeIval = Sequence( Func(geomNode.setTransparency, 1), LerpColorScaleInterval(geomNode, 0.3, (1, 1, 1, 0.5), (1, 1, 1, 1), blendType='easeOut'), LerpColorScaleInterval(geomNode, 0.3, (1, 1, 1, 1), (1, 1, 1, 0.5), blendType='easeIn'), Func(geomNode.setTransparency, 0)) self.dmgFadeIval.start() return def resetHeadColor(self): head = self.getPart('head') if head: head.setColorScale(1, 1, 1, 1) def b_handleSuitAttack(self, attack_id, suit_id): self.handleSuitAttack(attack_id, suit_id) self.b_lookAtObject(0, 0, 0, blink=1) self.sendUpdate('handleSuitAttack', [attack_id, suit_id]) def equip(self, gagId): if self.backpack: self.backpack.setCurrentGag(gagId) def unEquip(self): if self.backpack: self.backpack.setCurrentGag(None) return def b_unEquip(self): self.unEquip() self.sendUpdate('unEquip', []) def b_equip(self, gag_id): self.equip(gag_id) self.sendUpdate('equip', [gag_id]) def getBackpack(self): return self.backpack def setLoadout(self, gagIds): if self.backpack: loadout = [] for i in range(len(gagIds)): gagId = gagIds[i] gag = self.backpack.getGagByID(gagId) if gag: loadout.append(gag) self.backpack.setLoadout(loadout) def setBackpackAmmo(self, gagIds, ammoList): if not self.backpack: self.backpack = Backpack(self) for i in xrange(len(gagIds)): gagId = gagIds[i] ammo = ammoList[i] if not self.backpack.hasGag(gagId): self.backpack.addGag( gagId, ammo, GagGlobals.getGagData(gagId).get('maxSupply')) else: self.backpack.setSupply(gagId, ammo) def getBackpackAmmo(self): return ([], []) def setGagAmmo(self, gagId, ammo): self.backpack.setSupply(gagId, ammo) def setMoney(self, money): self.money = money def getMoney(self): return self.money def setAdminToken(self, value): self.token = value if value > -1: Toon.Toon.setAdminToken(self, value) else: Toon.Toon.removeAdminToken(self) def getAdminToken(self): return self.token def setAnimState(self, anim, timestamp=None, callback=None, extraArgs=[]): self.anim = anim if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) if type(anim) == types.IntType: anim = self.animId2animState[anim] if self.animFSM.getStateNamed(anim): self.animFSM.request(anim, [ts, callback, extraArgs]) return def b_setAnimState(self, anim): self.d_setAnimState(anim) self.setAnimState(anim, None) return def d_setAnimState(self, anim): if type(anim) == types.StringType: anim = self.animState2animId[anim] timestamp = globalClockDelta.getFrameNetworkTime() self.sendUpdate('setAnimState', [anim, timestamp]) def getAnimState(self): return self.anim def setName(self, name): Toon.Toon.setName(self, name) if self.cr.isShowingPlayerIds: self.showAvId() def d_setName(self, name): self.sendUpdate('setName', [name]) def b_setName(self, name): self.d_setName(name) self.setName(name) def showAvId(self): self.setDisplayName(self.getName() + '\n' + str(self.doId)) def showName(self): self.setDisplayName(self.getName()) def setDisplayName(self, name): self.setupNameTag(tempName=name) def wrtReparentTo(self, parent): DistributedSmoothNode.wrtReparentTo(self, parent) def announceHealthAndPlaySound(self, level, hp): DistributedAvatar.announceHealth(self, level, hp) hpSfx = base.audio3d.loadSfx('phase_11/audio/sfx/LB_toonup.ogg') base.audio3d.attachSoundToObject(hpSfx, self) SoundInterval(hpSfx, node=self).start() del hpSfx def announceGenerate(self): DistributedAvatar.announceGenerate(self) if self.animFSM.getCurrentState().getName() == 'off': self.setAnimState('neutral') self.startBlink() def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) self.startSmooth() def disable(self): if self.tunnelTrack: self.ignore(self.tunnelTrack.getDoneEvent()) self.tunnelTrack.finish() self.tunnelTrack = None if self.dmgFadeIval: self.dmgFadeIval.finish() self.dmgFadeIval = None self.busy = None taskMgr.remove(self.uniqueName('sBAL')) taskMgr.remove(self.uniqueName('blinkOnTurn')) if self.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None self.stopBlink() self.__removeHeadMeter() self.ignore('showAvId') self.ignore('showName') self.token = None self.stopSmooth() Toon.Toon.disable(self) DistributedAvatar.disable(self) return def delete(self): try: self.DistributedToon_deleted except: self.DistributedToon_deleted = 1 self.tutDone = None self.defaultShard = None Toon.Toon.delete(self) DistributedAvatar.delete(self) DistributedSmoothNode.delete(self) return
class LightDropGag(DropGag): rotate90 = False scale = 1 def __init__(self): DropGag.__init__(self) DropGag.setShadowData(self, isCircle=True, shadowScale=0.5) self.stunTime = 1.5 self.objTrack = None def startDrop(self, entity): if entity and self.dropLoc: x, y, z = self.dropLoc startPos = Point3(x, y, z + 20) entity.setPos(startPos) entity.node().setBounds(OmniBoundingVolume()) entity.node().setFinal(1) entity.headsUp(self.avatar) entity.setPythonTag('EntityRoot', entity) if self.rotate90: entity.setH(entity.getH() - 90) self.buildCollisions(entity) objectTrack = Sequence() animProp = LerpPosInterval(entity, self.fallDuration, self.dropLoc, startPos=startPos) bounceProp = Effects.createZBounce(entity, 2, self.dropLoc, 0.5, 1.5) objAnimShrink = Sequence(Wait(0.5), Func(entity.reparentTo, render), animProp, bounceProp) objectTrack.append(objAnimShrink) dropShadow = CIGlobals.makeDropShadow(1.0) dropShadow.reparentTo(hidden) dropShadow.setPos(self.dropLoc) if self.name == GagGlobals.FlowerPot: dropShadow.setZ(dropShadow.getZ() - 3.5) dropShadow.setScale(0.01) shadowTrack = Sequence( Func(dropShadow.reparentTo, render), LerpScaleInterval(dropShadow, self.fallDuration + 0.1, self.getShadowScale(), startScale=Point3(0.01, 0.01, 0.01)), Wait(0.8), Func(dropShadow.removeNode)) self.objTrack = Parallel( Sequence(Wait(self.fallDuration), Func(self.completeDrop)), objectTrack, shadowTrack) self.objTrack.start() self.dropLoc = None def onActivate(self, entity, suit): self.objTrack.finish() self.objTrack = None if not suit.isDead(): suit.setAnimState('drop-react') suit.d_disableMovement(wantRay=True) if not entity or entity.isEmpty(): entity = self.build() entity.setPos(suit.find('**/joint_head').getPos(render)) dropMdl = entity.find('**/DropMdl') if self.name == GagGlobals.FlowerPot: entity.setZ(entity, 3.5) bounce = Effects.createScaleZBounce(dropMdl, 1, dropMdl.getScale(render), 0.3, 0.75) dummyNode = suit.attachNewNode('fallOffNode') dummyNode.setX(2) dummyNode.setY(-2) flightIval = FlightProjectileInterval(entity, startPos=entity.getPos(render), endPos=dummyNode.getPos(render), duration=0.8, gravityMult=.35) Sequence(Parallel(bounce, flightIval), Wait(self.stunTime), Func(suit.d_enableMovement)).start() dummyNode.removeNode() del dummyNode
class DistributedBattleTrolley(DistributedObject): notify = directNotify.newCategory('DistributedBattleTrolley') STAND_POSITIONS = [Point3(-4.75, -5, 1.4), Point3(-4.75, -1.6, 1.4), Point3(-4.75, 1.6, 1.4), Point3(-4.75, 5, 1.4)] TROLLEY_NEUTRAL_POS = Point3(15.751, 14.1588, -0.984615) TROLLEY_GONE_POS = Point3(50, 14.1588, -0.984615) TROLLEY_ARRIVING_START_POS = Point3(-20, 14.1588, -0.984615) CAM_POS = Point3(-36.1269, 0.742999, 7.3503) CAM_HPR = Vec3(-90, -1.9966, 0) def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM.ClassicFSM('DistributedBattleTrolley', [State.State('off', self.enterOff, self.exitOff), State.State('wait', self.enterWait, self.exitWait), State.State('waitCountdown', self.enterWaitCountdown, self.exitWaitCountdown), State.State('leaving', self.enterLeaving, self.exitLeaving), State.State('arriving', self.enterArriving, self.exitArriving)], 'off', 'off') self.fsm.enterInitialState() self.trolleyStation = None self.trolleyCar = None self.trolleyKey = None self.countdownText = None self.soundMoving = base.loadSfx('phase_4/audio/sfx/SZ_trolley_away.mp3') self.soundBell = base.loadSfx('phase_4/audio/sfx/SZ_trolley_bell.mp3') self.hoodIndex = 0 self.localAvOnTrolley = False return def headOff(self, zoneId): hoodId = self.cr.playGame.hood.hoodId if hoodId == CIGlobals.ToontownCentral: hoodId = CIGlobals.BattleTTC requestStatus = {'zoneId': zoneId, 'hoodId': hoodId, 'where': 'playground', 'avId': base.localAvatar.doId, 'loader': 'safeZoneLoader', 'shardId': None, 'wantLaffMeter': 1, 'how': 'teleportIn'} self.cr.playGame.getPlace().doneStatus = requestStatus messenger.send(self.cr.playGame.getPlace().doneEvent) base.localAvatar.reparentTo(render) base.localAvatar.setPos(0, 0, 0) base.localAvatar.setHpr(0, 0, 0) base.localAvatar.walkControls.setCollisionsActive(1) self.localAvOnTrolley = False return def setHoodIndex(self, zone): self.hoodIndex = zone def getToZone(self): return self.toZone def enterOff(self, ts = 0): pass def exitOff(self): pass def enterWait(self, ts = 0): self.trolleyCar.setPos(self.TROLLEY_NEUTRAL_POS) def exitWait(self): pass def enterWaitCountdown(self, ts = 0): self.trolleyCar.setPos(self.TROLLEY_NEUTRAL_POS) if self.countdownText: self.countdownTrack = Sequence() for i in range(10): self.countdownTrack.append(Func(self.countdownText.node().setText, str(10 - i))) self.countdownTrack.append(Wait(1.0)) self.countdownTrack.start() def exitWaitCountdown(self): if hasattr(self, 'countdownTrack'): self.countdownTrack.finish() del self.countdownTrack if self.countdownText: self.countdownText.node().setText('') self.disableExitButton() def enterArriving(self, ts = 0): base.playSfx(self.soundMoving) self.moveTrack = LerpPosInterval(self.trolleyCar, duration=3.0, pos=self.TROLLEY_NEUTRAL_POS, startPos=self.TROLLEY_ARRIVING_START_POS, blendType='easeOut') self.moveTrack.start() def exitArriving(self): self.moveTrack.finish() self.acceptOnce('entertrolley_sphere', self.__handleTrolleyTrigger) del self.moveTrack def enterLeaving(self, ts = 0): base.playSfx(self.soundMoving) base.playSfx(self.soundBell) self.moveTrack = Parallel() self.moveTrack.append(LerpPosInterval(self.trolleyCar, duration=3.0, pos=self.TROLLEY_GONE_POS, startPos=self.TROLLEY_NEUTRAL_POS, blendType='easeIn')) if self.localAvOnTrolley == True: self.moveTrack.append(Sequence(Wait(2.0), Func(base.transitions.fadeOut))) self.moveTrack.start() self.ignore('entertrolley_sphere') def exitLeaving(self): self.moveTrack.finish() del self.moveTrack def setState(self, stateName, timestamp): ts = globalClockDelta.localElapsedTime(timestamp) self.fsm.request(stateName, [ts]) def __handleTrolleyTrigger(self, entry): self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.disablePies() self.notify.info('Waiting for response from server to enter trolley') self.sendUpdate('requestBoard') base.localAvatar.walkControls.setCollisionsActive(0) def fillSlot(self, index, avId): toon = self.cr.doId2do.get(avId) toon.stopSmooth() if toon: toon.wrtReparentTo(self.trolleyCar) slotPos = self.STAND_POSITIONS[index] toon.headsUp(slotPos) track = Sequence(Func(toon.setAnimState, 'run'), LerpPosInterval(toon, duration=1.0, pos=slotPos, startPos=toon.getPos()), Func(toon.setAnimState, 'neutral'), Func(toon.setHpr, 90, 0, 0)) track.start() if avId == base.localAvatar.doId: self.localAvOnTrolley = True base.localAvatar.stopSmartCamera() base.camera.wrtReparentTo(self.trolleyCar) camTrack = Sequence(Parallel(LerpPosInterval(base.camera, duration=0.5, pos=self.CAM_POS, startPos=base.camera.getPos(), blendType='easeOut'), LerpQuatInterval(base.camera, duration=0.5, hpr=self.CAM_HPR, startHpr=base.camera.getHpr(), blendType='easeOut')), Func(self.enableExitButton)) camTrack.start() def enableExitButton(self): gui = loader.loadModel('phase_3.5/models/gui/inventory_gui.bam') up = gui.find('**/InventoryButtonUp') down = gui.find('**/InventoryButtonDown') rlvr = gui.find('**/InventoryButtonRollover') self.exitButton = DirectButton(image=(up, down, rlvr), relief=None, text='Exit', text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.8, image_scale=(11, 1, 11), pos=(0, 0, -0.8), scale=0.15, command=self.__handleExitButton, image_color=(1, 0, 0, 1)) return def __handleExitButton(self): if self.fsm.getCurrentState().getName() == 'waitCountdown' and self.localAvOnTrolley == True: self.disableExitButton() self.sendUpdate('requestHopOff') def disableExitButton(self): if hasattr(self, 'exitButton'): self.exitButton.destroy() del self.exitButton def emptySlot(self, index, avId): toon = self.cr.doId2do.get(avId) toon.stopSmooth() currToonPos = toon.getPos(render) toon.wrtReparentTo(render) slotPos = self.STAND_POSITIONS[index] endPos = (-20, slotPos.getY(), 0.0) toon.setPos(self.trolleyCar, endPos) endPosWrtRender = toon.getPos(render) toon.setPos(currToonPos) toon.headsUp(self.trolleyCar, endPos) track = Sequence(Func(toon.setAnimState, 'run'), LerpPosInterval(toon, duration=1.0, pos=endPosWrtRender, startPos=currToonPos), Func(toon.setAnimState, 'neutral'), Func(toon.startSmooth)) if avId == base.localAvatar.doId: self.localAvOnTrolley = False track.append(Func(self.__hoppedOffTrolley)) track.start() def __hoppedOffTrolley(self): self.acceptOnce('entertrolley_sphere', self.__handleTrolleyTrigger) base.localAvatar.walkControls.setCollisionsActive(1) self.cr.playGame.getPlace().fsm.request('walk') def generate(self): DistributedObject.announceGenerate(self) self.trolleyStation = self.cr.playGame.hood.loader.geom.find('**/prop_trolley_station_DNARoot') self.trolleyCar = self.trolleyStation.find('**/trolley_car') self.trolleyKey = self.trolleyStation.find('**/key') tn = TextNode('trolleycountdowntext') tn.setFont(CIGlobals.getMickeyFont()) tn.setTextColor(1, 0, 0, 1) self.countdownText = self.trolleyStation.attachNewNode(tn) self.countdownText.setScale(3.0) self.countdownText.setPos(14.58, 10.77, 11.17) self.acceptOnce('entertrolley_sphere', self.__handleTrolleyTrigger) def delete(self): self.trolleyStation = None self.trolleyKey = None self.soundMoving = None self.soundBell = None self.troleyCar = None self.ignore('entertrolley_sphere') DistributedObject.delete(self) return
class DistributedTutorial(DistributedObject): notify = directNotify.newCategory('DistributedTutorial') GUIDE_NAME = 'Professor Prepostera' GUIDE_START_POS = (5, 10, -0.5) GUIDE_WATCH_POS = (12.4, 27.92, 0) GUIDE_WATCH_HPR = (41.63, 0, 0) GUIDE_INTRO_SPEECH = [ 'Hey, looks like you made it!', 'So, welcome to OToontown.', 'OToontown is short for Old Toontown, or Toontown from the past.', 'Not long ago, Toons used to live in present day Toontown.', 'Unfortunately, the Cogs planned a mega-invasion that was sure to be a complete takeover of Toontown and make all Toons go sad for good.', "There was no way we could have let that happen, so we built a time machine, and sent every Toon back in time to OToontown, where Cogs didn't exist yet.", 'The Cogs completely took over present day Toontown, and turned it into what they wanted it to be - a business metropolis.', 'Toons happily live and play in OToontown now, but we want to learn about present day Toontown...', ' ...or as we now call it, CogTropolis.', "We've built time machines that send Toons back to CogTropolis to fight Cogs and to see what the Cogs have done.", "We know that the Cogs took over Toontown and turned it into a grey business city, but we don't know how they did it.", 'Shopkeepers around OToontown will reward you for finding evidence that may help solve the mystery of how the Cogs turned Toontown into CogTropolis.', 'Before you are able to head to CogTropolis, you need to be trained for battle.', 'The Cogs have become much more skilled battlers and no longer wait for you to throw a gag before attacking you.', 'This is much more difficult for Toons, and it may take some time to get used to.', "I'm going to give you 2 gags to start...", 'A cupcake, and a squirting flower.', 'Equip Gags in your loadout to use by pressing the corresponding key on your keyboard.', 'You can use or throw the Gag that you have equipped by pressing the ALT key.', 'Also, use the Arrow Keys on your keyboard to move, and press CTRL to jump.', "I'm going to summon one of our dummy bots for you to practice battling.", "Click your mouse when you're ready." ] GUIDE_PT2_INFO = [ "Now it'll get a tad bit tougher.", 'This next dummy bot will be walking around.', 'This will test your aiming skills.', "Click your mouse when you're ready." ] GUIDE_PT3_INFO = [ 'This final dummy bot will walk around and try to attack you at times.', 'Defeat this Cog to continue on to the next part of the tutorial.' ] GUIDE_DONE = [ 'Great!', 'Did you know that Cog Invasion Online Alpha allows you to use any Gag that you want?', 'Just use the Gags page in your Shticker Book to swap out the Gags that you want to be able to use!', 'Also during Alpha testing, your Toon will start off with 5000 jellybeans and 100 Laff points.', "If you're looking to fight some Cogs, hop on the Trolley in the playgrounds to be teleported to CogTropolis!", 'Each playground has a different difficulty of Cogs, so be careful!', "You can only fight Cogs in Toontown Central, Minnie's Melodyland, Donald's Dock, and Donald's Dreamland at the moment.", 'You can also visit the Minigame Area using your Shticker Book to play some fun minigames!', 'These games are best to play with other Toons!', 'Remember, if you find any bugs or strange things during gameplay, you can go to the Contact Us page at coginvasion.com to report the issue.', 'Have fun!' ] GUIDE_START_TRAINING = "Alright! Let's do this!" def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM.ClassicFSM('TutorialFSM', [ State.State('off', self.enterOff, self.exitOff), State.State('newPlayerEmerge', self.enterPlayerEmerge, self.exitPlayerEmerge, ['off', 'introSpeech']), State.State('introSpeech', self.enterGuideIntroSpeech, self.exitGuideIntroSpeech, ['off', 'introSpeech2Training']), State.State('introSpeech2Training', self.enterIntroSpeech2Training, self.exitIntroSpeech2Training, ['off', 'training1']), State.State('training1', self.enterTrainingPT1, self.exitTrainingPT1, ['off', 'training2info']), State.State('training2info', self.enterTraining2Info, self.exitTraining2Info, ['off', 'training2']), State.State('training2', self.enterTrainingPT2, self.exitTrainingPT2, ['off', 'training3info']), State.State('training3info', self.enterTraining3Info, self.exitTraining3Info, ['off', 'training3']), State.State('training3', self.enterTrainingPT3, self.exitTrainingPT3, ['off', 'trainingDone']), State.State('trainingDone', self.enterTrainingDone, self.exitTrainingDone, ['off', 'leaveTutorial']), State.State('leaveTutorial', self.enterLeaveTutorial, self.exitLeaveTutorial, ['off']) ], 'off', 'off') self.fsm.enterInitialState() self.dnaStore = DNAStorage() self.streetGeom = None self.sky = None self.skyUtil = SkyUtil() self.guide = None self.music = None self.battleMusic = None self.playerCamPos = None self.playerCamHpr = None return def enterOff(self): pass def exitOff(self): pass def introStuff(self): base.localAvatar.getGeomNode().hide() base.localAvatar.setPos(0, 0, -0.5) base.localAvatar.setHpr(0, 0, 0) self.guide.setPos(self.GUIDE_START_POS) self.guide.headsUp(base.localAvatar) base.localAvatar.attachCamera() def enterPlayerEmerge(self): self.introStuff() self.guide.loop('neutral') base.transitions.irisIn() base.taskMgr.doMethodLater(1.0, self.__playerEmerge, 'playerEmergeTask') def __playerEmerge(self, task): base.localAvatar.setAnimState('teleportIn', callback=self.__playerEmergeFinished) return Task.done def __playerEmergeFinished(self): base.localAvatar.setAnimState('neutral') self.fsm.request('introSpeech') def exitPlayerEmerge(self): base.localAvatar.detachCamera() base.taskMgr.remove('playerEmergeTask') base.transitions.noTransitions() def enterGuideIntroSpeech(self): base.localAvatar.attachCamera() renderPos = base.camera.getPos(render) renderHpr = base.camera.getHpr(render) base.localAvatar.detachCamera() endPos = base.localAvatar.getPos(render) + (0, 0, 4) base.camera.setPos(endPos) base.camera.lookAt(self.guide, 0, 0, 3) endHpr = base.camera.getHpr(render) base.camera.setPos(renderPos) base.camera.setHpr(renderHpr) self.chatIndex = -1 self.doNextIntroSpeech() self.camMoveTrack = Sequence( Parallel( LerpPosInterval(base.camera, duration=3.0, pos=endPos, startPos=renderPos, blendType='easeOut'), LerpQuatInterval(base.camera, duration=3.0, hpr=endHpr, startHpr=renderHpr, blendType='easeOut')), Func(base.localAvatar.getGeomNode().hide)) self.camMoveTrack.start() def __finishedReadingGuideIntroSpeech(self): self.guide.autoClearChat = True self.guide.setChat(self.GUIDE_START_TRAINING) self.fsm.request('introSpeech2Training') def doNextIntroSpeech(self): self.chatIndex += 1 if self.chatIndex >= len(self.GUIDE_INTRO_SPEECH): self.__finishedReadingGuideIntroSpeech() return self.guide.setChat(self.GUIDE_INTRO_SPEECH[self.chatIndex]) Sequence(Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.doNextIntroSpeech)).start() def exitGuideIntroSpeech(self): self.camMoveTrack.finish() base.localAvatar.getGeomNode().show() del self.camMoveTrack del self.chatIndex def enterIntroSpeech2Training(self): startCamPos = base.camera.getPos(render) startCamHpr = base.camera.getHpr(render) base.camera.setPosHpr(0, 0, 0, 0, 0, 0) base.localAvatar.attachCamera() endCamPos = base.camera.getPos(render) endCamHpr = base.camera.getHpr(render) base.localAvatar.detachCamera() startHpr = self.guide.getHpr(render) self.guide.headsUp(self.GUIDE_WATCH_POS) endHpr = self.guide.getHpr(render) self.guide.loop('run') self.camMoveIval = Parallel( LerpPosInterval(base.camera, duration=2.0, pos=endCamPos, startPos=startCamPos, blendType='easeOut'), LerpQuatInterval(base.camera, duration=2.0, hpr=endCamHpr, startHpr=startCamHpr, blendType='easeOut'), Sequence( LerpPosInterval(self.guide, duration=2.0, pos=self.GUIDE_WATCH_POS, startPos=self.guide.getPos(render)), Func(self.guide.loop, 'walk'), LerpHprInterval(self.guide, duration=1.0, hpr=self.GUIDE_WATCH_HPR, startHpr=endHpr), Func(self.guide.loop, 'neutral')), LerpHprInterval(self.guide, duration=1.0, hpr=endHpr, startHpr=startHpr)) self.camMoveIval.setDoneEvent('introSpeech2TrainingDone') self.acceptOnce('introSpeech2TrainingDone', self.__handleIS2TDone) self.camMoveIval.start() def __handleIS2TDone(self): self.fsm.request('training1') def exitIntroSpeech2Training(self): self.ignore('introSpeech2TrainingDone') self.camMoveIval.finish() del self.camMoveIval def makeWhisper(self, msg): whisper = WhisperPopup(msg, CIGlobals.getToonFont(), ChatGlobals.WTSystem) whisper.manage(base.marginManager) def enterTrainingPT1(self): self.music.stop() base.playMusic(self.battleMusic, volume=0.8, looping=1) self.sendUpdate('makeSuit', [0]) base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.startBlink() base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.collisionsOn() base.localAvatar.enableAvatarControls() base.localAvatar.enableGags(1) base.localAvatar.showGagButton() base.localAvatar.startTrackAnimToSpeed() self.makeWhisper( 'This should be pretty simple. Just throw a gag at this dummy bot to defeat it.' ) def suitNoHealth(self, index): if index == 0: self.makeWhisper( ('Good job, {0}!').format(base.localAvatar.getName())) else: if index == 1: self.makeWhisper("Wow, you're doing very well!") def suitExploded(self, index): if index == 0: self.makeWhisper( 'Pick up the jellybean that he dropped. You can use them to buy more gags for your Toon.' ) self.battleMusic.stop() base.playMusic(self.music, looping=1, volume=0.8) def pickedUpJellybean(self): if self.fsm.getCurrentState().getName() == 'training1': self.fsm.request('training2info') else: if self.fsm.getCurrentState().getName() == 'training2': self.fsm.request('training3info') else: if self.fsm.getCurrentState().getName() == 'training3': self.fsm.request('trainingDone') def exitTrainingPT1(self): base.localAvatar.lastState = None base.localAvatar.disableAvatarControls() base.localAvatar.detachCamera() base.localAvatar.stopSmartCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.stopBlink() base.localAvatar.collisionsOff() base.localAvatar.controlManager.placeOnFloor() base.localAvatar.disableGags() base.localAvatar.stopTrackAnimToSpeed() base.localAvatar.hideGagButton() return def enterTraining2Info(self): base.camera.setPos(3.09, 37.16, 3.93) base.camera.setHpr(225, 0, 0) self.guide.autoClearChat = False self.chatIndex = -1 self.doNextTraining2Speech() def __finishedReadingGuideTraining2Speech(self): self.guide.autoClearChat = True self.guide.clearChat() self.fsm.request('training2') def doNextTraining2Speech(self): self.chatIndex += 1 if self.chatIndex >= len(self.GUIDE_PT2_INFO): self.__finishedReadingGuideTraining2Speech() return self.guide.setChat(self.GUIDE_PT2_INFO[self.chatIndex]) Sequence( Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.doNextTraining2Speech)).start() def exitTraining2Info(self): base.camera.setPosHpr(0, 0, 0, 0, 0, 0) del self.chatIndex def enterTrainingPT2(self): self.music.stop() base.playMusic(self.battleMusic, volume=0.8, looping=1) self.sendUpdate('makeSuit', [1]) base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.startBlink() base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.collisionsOn() base.localAvatar.enableAvatarControls() base.localAvatar.enableGags(1) base.localAvatar.showGagButton() base.localAvatar.startTrackAnimToSpeed() def exitTrainingPT2(self): base.localAvatar.lastState = None base.localAvatar.disableAvatarControls() base.localAvatar.detachCamera() base.localAvatar.stopSmartCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.stopBlink() base.localAvatar.collisionsOff() base.localAvatar.controlManager.placeOnFloor() base.localAvatar.disableGags() base.localAvatar.stopTrackAnimToSpeed() base.localAvatar.hideGagButton() return def enterTraining3Info(self): base.camera.setPos(3.09, 37.16, 3.93) base.camera.setHpr(225, 0, 0) self.guide.autoClearChat = False self.chatIndex = -1 self.doNextTraining3Speech() def __finishedReadingGuideTraining3Speech(self): self.guide.autoClearChat = True self.guide.clearChat() self.fsm.request('training3') def doNextTraining3Speech(self): self.chatIndex += 1 if self.chatIndex >= len(self.GUIDE_PT3_INFO): self.__finishedReadingGuideTraining3Speech() return self.guide.setChat(self.GUIDE_PT3_INFO[self.chatIndex]) Sequence( Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.doNextTraining3Speech)).start() def exitTraining3Info(self): base.camera.setPosHpr(0, 0, 0, 0, 0, 0) del self.chatIndex def enterTrainingPT3(self): self.music.stop() base.playMusic(self.battleMusic, volume=0.8, looping=1) self.sendUpdate('makeSuit', [2]) base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.startBlink() base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.collisionsOn() base.localAvatar.enableAvatarControls() base.localAvatar.enableGags(1) base.localAvatar.showGagButton() base.localAvatar.startTrackAnimToSpeed() def exitTrainingPT3(self): base.localAvatar.lastState = None base.localAvatar.disableAvatarControls() base.localAvatar.detachCamera() base.localAvatar.stopSmartCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.stopBlink() base.localAvatar.collisionsOff() base.localAvatar.controlManager.placeOnFloor() base.localAvatar.disableGags() base.localAvatar.stopTrackAnimToSpeed() base.localAvatar.hideGagButton() return def enterTrainingDone(self): base.camera.setPos(3.09, 37.16, 3.93) base.camera.setHpr(225, 0, 0) self.guide.autoClearChat = False self.chatIndex = -1 self.doNextTrainingDoneSpeech() def __finishedReadingGuideTrainingDoneSpeech(self): self.guide.autoClearChat = True self.guide.clearChat() self.fsm.request('leaveTutorial') def doNextTrainingDoneSpeech(self): self.chatIndex += 1 if self.chatIndex >= len(self.GUIDE_DONE): self.__finishedReadingGuideTrainingDoneSpeech() return self.guide.setChat(self.GUIDE_DONE[self.chatIndex]) Sequence( Wait(0.1), Func(self.acceptOnce, 'mouse1-up', self.doNextTrainingDoneSpeech)).start() def exitTrainingDone(self): base.camera.setPosHpr(0, 0, 0, 0, 0, 0) del self.chatIndex def enterLeaveTutorial(self): base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.b_setAnimState('teleportOut', callback=self.__teleOutDone) def __teleOutDone(self): zoneId = CIGlobals.ToontownCentralId hoodId = CIGlobals.ToontownCentral whereName = 'playground' avId = base.localAvatar.doId loaderName = 'safeZoneLoader' self.sendUpdate('finishedTutorial') self.cr.playGame.load() self.cr.playGame.enter(hoodId, zoneId, base.localAvatar.doId) def exitLeaveTutorial(self): base.localAvatar.stopSmartCamera() base.localAvatar.detachCamera() def announceGenerate(self): DistributedObject.announceGenerate(self) base.transitions.fadeScreen(0.0) self.guide = Toon(base.cr) self.guide.autoClearChat = False self.guide.parseDNAStrand(NPCGlobals.NPC_DNA[self.GUIDE_NAME]) self.guide.setName(self.GUIDE_NAME) self.guide.generateToon() self.guide.nametag.setNametagColor( NametagGlobals.NametagColors[NametagGlobals.CCNPC]) self.guide.nametag.setActive(0) self.guide.nametag.updateAll() self.guide.startBlink() self.guide.reparentTo(render) base.localAvatar.reparentTo(render) loader.loadDNAFile(self.dnaStore, 'phase_3.5/dna/storage_tutorial.pdna') node = loader.loadDNAFile(self.dnaStore, 'phase_3.5/dna/tutorial_street.pdna') if node.getNumParents() == 1: self.streetGeom = NodePath(node.getParent(0)) self.streetGeom.reparentTo(hidden) else: self.streetGeom = hidden.attachNewNode(node) self.streetGeom.flattenMedium() gsg = base.win.getGsg() if gsg: self.streetGeom.prepareScene(gsg) self.streetGeom.reparentTo(render) self.streetGeom.setPos(20.5, -20, 0) self.streetGeom.setH(90) self.sky = loader.loadModel('phase_3.5/models/props/TT_sky.bam') self.skyUtil.startSky(self.sky) self.sky.reparentTo(camera) ce = CompassEffect.make(NodePath(), CompassEffect.PRot | CompassEffect.PZ) self.sky.node().setEffect(ce) self.music = base.loadMusic('phase_3.5/audio/bgm/TC_SZ.mid') base.playMusic(self.music, volume=0.8, looping=1) self.battleMusic = base.loadMusic( 'phase_3.5/audio/bgm/encntr_general_bg.mid') self.fsm.request('newPlayerEmerge') base.localAvatar.inTutorial = True def disable(self): self.fsm.requestFinalState() del self.fsm if self.guide: self.guide.disable() self.guide.delete() self.guide = None if self.streetGeom: self.streetGeom.removeNode() self.streetGeom = None if self.sky: self.sky.removeNode() self.sky = None if self.music: self.music.stop() self.music = None if self.battleMusic: self.battleMusic.stop() self.battleMusic = None self.dnaStore.reset_nodes() self.dnaStore.reset_hood_nodes() self.dnaStore.reset_place_nodes() self.dnaStore.reset_hood() self.dnaStore.reset_fonts() self.dnaStore.reset_DNA_vis_groups() self.dnaStore.reset_textures() self.dnaStore.reset_block_numbers() self.dnaStore.reset_block_zones() self.dnaStore.reset_suit_points() self.dnaStore = None self.skyUtil = None base.localAvatar.inTutorial = False DistributedObject.disable(self) return
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 xrange(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.loadSfx('phase_4/audio/sfx/MG_pairing_card_flip_face_up.ogg') self.turnDownSound = base.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 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 xrange(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 CogThief(DirectObject): notify = directNotify.newCategory('CogThief') DefaultSpeedWalkAnim = 4.0 CollisionRadius = 1.25 MaxFriendsVisible = 4 Infinity = 100000.0 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) 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 self.velocity = Vec3(0, 0, 0) self.oldVelocity = Vec3(0, 0, 0) self.acceleration = Vec3(0, 0, 0) self.bodyLength = self.CollisionRadius * 2 self.cruiseDistance = 2 * self.bodyLength self.maxVelocity = self.cogSpeed 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): 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() self.suit.loop('neutral') def initCollisions(self): self.collSphere = CollisionSphere(0, 0, 0, 1.25) 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.accept('enter' + self.collSphereName, self.handleEnterSphere) self.pieCollSphere = CollisionTube(0, 0, 0, 0, 0, 4, self.CollisionRadius) 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) 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): self.notify.debug('self.netTimeSentToStartByHit =%s' % self.netTimeSentToStartByHit) if not self.game: self.notify.debug('updateGoal self.game is None, just returning') return None if not self.suit: self.notify.debug('updateGoal self.suit is None, just returning') return None 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: pass 1 if inResponseClientStamp < self.netTimeSentToStartByHit and self.goal == CTGG.NoGoal and goalType == CTGG.RunAwayGoal: 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 def startWalkAnim(self): if self.suit: self.suit.loop('walk') speed = self.cogSpeed self.defaultPlayRate = float(self.cogSpeed / self.DefaultSpeedWalkAnim) self.suit.setPlayRate(self.defaultPlayRate, 'walk') def think(self): 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 None 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): 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): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits = 32) gameTime = self.game.local2GameTime(localStamp) return gameTime def respondToToonHit(self, timestamp): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits = 32) if self.netTimeSentToStartByHit < timestamp: self.clearGoal() self.showKaboom() 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): self.goal = CTGG.NoGoal self.goalId = CTGG.InvalidGoalId def thinkAboutGettingBarrel(self): if not self.game: return None if not hasattr(self.game, 'barrels'): return None if self.goalId not in xrange(len(self.game.barrels)): return None 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) self.doneAdjust = True displacement = barrelPos - myPos distanceToToon = displacement.length() self.suit.headsUp(barrel) lengthTravelled = diffTime * self.cogSpeed if lengthTravelled > distanceToToon: lengthTravelled = distanceToToon displacement.normalize() dirVector = displacement dirVector *= lengthTravelled newPos = myPos + dirVector newPos.setZ(0) self.suit.setPos(newPos) self.adjustPlayRate(newPos, myPos, diffTime) self.lastThinkTime = globalClock.getFrameTime() def stopWalking(self, timestamp): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits = 32) if localStamp > self.lastLocalTimeStampFromAI: self.suit.loop('neutral') self.clearGoal() def thinkAboutRunAway(self): if not self.game: return None 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) self.doneAdjust = True displacement = returnPos - myPos distanceToToon = displacement.length() tempNp = render.attachNewNode('tempRet') tempNp.setPos(returnPos) self.suit.headsUp(tempNp) tempNp.removeNode() lengthTravelled = diffTime * self.cogSpeed if lengthTravelled > distanceToToon: lengthTravelled = distanceToToon displacement.normalize() dirVector = displacement dirVector *= lengthTravelled newPos = myPos + dirVector 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: self.game.sendCogAtReturnPos(self.cogIndex, self.barrel) self.signalledAtReturnPos = True self.lastThinkTime = globalClock.getFrameTime() def makeCogCarryBarrel(self, timestamp, inResponseClientStamp, barrelModel, barrelIndex, cogPos): if not self.game: return None localTimeStamp = globalClockDelta.networkToLocalTime(timestamp, bits = 32) 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): localTimeStamp = globalClockDelta.networkToLocalTime(timestamp, bits = 32) self.lastLocalTimeStampFromAI = localTimeStamp barrelModel.reparentTo(render) barrelModel.setPos(barrelPos) self.barrel = CTGG.NoBarrelCarried def respondToPieHit(self, timestamp): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits = 32) if self.netTimeSentToStartByHit < timestamp: self.clearGoal() self.showSplat() 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): 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): 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): if not self.lastThinkTime: self.lastThinkTime = globalClock.getFrameTime() dt = globalClock.getFrameTime() - self.lastThinkTime self.oldpos = self.suit.getPos() pos = self.suit.getPos() pos += self.velocity * dt self.suit.setPos(pos) self.seeFriends() acc = Vec3(0, 0, 0) self.accumulate(acc, self.getTargetVector()) if self.numFlockmatesSeen > 0: keepDistanceVector = self.keepDistance() oldAcc = Vec3(acc) self.accumulate(acc, keepDistanceVector) if self.cogIndex == 0: pass if acc.length() > self.maxAcceleration: acc.normalize() acc *= self.maxAcceleration self.oldVelocity = self.velocity self.velocity += acc if self.velocity.length() > self.maxVelocity: self.velocity.normalize() self.velocity *= self.maxVelocity forwardVec = Vec3(1, 0, 0) heading = rad2Deg(math.atan2(self.velocity[1], self.velocity[0])) heading -= 90 self.suit.setH(heading) def getTargetVector(self): 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): accumulator += valueToAdd return accumulator.length() def seeFriends(self): 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 dist != self.Infinity return self.numFlockmatesSeen def clearVisibleList(self): self.visibleFriendsList = [] self.numFlockmatesSeen = 0 self.nearestFlockmate = None self.distToNearestFlockmate = self.Infinity def addToVisibleList(self, cogIndex): if self.numFlockmatesSeen < self.MaxFriendsVisible: self.visibleFriendsList.append(cogIndex) self.numFlockmatesSeen += 1 if self.cogIndex == 0: pass def canISee(self, cogIndex): if self.cogIndex == cogIndex: return self.Infinity cogThief = self.game.getCogThief(cogIndex) distance = self.suit.getDistance(cogThief.suit) if distance < self.perceptionRange: return distance return self.Infinity def sameGoal(self, cogIndex): cogThief = self.game.getCogThief(cogIndex) if cogThief.goalId == self.goalId: pass result = cogThief.goal == self.goal return result def keepDistance(self): 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 if self.distToNearestFlockmate < self.SeparationDistance: change.normalize() change *= -(1 - ratio) elif self.distToNearestFlockmate > self.SeparationDistance: change.normalize() change *= ratio else: change = Vec3(0, 0, 0) return change def showKaboom(self): 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): 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.10000000000000001, 0.10000000000000001, 0.10000000000000001), blendType = 'easeOut'), Func(self.splat.hide))) self.kaboomTrack.start()
class DistributedPartyGate(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPartyGate") def __init__(self, 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.loadSfx("phase_4/audio/sfx/clock%s.mp3" % si)) def generate(self): 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 None self.clockFlat = partyGate.find("**/clock_flat") collSphere = CollisionSphere(0, 0, 0, 6.9000000000000004) collSphere.setTangible(1) self.partyGateSphere = CollisionNode("PartyGateSphere") self.partyGateSphere.addSolid(collSphere) self.partyGateCollNodePath = partyGate.find("**/partyGate_stepsLocator").attachNewNode(self.partyGateSphere) self._DistributedPartyGate__enableCollisions() self.toontownTimeGui = ServerTimeGui(partyGate, hourCallback=self.hourChange) self.toontownTimeGui.setPos( partyGate.find("**/clockText_locator").getPos() + Point3(0.0, 0.0, -0.20000000000000001) ) self.toontownTimeGui.setHpr(partyGate.find("**/clockText_locator").getHpr()) self.toontownTimeGui.setScale(12.0, 1.0, 26.0) self.toontownTimeGui.amLabel.setPos(-0.035000000000000003, 0, -0.032000000000000001) self.toontownTimeGui.amLabel.setScale(0.5) self.toontownTimeGui.updateTime() self.setupSignText() def setupSignText(self): 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 None gateFont = ToontownGlobals.getMinnieFont() leftSign = partyGate.find("**/signTextL_locatorBack") signScale = 0.34999999999999998 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.69999999999999996, 0.29999999999999999, 0.29999999999999999, 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.69999999999999996, 0.29999999999999999, 0.29999999999999999, 1.0), scale=signScale, ) def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) if ToontownGlobals.dnaMap.has_key(self.zoneId): 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._DistributedPartyGate__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._DistributedPartyGate__handleMessageDone) self.messageGui = TTDialog.TTGlobalDialog( doneEvent=self.messageDoneEvent, message=message, style=TTDialog.Acknowledge ) def _DistributedPartyGate__handleMessageDone(self): self.ignore(self.messageDoneEvent) self.freeAvatar() self.messageGui.cleanup() self.messageGui = None def _DistributedPartyGate__handleAskDone(self): DistributedPartyGate.notify.debug("__handleAskDone") self.ignore(self.publicPartyChooseGuiDoneEvent) doneStatus = self.publicPartyGui.doneStatus self.publicPartyGui.stash() if doneStatus is None: self.freeAvatar() return None self.sendUpdate("partyChoiceRequest", [base.localAvatar.doId, doneStatus[0], doneStatus[1]]) def partyRequestDenied(self, reason): DistributedPartyGate.notify.debug( "partyRequestDenied( reason=%s )" % PartyGlobals.PartyGateDenialReasons.getString(reason) ) if reason == PartyGlobals.PartyGateDenialReasons.Unavailable: self.showMessage(TTLocalizer.PartyGatePartyUnavailable) elif reason == PartyGlobals.PartyGateDenialReasons.Full: self.showMessage(TTLocalizer.PartyGatePartyFull) def setParty(self, partyInfoTuple): DistributedPartyGate.notify.debug("setParty") self.freeAvatar() if partyInfoTuple[0] == 0: DistributedPartyGate.notify.debug("Public Party closed before toon could get to it.") return None (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, } ) 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() seq1 = Sequence() for i in range(currentHour): seq1.append(SoundInterval(self.clockSounds[i])) seq1.append(Wait(0.20000000000000001)) timeForEachDeformation = seq1.getDuration() / currentHour seq2 = Sequence() for i in range(currentHour): seq2.append( self.clockFlat.scaleInterval( timeForEachDeformation / 2.0, Vec3(0.90000000000000002, 1.0, 1.2), blendType="easeInOut" ) ) seq2.append( self.clockFlat.scaleInterval( timeForEachDeformation / 2.0, Vec3(1.2, 1.0, 0.90000000000000002), blendType="easeInOut" ) ) seq2.append( self.clockFlat.scaleInterval(timeForEachDeformation / 2.0, Vec3(1.0, 1.0, 1.0), blendType="easeInOut") ) self.hourSoundInterval.append(seq1) self.hourSoundInterval.append(seq2) self.hourSoundInterval.start() def handleEnterGateSphere(self, collEntry): self.notify.debug("Entering steps Sphere....") base.cr.playGame.getPlace().fsm.request("stopped") self.sendUpdate("getPartyList", [base.localAvatar.doId]) def listAllPublicParties(self, publicPartyInfo): self.notify.debug("listAllPublicParties : publicPartyInfo = %s" % publicPartyInfo) self.acceptOnce(self.publicPartyChooseGuiDoneEvent, self._DistributedPartyGate__handleAskDone) self.publicPartyGui.refresh(publicPartyInfo) self.publicPartyGui.unstash() def _DistributedPartyGate__enableCollisions(self): self.accept("enterPartyGateSphere", self.handleEnterGateSphere) self.partyGateSphere.setCollideMask(OTPGlobals.WallBitmask) def _DistributedPartyGate__disableCollisions(self): self.ignore("enterPartyGateSphere") self.partyGateSphere.setCollideMask(BitMask32(0)) def handleSleep(self): if hasattr(self, "messageGui") and self.messageGui: self._DistributedPartyGate__handleMessageDone()
class DodgeballFirstPerson(FirstPerson): """The first person controls for the local player in Winter Dodgeball""" notify = directNotify.newCategory("DodgeballFirstPerson") MaxPickupDistance = 5.0 def __init__(self, mg): self.mg = mg self.crosshair = None self.soundCatch = None self.vModelRoot = None self.vModel = None self.ival = None self.soundPickup = base.loadSfx( 'phase_4/audio/sfx/MG_snowball_pickup.wav') self.fakeSnowball = loader.loadModel( "phase_5/models/props/snowball.bam") self.hasSnowball = False self.mySnowball = None self.fsm = ClassicFSM.ClassicFSM("DodgeballFirstPerson", [ State.State("off", self.enterOff, self.exitOff), State.State("hold", self.enterHold, self.exitHold), State.State("catch", self.enterCatch, self.exitCatch), State.State("throw", self.enterThrow, self.exitThrow) ], "off", "off") self.fsm.enterInitialState() FirstPerson.__init__(self) def enterOff(self): if self.vModel: self.vModel.hide() def exitOff(self): if self.vModel: self.vModel.show() def enterHold(self): self.ival = Sequence(ActorInterval(self.vModel, "hold-start"), Func(self.vModel.loop, "hold")) self.ival.start() def exitHold(self): if self.ival: self.ival.finish() self.ival = None self.vModel.stop() def enterThrow(self): self.ival = Parallel( Sequence(Wait(0.4), Func(self.mySnowball.b_throw)), Sequence(ActorInterval(self.vModel, "throw"), Func(self.fsm.request, 'off'))) self.ival.start() def exitThrow(self): if self.ival: self.ival.pause() self.ival = None self.vModel.stop() def enterCatch(self): self.ival = Parallel( Sequence(Wait(0.2), Func(self.__tryToCatchOrGrab)), Sequence(ActorInterval(self.vModel, "catch"), Func(self.__maybeHold))) self.ival.start() def __maybeHold(self): if self.hasSnowball: self.fsm.request('hold') else: self.fsm.request('off') def __tryToCatchOrGrab(self): snowballs = list(self.mg.snowballs) snowballs.sort( key=lambda snowball: snowball.getDistance(base.localAvatar)) for i in xrange(len(snowballs)): snowball = snowballs[i] if (not snowball.hasOwner() and not snowball.isAirborne and snowball.getDistance(base.localAvatar) <= DodgeballFirstPerson.MaxPickupDistance): snowball.b_pickup() self.mySnowball = snowball self.fakeSnowball.setPosHpr(0, 0.73, 0, 0, 0, 0) self.fakeSnowball.reparentTo( self.vModel.exposeJoint(None, "modelRoot", "Bone.011")) base.playSfx(self.soundPickup) self.hasSnowball = True break def exitCatch(self): self.vModel.stop() if self.ival: self.ival.pause() self.ival = None def start(self): # Black crosshair because basically the entire arena is white. self.crosshair = getCrosshair(color=(0, 0, 0, 1), hidden=False) self.soundCatch = base.loadSfx( "phase_4/audio/sfx/MG_sfx_vine_game_catch.ogg") self.vModelRoot = camera.attachNewNode('vModelRoot') self.vModelRoot.setPos(-0.09, 1.38, -2.48) self.vModel = Actor( "phase_4/models/minigames/v_dgm.egg", { "hold": "phase_4/models/minigames/v_dgm-ball-hold.egg", "hold-start": "phase_4/models/minigames/v_dgm-ball-hold-start.egg", "throw": "phase_4/models/minigames/v_dgm-ball-throw.egg", "catch": "phase_4/models/minigames/v_dgm-ball-catch.egg" }) self.vModel.setBlend(frameBlend=True) self.vModel.reparentTo(self.vModelRoot) self.vModel.setBin("fixed", 40) self.vModel.setDepthTest(False) self.vModel.setDepthWrite(False) self.vModel.hide() base.localAvatar.walkControls.setWalkSpeed(ToonForwardSpeed, ToonJumpForce, ToonReverseSpeed, ToonRotateSpeed) FirstPerson.start(self) def reallyStart(self): FirstPerson.reallyStart(self) base.localAvatar.startTrackAnimToSpeed() self.accept('mouse3', self.__handleCatchOrGrabButton) self.accept('mouse1', self.__handleThrowButton) def __handleThrowButton(self): if self.hasSnowball and self.mySnowball and self.fsm.getCurrentState( ).getName() == 'hold': self.fakeSnowball.reparentTo(hidden) self.fsm.request('throw') def __handleCatchOrGrabButton(self): if not self.hasSnowball and not self.mySnowball and self.fsm.getCurrentState( ).getName() == 'off': self.fsm.request('catch') def reallyEnd(self): base.localAvatar.setWalkSpeedNormal() FirstPerson.reallyEnd(self)
class DistributedDodgeballGame(DistributedToonFPSGame, TeamMinigame): """The winter dodgeball minigame (client side)""" notify = directNotify.newCategory("DistributedDodgeballGame") TreeData = [['prop_snow_tree_small_ur', Point3(23.23, 66.52, 7.46)], ['prop_snow_tree_small_ul', Point3(-34.03, 88.02, 24.17)], ['prop_snow_tree_small_ur', Point3(-54.80, 0, 4.19)], ['prop_snow_tree_small_ul', Point3(54.80, -5, 4.19)], ['prop_snow_tree_small_ur', Point3(62.71, 62.66, 16.80)], ['prop_snow_tree_small_ul', Point3(-23.23, -66.52, 6)], ['prop_snow_tree_small_ur', Point3(34.03, -88.02, 23)], ['prop_snow_tree_small_ul', Point3(-62.71, -62.66, 16)]] SnowballData = [Point3(30, 0, 0.75), Point3(22.5, 0, 0.75), Point3(15, 0, 0.75), Point3(7.5, 0, 0.75), Point3(0, 0, 0.75), Point3(-7.5, 0, 0.75), Point3(-15, 0, 0.75), Point3(-22.5, 0, 0.75), Point3(-30, 0, 0.75)] GameSong = "phase_4/audio/bgm/MG_Dodgeball.ogg" GameDesc = ("Welcome to the north! You have been invited to play dodgeball with the penguins!\n\n" "How To Play\nWASD to Move and use the mouse to aim.\nLeft click to Throw!\nRight click" " to Catch!\n\nObjective\nThe first team to get everyone out wins!") InitCamTrans = [Point3(25, 45, 19.5317), Vec3(154.001, -15, 0)] SnowBallDmg = 25 GetSnowBalls = "Pick up a snowball from the center!" def __init__(self, cr): try: self.DistributedDodgeballGame_initialized return except: self.DistributedDodgeballGame_initialized = 1 DistributedToonFPSGame.__init__(self, cr) TeamMinigame.__init__(self, "BlueSnow", ('phase_4/maps/db_blue_neutral.png', 'phase_4/maps/db_blue_hover.png', 'phase_4/maps/db_blue_hover.png'), "RedIce", ('phase_4/maps/db_red_neutral.png', 'phase_4/maps/db_red_hover.png', 'phase_4/maps/db_red_hover.png')) self.fsm.addState(State('chooseTeam', self.enterChooseTeam, self.exitChooseTeam, ['waitForOthers'])) self.fsm.addState(State('scrollBy', self.enterScrollBy, self.exitScrollBy, ['countdown'])) self.fsm.addState(State('countdown', self.enterCountdown, self.exitCountdown, ['play'])) self.fsm.getStateNamed('waitForOthers').addTransition('chooseTeam') self.fsm.getStateNamed('waitForOthers').addTransition('scrollBy') self.firstPerson = DodgeballFirstPerson(self) self.scrollBySeq = None self.infoText = None self.infoText = getAlertText() self.spawnPointsByTeam = { BLUE: [ [Point3(5, 15, 0), Vec3(180, 0, 0)], [Point3(15, 15, 0), Vec3(180, 0, 0)], [Point3(-5, 15, 0), Vec3(180, 0, 0)], [Point3(-15, 15, 0), Vec3(180, 0, 0)]], RED: [ [Point3(5, -15, 0), Vec3(0, 0, 0)], [Point3(15, -15, 0), Vec3(0, 0, 0)], [Point3(-5, -15, 0), Vec3(0, 0, 0)], [Point3(-15, -15, 0), Vec3(0, 0, 0)]]} # Environment vars self.sky = None self.arena = None self.fog = None self.snow = None self.snowRender = None self.trees = [] self.snowballs = [] def snowballHitWall(self, snowballIndex): snowball = self.snowballs[snowballIndex] snowball.handleHitWallOrPlayer() def snowballHitPlayer(self, damagedPlayer, snowballIndex): av = self.getRemoteAvatar(damagedPlayer) if av: print "setting health" av.setHealth(av.health - DistributedDodgeballGame.SnowBallDmg) if damagedPlayer == base.localAvatar.doId: self.showAlert("You were hit by a snowball!") snowball = self.snowballs[snowballIndex] snowball.handleHitWallOrPlayer() def playerCaughtSnowball(self, snowballIndex, catcherId): av = self.getRemoteAvatar(catcherId) if av: snowball = self.snowballs[snowballIndex] snowball.pauseThrowIval() snowball.pickup(av) def setupRemoteAvatar(self, avId): av = RemoteDodgeballAvatar(self, self.cr, avId) if avId == self.cr.localAvId: self.myRemoteAvatar = av print "setup remove avatar {0}".format(avId) self.remoteAvatars.append(av) def __getSnowTree(self, path): trees = loader.loadModel('phase_8/models/props/snow_trees.bam') tree = trees.find('**/' + path) tree.find('**/*shadow*').removeNode() return tree def load(self): self.setMinigameMusic(DistributedDodgeballGame.GameSong) self.setDescription(DistributedDodgeballGame.GameDesc) self.createWorld() trans = DistributedDodgeballGame.InitCamTrans camera.setPos(trans[0]) camera.setHpr(trans[1]) DistributedToonFPSGame.load(self) def createWorld(self): self.deleteWorld() self.sky = loader.loadModel("phase_3.5/models/props/BR_sky.bam") self.sky.reparentTo(render) self.sky.setZ(-40) self.sky.setFogOff() self.arena = loader.loadModel("phase_4/models/minigames/dodgeball_arena.egg") self.arena.reparentTo(render) self.arena.setScale(0.75) self.arena.find('**/team_divider').setBin('ground', 18) self.arena.find('**/floor').setBin('ground', 18) self.arena.find('**/team_divider_coll').setCollideMask(CIGlobals.FloorBitmask) for data in DistributedDodgeballGame.TreeData: code = data[0] pos = data[1] tree = self.__getSnowTree(code) tree.reparentTo(self.arena) tree.setPos(pos) self.trees.append(tree) for i in xrange(len(DistributedDodgeballGame.SnowballData)): snowdata = DistributedDodgeballGame.SnowballData[i] snowball = Snowball(self, i) snowball.load() snowball.reparentTo(render) snowball.setPos(snowdata) self.snowballs.append(snowball) self.snow = ParticleLoader.loadParticleEffect('phase_8/etc/snowdisk.ptf') self.snow.setPos(0, 0, 5) self.snowRender = self.arena.attachNewNode('snowRender') self.snowRender.setDepthWrite(0) self.snowRender.setBin('fixed', 1) self.snow.start(camera, self.snowRender) self.fog = Fog('snowFog') self.fog.setColor(0.486, 0.784, 1) self.fog.setExpDensity(0.003) render.setFog(self.fog) def throw(self, snowballIndex, p): snowball = self.snowballs[snowballIndex] snowball.throw(p) def snowballPickup(self, snowballIndex, pickerUpperAvId): remoteAv = self.getRemoteAvatar(pickerUpperAvId) if remoteAv: snowball = self.snowballs[snowballIndex] snowball.pickup(remoteAv) def deleteWorld(self): for snowball in self.snowballs: snowball.removeNode() self.snowballs = [] for tree in self.trees: tree.removeNode() self.trees = [] if self.snow: self.snow.cleanup() self.snow = None if self.snowRender: self.snowRender.removeNode() self.snowRender = None self.fog = None if self.sky: self.sky.removeNode() self.sky = None if self.arena: self.arena.removeNode() self.arena = None render.clearFog() def enterPlay(self): self.firstPerson.reallyStart() def exitPlay(self): self.firstPerson.end() def enterCountdown(self): self.firstPerson.start() self.firstPerson.disableMouse() self.infoText.setText(DistributedDodgeballGame.GetSnowBalls) self.countdownText = getGameText() self.countdownIval = Parallel( Sequence( Func(self.countdownText.setText, "5"), getCountdownIval(self.countdownText), Func(self.countdownText.setText, "4"), getCountdownIval(self.countdownText), Func(self.countdownText.setText, "3"), getCountdownIval(self.countdownText), Func(self.countdownText.setText, "2"), getCountdownIval(self.countdownText), Func(self.countdownText.setText, "1"), getCountdownIval(self.countdownText)), getAlertPulse(self.infoText), name = "COUNTDOWNIVAL") self.countdownIval.setDoneEvent(self.countdownIval.getName()) self.acceptOnce(self.countdownIval.getDoneEvent(), self.__handleCountdownDone) self.countdownIval.start() def __handleCountdownDone(self): self.fsm.request('play') def exitCountdown(self): if hasattr(self, 'countdownText'): self.countdownText.destroy() del self.countdownText if hasattr(self, 'countdownIval'): self.ignore(self.countdownIval.getDoneEvent()) self.countdownIval.finish() del self.countdownIval def enterScrollBy(self): BLUE_START_POS = Point3(-20, 0, 4) BLUE_END_POS = Point3(20, 0, 4) BLUE_HPR = Vec3(0, 0, 0) RED_START_POS = Point3(20, 0, 4) RED_END_POS = Point3(-20, 0, 4) RED_HPR = Vec3(180, 0, 0) self.playMinigameMusic() self.scrollBySeq = Sequence( Func(camera.setHpr, BLUE_HPR), LerpPosInterval( camera, duration = 5.0, pos = BLUE_END_POS, startPos = BLUE_START_POS, blendType = 'easeOut'), Func(base.transitions.fadeOut, 0.4), Wait(0.5), Func(base.transitions.fadeIn, 0.4), Func(camera.setHpr, RED_HPR), LerpPosInterval( camera, duration = 5.0, pos = RED_END_POS, startPos = RED_START_POS, blendType = 'easeOut'), name = "SCROLLBYSEQ") self.scrollBySeq.setDoneEvent(self.scrollBySeq.getName()) self.acceptOnce(self.scrollBySeq.getDoneEvent(), self.__handleScrollByDone) self.scrollBySeq.start() def __handleScrollByDone(self): self.fsm.request('countdown') def exitScrollBy(self): if self.scrollBySeq: self.ignore(self.scrollBySeq.getDoneEvent()) self.scrollBySeq.finish() self.scrollBySeq = None def allPlayersReady(self): self.fsm.request('scrollBy') def chooseUrTeam(self): # The AI has told us it's time to choose our team. self.fsm.request('chooseTeam') def enterChooseTeam(self): self.makeSelectionGUI() def acceptedIntoTeam(self, spawnPoint): TeamMinigame.acceptedIntoTeam(self) self.sendUpdate('readyToStart') self.fsm.request('waitForOthers') pos, hpr = self.spawnPointsByTeam[self.team][spawnPoint] base.localAvatar.setPos(pos) base.localAvatar.setHpr(hpr) def exitChooseTeam(self): self.destroySelectionGUI() def announceGenerate(self): DistributedToonFPSGame.announceGenerate(self) base.camLens.setMinFov(CIGlobals.GunGameFOV / (4./3.)) self.load() def disable(self): self.deleteWorld() self.trees = None self.snowballs = None self.spawnPointsByTeam = None if self.firstPerson: self.firstPerson.cleanup() self.firstPerson = None DistributedToonFPSGame.disable(self)
class gameScene(FSM,DirectObject): """ **************************** Méthodes pour l'initialisation **************************** """ def __init__(self,app): self.app = app; FSM.__init__(self,"gameScene") self.defaultTransitions = {"Init":["Base"],"Base":["Cinematic","Explore"],"Cinematic":["Base","Explore"],"Explore":["Base","Cinematic"]} if self.app.main_config["lang_chx"] == 0: self.app.speak = lang.fr.fr_lang elif self.app.main_config["lang_chx"] == 1: self.app.speak = lang.en.en_lang self.giroscope = render.attachNewNode("giroscope"); self.giroscope.setPos(0,0,0); self.giroscope.setHpr(0,0,0) self.giroHpr = [0,0,0]; self.giroPos = [0,0,0]; camera.reparentTo(self.giroscope); camera.setPos(0,-34,25); camera.lookAt(0,0,0) # self.camMove = {"strapCam":[0,0,0],"rotCam":[0,0,0]} # # # DEBUG : test du passage de la scène et du display self.accept("a",self.returnMainMenu) self.accept("escape",sys.exit,[0]) ### # self.dic_gui = {"wait_visual":{},"main_visual":{},"tuto_visual":{},"base_visual":{},"explore_visual":{}} self.loadGUI(); self.dic_gui["wait_visual"]["frame"].show() self.act_place = self.app.transit["place"]; self.actscene = scenebuilder.gamescene_builder[self.act_place] self.type_place = 0 #0 : base; 1 : explore; 2 : cinematic self.dic_statics, self.dic_dynamics, self.dic_lights = self.app.arcstools.parse_scene(self.actscene,self) self.loadmodels(); self.dic_anims = {}; self.activeAnim() self.dic_sounds = {}; self.loadSfx(); self.dic_musics = {}; self.loadMusics() # # TODO : voir pour une tâche en "again" pour la gestion de la souris # # DEBUG : retour au menu principal (méthode de test) def returnMainMenu(self): taskMgr.add(self.app.main_screen,"return to main menu") ### def loadSfx(self): # # TODO : chargement des sons # pass def loadMusics(self): # # TODO : chargement des musiques # pass def loadGUI(self): #frame de chargement tmp_frame = DirectFrame(); self.dic_gui["wait_visual"]["frame"] = tmp_frame; tmp_frame.hide() tmp_gui = self.app.arcLabel(self.app.speak["wait_visual"]["titre"],(0,0,0.4),0.15,TextNode.ACenter) tmp_gui.reparentTo(tmp_frame); self.dic_gui["wait_visual"]["titre"] = tmp_gui tmp_gui = self.app.arcLabel(self.app.speak["wait_visual"]["waiting_text"],(0,0,0),0.1,TextNode.ACenter) tmp_gui.reparentTo(tmp_frame); self.dic_gui["wait_visual"]["waiting_text"] = tmp_gui #frame principale # # TODO : frame principale, présente tout le temps # tmp_frame = DirectFrame(); self.dic_gui["main_visual"]["frame"] = tmp_frame; tmp_frame.hide() # # TODO : barre de boutons pour quitter, les options, l'aide, etc # tmp_gui = self.app.arcButton(self.app.speak["main_visual"]["quit"],(-0.75,0,0.95),None,0.06,TextNode.ACenter) tmp_gui.reparentTo(tmp_frame); tmp_gui["state"] = DGG.DISABLED; self.dic_gui["main_visual"]["quit"] = tmp_gui # # #tmp_gui = self.app.arcButton(self.app.speak["main_visual"][""],(-0.4,0,0.95),None,0.06,TextNode.ACenter) #tmp_gui.reparentTo(tmp_frame); tmp_gui["state"] = DGG.DISABLED; self.dic_gui["main_visual"][""] = tmp_gui # # tmp_gui = self.app.arcButton(self.app.speak["main_visual"]["option"],(0.4,0,0.95),None,0.06,TextNode.ACenter) tmp_gui.reparentTo(tmp_frame); tmp_gui["state"] = DGG.DISABLED; self.dic_gui["main_visual"]["option"] = tmp_gui # # tmp_gui = self.app.arcButton(self.app.speak["main_visual"]["help"],(0.75,0,0.95),None,0.06,TextNode.ACenter) tmp_gui.reparentTo(tmp_frame); tmp_gui["state"] = DGG.DISABLED; self.dic_gui["main_visual"]["help"] = tmp_gui # # #frame "tutoriel" # # TODO : frame s'affichant uniquement lors de la création d'une partie # tmp_frame = DirectFrame(); self.dic_gui["tuto_visual"]["frame"] = tmp_frame; tmp_frame.hide() # # #frame "base" # # TODO : frame lorsque l'unité est dans une base # tmp_frame = DirectFrame(); self.dic_gui["base_visual"]["frame"] = tmp_frame; tmp_frame.hide() # # #frame "explore" # # TODO : frame lorsque l'unité est sortie # tmp_frame = DirectFrame(); self.dic_gui["explore_visual"]["frame"] = tmp_frame; tmp_frame.hide() # # def loadmodels(self): tmp_mod = Actor("mainscene/models/dynamics/main_gates.bam"); tmp_mod.reparentTo(camera) tmp_mod.setPos(0,14,0); tmp_mod.setHpr(0,90,0); self.gates = tmp_mod # # TODO : chargement des models additionnels # # 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))) # # TODO : chargement des animations # # def mouseTask(self,task): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() # # TODO : capture de la souris # # return task.cont """ **************************** méthodes pour contrôler la caméra **************************** """ def activeCamControl(self): self.accept("arrow_left",self.captureCamControl,["strap","left","down"]) self.accept("arrow_left-up",self.captureCamControl,["strap","left","up"]) self.accept("arrow_right",self.captureCamControl,["strap","right","down"]) self.accept("arrow_right-up",self.captureCamControl,["strap","right","up"]) self.accept("shift",self.captureCamControl,["rot","down"]); self.accept("shift-up",self.captureCamControl,["rot","up"]) # # TODO : activation des contrôles de la caméra # # # pass def captureCamControl(self,cmd1,cmd2=None,cmd3=None): # # TODO : capture des contrôles de la caméra # print cmd1 print cmd2 print cmd3 # pass def moveCam(self,task): # # TODO : gestion des contrôles de la caméra # # return task.cont """ **************************** méthodes pour l'état "Init" **************************** """ def enterInit(self): self.gates.play("open_gates"); taskMgr.doMethodLater(7,self.initTasks,"entering cam") taskMgr.doMethodLater(9,self.initTasks,"change state"); self.task_chx = 0 self.dic_gui["wait_visual"]["frame"].hide() def exitInit(self): pass def initTasks(self,task): if self.task_chx == 0: self.cam_anim_enter.start(); self.task_chx = 1 elif self.task_chx == 1: self.request("Base") return task.done """ **************************** méthodes pour l'état "Base" **************************** """ def enterBase(self): self.app.change_cursor("main"); self.dic_gui["main_visual"]["frame"].show() # # TODO : etat pour afficher une base (enterBase) # self.activeCamControl() # # def exitBase(self): # # TODO : méthode de sortie de l'état "Base" # pass """ **************************** méthodes pour l'état "Cinematic" **************************** """ def enterCinematic(self): # # TODO : méthode d'entrée dans l'état "Cinematic" # print "Cinematic state entering" # def exitCinematic(self): # # TODO : moéthde de sortie de l'état "Cinematic" # print "Cinematic state exiting" # """ **************************** méthodes pour l'état "Explore" **************************** """ def enterExplore(self): # # TODO : méthode d'entrée dans l'état "Explore" # print "Explore state entering" # def exitExplore(self): # # TODO : méthode de sortie de l'état "Explore" # print "Explore state exiting" # """ **************************** méthodes pour la sortie de la scène de jeu **************************** """ def delete_actscene(self): for key in self.dic_anims: try: self.dic_anims[key].finish() except: pass self.dic_anims[key] = None for key in self.dic_lights: render.clearLight(self.dic_lights[key]); self.dic_lights[key].removeNode() for key in self.dic_statics: self.dic_statics[key].removeNode() for key in self.dic_dynamics: self.dic_dynamics[key].delete() self.dic_statics = None; self.dic_dynamics = None; self.dic_anims = None def close(self): self.ignoreAll(); # #taskMgr.remove(self.mouse_task); self.mouse_task = None # for key in self.dic_sounds: self.dic_sounds[key].stop(); self.dic_sounds[key] = None for key in self.dic_musics: self.dic_musics[key].stop(); self.dic_musics[key] = None for key1 in self.dic_gui: for key2 in self.dic_gui[key1]: for t in self.dic_gui[key1][key2].options(): if t[0] == "command": self.dic_gui[key1][key2]["command"] = None; break self.dic_gui[key1][key2].removeNode() self.dic_sounds = None; self.dic_musics = None # # TODO : suppression des éléments non classés # self.giroscope.removeNode(); self.gates.delete() try: self.cam_anim_enter.finish(); self.cam_anim_exit.finish() except: pass del self.cam_anim_exit; del self.cam_anim_enter # # DEBUG : cette méthode n'aura plus d'utilité une fois le code de ce fichier terminé def __del__(self): print "delete gamescene"
class DistributedCityCart(DistributedNode): notify = directNotify.newCategory('DistributedCityCart') def __init__(self, cr): DistributedNode.__init__(self, cr) self.fsm = ClassicFSM('DistributedCityCart', [State('off', self.enterOff, self.exitOff), State('pathFollow', self.enterPathFollow, self.exitPathFollow), State('collision', self.enterCollision, self.exitCollision)], 'off', 'off') self.fsm.enterInitialState() self.suitInCar = None self.cart = None self.honkSfxPath = 'phase_14/audio/sfx/cogtropolis_citycar_driveby_horn.ogg' self.cartModelPath = 'phase_12/models/bossbotHQ/Coggolf_cart3.bam' self.moPaths = ['phase_14/models/paths/ct-citycar-drivepath-1.egg', 'phase_14/models/paths/ct-citycar-drivepath-2.egg', 'phase_14/models/paths/ct-citycar-drivepath-3.egg', 'phase_14/models/paths/ct-citycar-drivepath-4.egg', 'phase_14/models/paths/ct-citycar-drivepath-5.egg', 'phase_14/models/paths/ct-citycar-drivepath-6.egg'] self.moPath = None self.soundEngineLoop = None self.soundDriveByHorn = None self.ivalTDisplace = None self.pathIndex = None self.wheelSpinTrack = None self.collNodePath = None self.soundDriveBy = None def setIvalTDisplace(self, displace): self.ivalTDisplace = displace def setPathIndex(self, index): self.pathIndex = index def setState(self, state, timestamp): ts = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.fsm.request(state, [ts]) def enterOff(self): pass def exitOff(self): pass def enterPathFollow(self, ts): duration = CityCartGlobals.index2Duration[self.pathIndex] self.moPath = NURBSMopath.NURBSMopath(self.moPaths[self.pathIndex], name = self.uniqueName('DCityCart_moPath')) startT = 0.0 if ts > 0.0: startT = (ts % duration) * (1.0 / duration) self.moPath.play(self, loop = True, duration = duration, startT = startT) base.taskMgr.add(self.__drive, self.uniqueName('DCityCart.drive')) self.wheelSpinTrack = Parallel() for name in ['leftFrontWheel', 'rightBackWheel', 'rightFrontWheel', 'leftBackWheel']: wheel = self.find('**/' + name) self.wheelSpinTrack.append(LerpHprInterval(wheel, duration = 0.1, hpr = (0, 360, 0), startHpr = (0, 0, 0))) self.wheelSpinTrack.loop() self.accept('enter' + self.collNodePath.node().getName(), self.__handleRanOver) def __handleRanOver(self, entry): self.suitInCar.setChat(CityCartGlobals.SuitRanOverTaunt) self.sendUpdate('hitByCar') self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.b_setAnimState('squish', callback = self.cr.playGame.getPlace().fsm.request, extraArgs = ['walk']) def __drive(self, task): if base.localAvatar.getDistance(self) < 10.0: if self.soundDriveByHorn.status() == self.soundDriveByHorn.READY: wantsToHonk = random.randint(0, 3) if wantsToHonk == 3: base.playSfx(self.soundDriveByHorn) return task.cont elif base.localAvatar.getDistance(self) < 20.0: if self.soundDriveBy.status() == self.soundDriveBy.READY: base.playSfx(self.soundDriveBy) return task.cont return task.cont def exitPathFollow(self): self.ignore('enter' + self.collNodePath.node().getName()) base.taskMgr.remove(self.uniqueName('DCityCart.drive')) if self.wheelSpinTrack: self.wheelSpinTrack.finish() self.wheelSpinTrack = None if self.moPath: self.moPath.stop() self.moPath = None def enterCollision(self, ts): pass def exitCollision(self): pass def generate(self): DistributedNode.generate(self) self.cart = loader.loadModel(self.cartModelPath) self.cart.reparentTo(self) self.cart.setH(180) plans = [] for plan in SuitBank.getSuits(): if plan.getSuitType() != SuitType.B: plans.append(plan) plan = random.choice(plans) self.suitInCar = Suit() self.suitInCar.level = 0 self.suitInCar.generate(plan, Variant.NORMAL) self.suitInCar.loop('sit') self.suitInCar.disableRay() self.suitInCar.setScale(0.7) self.suitInCar.setH(180) self.suitInCar.setPos(0, -1, -1.5) self.suitInCar.reparentTo(self.cart.find('**/seat1')) self.suitInCar.show() self.soundEngineLoop = base.audio3d.loadSfx('phase_6/audio/sfx/KART_Engine_loop_0.ogg') base.audio3d.attachSoundToObject(self.soundEngineLoop, self) base.playSfx(self.soundEngineLoop, looping = 1) self.soundDriveByHorn = base.audio3d.loadSfx(self.honkSfxPath) base.audio3d.attachSoundToObject(self.soundDriveByHorn, self) self.soundDriveBy = base.audio3d.loadSfx('phase_14/audio/sfx/cogtropolis_citycar_driveby.ogg') base.audio3d.attachSoundToObject(self.soundDriveBy, self) sphere = CollisionSphere(0, 0, 0, 2.5) sphere.setTangible(0) node = CollisionNode(self.uniqueName('cartSphere')) node.setCollideMask(CIGlobals.WallBitmask) node.addSolid(sphere) self.collNodePath = self.attachNewNode(node) self.collNodePath.setZ(1.5) self.collNodePath.setSy(2.0) self.collNodePath.setSx(1.75) def disable(self): self.fsm.requestFinalState() if self.moPath: self.moPath.stop() self.moPath = None self.moPaths = None self.honkSfxPath = None self.cartModelPath = None self.soundEngineLoop = None self.soundDriveBy = None if self.suitInCar: self.suitInCar.disable() self.suitInCar.delete() self.suitInCar = None if self.cart: self.cart.removeNode() self.cart = None del self.fsm DistributedNode.disable(self)
class Suit(Avatar): notify = directNotify.newCategory('Suit') def __init__(self): Avatar.__init__(self) self.dept = None self.suit = None self.head = None self.headModel = None self.variant = None self.handColor = None self.voice = None self.chat = None self.chatDial = None self.shadow = None self.deathSound = None self.propeller = None self.smallExp = None self.largeExp = None self.explosion = None self.hasSpawned = False self.suitTrack = None self.timestampAnimTrack = None self.propellerSounds = {} self.healthBar = None self.healthBarGlow = None self.condition = 0 self.avatarType = CIGlobals.Suit self.suitPlan = None self.footstepSound = None self.showNametagInMargins = False self.surfaceProp = "metal" self.activities = { ACT_WAKE_ANGRY: WakeAngry(self), ACT_SMALL_FLINCH: Flinch(self), ACT_DIE: Die(self), ACT_VICTORY_DANCE: VictoryDance(self), ACT_COG_FLY_DOWN: FlyDown(self), ACT_SIT: Sit(self), ACT_STUN: Stun(self) } self.standWalkRunReverse = [('neutral', 'walk', 0.0, 5.0, 1.0, 1.0)] self.gruntSound = base.audio3d.loadSfx( "phase_14/audio/sfx/cog_grunt.ogg") base.audio3d.attachSoundToObject(self.gruntSound, self) self.animFSM = ClassicFSM('Suit', [ State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('die', self.enterDie, self.exitDie), State('win', self.enterWin, self.exitWin), State('flail', self.enterFlail, self.exitFlail), State('flyDown', self.enterFlyDown, self.exitFlyDown), State('flyAway', self.enterFlyAway, self.exitFlyAway), State('flyNeutral', self.enterFlyNeutral, self.exitFlyNeutral), State('trayWalk', self.enterTrayWalk, self.exitTrayWalk), State('trayNeutral', self.enterTrayNeutral, self.exitTrayNeutral), State('stunned', self.enterStunned, self.exitStunned), State('pie', self.enterPie, self.exitPie), State('drop', self.enterDrop, self.exitDrop), State('drop-react', self.enterDropReact, self.exitDropReact), State('soak', self.enterSoak, self.exitSoak), State('squirt-small', self.enterSquirtSmall, self.exitSquirtSmall) ], 'off', 'off') self.animFSM.enterInitialState() def getRightHandNode(self): return self.find("**/joint_Rhold") def getLeftHandNode(self): return self.find("**/joint_Lhold") def getHeadNode(self): return self.headModel def getUpperBodySubpart(self): return [None] def getLowerBodySubpart(self): return [None] def getMoveAction(self, forward, rotate, strafe): return 0 def enterPie(self, ts=0): self.play('pie') def exitPie(self): self.stop() def enterDrop(self, ts=0): self.play("drop") def exitDrop(self): self.stop() def enterDropReact(self, ts=0): self.play('drop-react') def exitDropReact(self): self.stop() def enterSoak(self, ts=0): self.play('soak') def exitSoak(self): self.stop() def enterSquirtSmall(self, ts=0): self.play('squirt-small') def exitSquirtSmall(self): self.stop() def enterStunned(self, animB4Stun, ts=0): self.show() if isinstance(animB4Stun, int): animB4Stun = SuitGlobals.getAnimById(animB4Stun).getName() self.stunnedSound = base.loadSfxOnNode( "phase_4/audio/sfx/SZ_TC_bird1.ogg", self) self.stunnedSound.setLoop(True) self.stunnedSound.play() self.stunnedIval = Parallel( Sequence(ActorInterval(self, animB4Stun), Func(self.loop, 'stunned')), SuitGlobals.createStunInterval(self, 0, 100)) self.stunnedIval.start() def clearStunnedIval(self): if hasattr(self, 'stunnedSound'): self.stunnedSound.stop() del self.stunnedSound if hasattr(self, 'stunnedIval'): self.stunnedIval.finish() del self.stunnedIval def exitStunned(self): self.clearStunnedIval() self.stop() def getLeftHand(self): return self.find("**/joint_Lhold") def getRightHand(self): return self.find("**/joint_Rhold") def getNametagJoints(self): return [] # BEGIN STATES def enterOff(self, ts=0): pass def exitOff(self): pass def exitGeneral(self): pass def enterTrayWalk(self, ts=0): self.show() self.loop('tray-walk') def exitTrayWalk(self): self.exitGeneral() def enterTrayNeutral(self, ts=0): self.loop('tray-neutral') def exitTrayNeutral(self): self.stop() def enterNeutral(self, ts=0): self.show() self.loop("neutral") def exitNeutral(self): self.exitTimestampAnimTrack() self.exitGeneral() def enterWalk(self, ts=0): self.show() self.loop("walk") self.enableRay() self.disableShadowRay() self.startFootsteps() def exitWalk(self): self.stopFootsteps() self.exitTimestampAnimTrack() self.exitGeneral() self.enableShadowRay() def enterFlail(self, ts=0): self.pingpong('flail', fromFrame=30, toFrame=35) def exitFlail(self): self.stop() def exitTimestampAnimTrack(self): if self.timestampAnimTrack: self.timestampAnimTrack.pause() self.timestampAnimTrack = None def enterFlyNeutral(self, ts=0): self.disableRay() self.enableShadowRay() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['neutral'] base.playSfx(sfx, node=self, looping=1) self.propeller.loop('chan', fromFrame=0, toFrame=3) self.setPlayRate(0.8, 'land') self.pingpong('land', fromFrame=0, toFrame=10) def exitFlyNeutral(self): self.cleanupPropeller() def enterFlyDown(self, ts=0): self.disableRay() self.enableShadowRay() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['in'] base.playSfx(sfx, node=self) groundF = 28 dur = self.getDuration('land') fr = self.getFrameRate('land') if fr: animTimeInAir = groundF / fr else: animTimeInAir = groundF impactLength = dur - animTimeInAir timeTillLanding = 6.5 - impactLength waitTime = timeTillLanding - animTimeInAir lastSpinFrame = 8 propDur = self.propeller.getDuration('chan') fr = self.propeller.getFrameRate('chan') spinTime = lastSpinFrame / fr openTime = (lastSpinFrame + 1) / fr if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyDown') else: name = 'enterFlyDown' animTrack = Sequence(Func(self.pose, 'land', 0), Wait(waitTime), ActorInterval(self, 'land', duration=dur)) propTrack = Parallel( SoundInterval(sfx, duration=waitTime + dur, node=self), Sequence( ActorInterval(self.propeller, 'chan', constrainedLoop=1, duration=waitTime + spinTime, startTime=0.0, endTime=spinTime), ActorInterval(self.propeller, 'chan', duration=propDur - openTime, startTime=openTime))) self.suitTrack = Parallel(animTrack, propTrack, name=self.taskName('flyDown')) if not self.hasSpawned: self.show() fadeInTrack = Sequence( Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 1), startColorScale=VBase4(1, 1, 1, 0)), Func(self.clearColorScale), Func(self.clearTransparency)) self.hasSpawned = True self.suitTrack.append(fadeInTrack) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyDown) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) def exitFlyDown(self): self.cleanupPropeller() self.enableRay() if self.suitTrack != None: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.exitGeneral() def enterFlyAway(self, ts=0, doFadeOut=0): self.show() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['out'] if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyAway') else: name = 'enterFlyAway' dur = self.getDuration('land') actInt = ActorInterval(self, 'land', loop=0, startTime=dur, endTime=0.0) lastSpinFrame = 8 propDur = self.propeller.getDuration('chan') fr = self.propeller.getFrameRate('chan') spinTime = lastSpinFrame / fr openTime = (lastSpinFrame + 1) / fr propTrack = Parallel( SoundInterval(sfx, node=self), Sequence( Func(self.propeller.show), ActorInterval(self.propeller, 'chan', endTime=openTime, startTime=propDur), ActorInterval(self.propeller, 'chan', constrainedLoop=1, duration=propDur - openTime, startTime=spinTime, endTime=0.0))) self.suitTrack = Parallel(actInt, propTrack, name=self.taskName('trackName')) if doFadeOut: fadeOut = Sequence( Wait(4.0), Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, hidden)) self.suitTrack.append(fadeOut) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyAway) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) self.disableRay() self.enableShadowRay() def exitFlyAway(self): self.cleanupPropeller() if self.suitTrack: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.exitGeneral() def enterDie(self, ts=0): self.show() self.clearStunnedIval() self.generateCog(isLose=1) self.nametag.clearChatText() self.deleteNameTag() self.deathSound = base.audio3d.loadSfx( "phase_3.5/audio/sfx/Cog_Death_Full.ogg") base.audio3d.attachSoundToObject(self.deathSound, self) trackName = self.uniqueName('enterDie') smallGears = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosionSmall.ptf') #smallGears.getParticlesNamed('particles-1').setPoolSize(30) singleGear = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosion.ptf') singleGear.getParticlesNamed('particles-1').setPoolSize(1) smallGearExplosion = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosion.ptf') smallGearExplosion.getParticlesNamed('particles-1').setPoolSize(10) bigGearExplosion = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosionBig.ptf') bigGearExplosion.getParticlesNamed('particles-1').setPoolSize(30) smallGears.setDepthWrite(False) singleGear.setDepthWrite(False) smallGearExplosion.setDepthWrite(False) bigGearExplosion.setDepthWrite(False) gearPoint = self.getPos(render) + (0, 0, self.getHeight() - 0.2) self.smallGears = smallGears self.smallGears.setPos(gearPoint) self.singleGear = singleGear self.singleGear.setPos(gearPoint) self.smallGearExp = smallGearExplosion self.smallGearExp.setPos(gearPoint) self.bigGearExp = bigGearExplosion self.bigGearExp.setPos(gearPoint) gearTrack = Sequence(Wait(0.7), Func(self.doSingleGear), Wait(1.5), Func(self.doSmallGears), Wait(3.0), Func(self.doBigExp)) self.suitTrack = Parallel( Sequence(Wait(0.8), SoundInterval(self.deathSound, duration=4.28)), Sequence(Wait(0.7), Func(self.doSingleGear), Wait(4.5), Func(self.suitExplode), Wait(1.0), Func(self.disableBodyCollisions)), gearTrack, Sequence(ActorInterval(self, 'lose', duration=6), Func(self.getGeomNode().hide)), name=trackName) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getName(), self.exitDie) if self.isDistributed(): self.suitTrack.delayDelete = DelayDelete.DelayDelete( self, trackName) self.suitTrack.start(ts) def doSingleGear(self): self.singleGear.start(CIGlobals.getParticleRender()) def doSmallGears(self): self.smallGears.start(CIGlobals.getParticleRender()) def doSmallExp(self): self.smallGearExp.start(CIGlobals.getParticleRender()) def doBigExp(self): self.bigGearExp.start(CIGlobals.getParticleRender()) def suitExplode(self): pos = self.getPart('body').find('**/joint_head').getPos(render) + ( 0, 0, 2) # Force the loser suit to use UnlitGeneric shader, workaround for the has_mat() assertion BSPUtility.applyUnlitOverride(self) CIGlobals.makeExplosion(pos, 0.5, soundVol=0.32, smoke=False) def exitDie(self): if self.suitTrack != None: self.ignore(self.suitTrack.getName()) self.suitTrack.finish() if self.isDistributed(): DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None if hasattr(self, 'singleGear'): self.singleGear.softStop() del self.singleGear if hasattr(self, 'smallGears'): self.smallGears.softStop() del self.smallGears if hasattr(self, 'smallGearExp'): self.smallGearExp.softStop() del self.smallGearExp if hasattr(self, 'bigGearExp'): self.bigGearExp.softStop() del self.bigGearExp if self.deathSound: self.deathSound.stop() self.deathSound = None def enterWin(self, ts=0): self.play('win') def exitWin(self): self.exitGeneral() # END STATES def generateSuit(self, suitPlan, variant, voice=None, hideFirst=False): startTime = globalClock.getRealTime() self.suitPlan = suitPlan self.suit = suitPlan.getSuitType() self.head = suitPlan.getHead() self.dept = suitPlan.getDept() self.handColor = suitPlan.getHandColor() self.variant = variant self.setVoice(voice) self.generateCog() mat = CIGlobals.getCharacterMaterial(shininess=50.0, specular=(0.4, 0.4, 0.4, 1)) self.setMaterial(mat) #ts = TextureStage('shiny') #ts.setMode(TextureStage.MAdd) #ts.setRgbScale(2) #tex = loader.loadCubeMap('phase_14/maps/cubemap/defaultcubemap_#.png') #tex = loader.loadTexture('phase_14/maps/envmap001a_cog.png') #self.setTexGen(ts, TexGenAttrib.MEyeSphereMap) #self.setTexture(ts, tex) self.initializeBodyCollisions() if hideFirst: self.hide() else: self.show() endTime = globalClock.getRealTime() print("generateSuit took {0} ms".format((endTime - startTime) * 1000)) def __blinkRed(self, task): self.healthBar.setColor(SuitGlobals.healthColors[3], 1) #self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[3], 1) if self.condition == 5: self.healthBar.setScale(1.17) return task.done def __blinkGray(self, task): if not self.healthBar: return self.healthBar.setColor(SuitGlobals.healthColors[4], 1) #self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[4], 1) if self.condition == 5: self.healthBar.setScale(1.0) return task.done def generateHealthBar(self): self.removeHealthBar() button = loader.loadModel('phase_3.5/models/gui/matching_game_gui.bam' ).find('**/minnieCircle') button.setScale(3.0) button.setH(180) button.setColor(SuitGlobals.healthColors[0]) chestNull = self.find('**/def_joint_attachMeter') if chestNull.isEmpty(): chestNull = self.find('**/joint_attachMeter') button.reparentTo(chestNull) self.healthBar = button #self.healthBarGlow = loader.loadModel('phase_3.5/models/props/glow.bam') #self.healthBarGlow.reparentTo(self.healthBar) #self.healthBarGlow.setScale(0.28) #self.healthBarGlow.setPos(-0.005, 0.01, 0.015) #self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[0]) button.flattenLight() button.setLightOff() self.condition = 0 if hasattr(self, 'getHealth'): self.updateHealthBar(self.getHealth()) def updateHealthBar(self, hp): if not self.healthBar: return if hp > self.health: self.health = hp health = 0.0 try: health = float(hp) / float(self.maxHealth) except: pass if health > 0.95: condition = 0 elif health > 0.7: condition = 1 elif health > 0.3: condition = 2 elif health > 0.05: condition = 3 elif health > 0.0: condition = 4 else: condition = 5 if self.condition != condition: taskMgr.remove(self.taskName('blink-task')) if condition == 4: blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.75), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) elif condition == 5: blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.25), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) else: self.healthBar.setColor(SuitGlobals.healthColors[condition], 1) #self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[condition], 1) self.condition = condition def removeHealthBar(self): if self.healthBar: self.healthBar.removeNode() self.healthBar = None if self.condition == 4 or self.condition == 5: taskMgr.remove(self.taskName('blink-task')) self.healthCondition = 0 return def initializeBodyCollisions(self): self.notify.info('Initializing Body Collisions!') self.setupPhysics(2, self.getHeight()) self.enableRay() def hideSuit(self): self.hide() def showSuit(self): self.show() fadeIn = Sequence( Func(self.setTransparency, 1), self.colorScaleInterval(0.6, colorScale=Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, render)) fadeIn.start() def doStunEffect(self): self.clearStunnedIval() self.stunnedIval = SuitGlobals.createStunInterval(self, 0, 2) self.stunnedIval.start() def doGagEffect(self, flags): GagEffects.doGagEffect(self, flags) def generateCog(self, isLose=0, nameTag=True): #startTime = globalClock.getRealTime() generateCollector.start() cleanupCollector.start() self.cleanup() cleanupCollector.stop() if not isLose: if self.suitPlan in SuitBank.suitSetups: setup = SuitBank.suitSetups[self.suitPlan] else: setup = SuitBank.SuitSetup() SuitBank.suitSetups[self.suitPlan] = setup if not self.variant in setup.actor: setupActor = Actor() if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: setupActor.loadModel( 'phase_5/models/char/cog%s_robot-zero.bam' % (str(self.suit)), 'body') else: setupActor.loadModel( 'phase_3.5/models/char/suit%s-mod.bam' % (str(self.suit)), 'body') animations = SuitGlobals.animations anims = {} for anim in animations: if not self.suit in anim.getSuitTypes(): continue path = 'phase_%s/models/char/suit%s-%s.bam' % ( anim.getPhase(), self.suit, anim.getFile()) anims[anim.getName()] = path setupActor.loadAnims(anims, 'body') setup.actor[self.variant] = setupActor actorCollector.start() self.copyActor(setup.actor[self.variant]) actorCollector.stop() healthBarCollector.start() self.generateHealthBar() healthBarCollector.stop() footstepCollector.start() if self.suitPlan.suitType == SuitType.A: self.footstepSound = base.audio3d.loadSfx( "phase_5/audio/sfx/ENC_cogafssm.ogg") elif self.suitPlan.suitType == SuitType.B: self.footstepSound = base.audio3d.loadSfx( "phase_5/audio/sfx/ENC_cogbfssm.ogg") elif self.suitPlan.suitType == SuitType.C: self.footstepSound = base.audio3d.loadSfx( "phase_5/audio/sfx/ENC_cogcfssm.ogg") if self.footstepSound: base.audio3d.attachSoundToObject(self.footstepSound, self) self.footstepSound.setVolume(0.0) self.footstepSound.setLoop(True) self.footstepSound.play() footstepCollector.stop() else: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.loadModel( 'phase_5/models/char/cog%s_robot-lose-mod.bam' % (str(self.suit)), 'body') else: self.loadModel( 'phase_4/models/char/suit%s-lose-mod.bam' % (str(self.suit)), 'body') self.loadAnims( { 'lose': 'phase_4/models/char/suit%s-lose.bam' % (str(self.suit)) }, 'body') genHeadCollector.start() if self.variant != Variant.SKELETON: self.headModel = self.head.generate() self.headModel.reparentTo(self.find("**/joint_head")) if self.suitPlan.getName() == SuitGlobals.VicePresident: self.headModel.setScale(0.35) self.headModel.setHpr(270, 0, 270) self.headModel.setZ(-0.10) self.headModel.loop('neutral') if self.variant == Variant.SKELETON: self.headModel = self.find("**/joint_head") #antenna = loader.loadModel("models/police_antenna.bam") ##antenna.reparentTo(self.find("**/joint_head")) #antenna.setPos(0.5, -0.5, 0) #antenna.setScale(1.25) #antenna.clearModelNodes() #antenna.flattenStrong() genHeadCollector.stop() self.setClothes() classScale = 1.0 #self.suitPlan.getCogClassAttrs().scaleMod self.setAvatarScale( (self.suitPlan.getScale() / SuitGlobals.scaleFactors[self.suit]) * classScale) self.setHeight(self.suitPlan.getHeight()) nametagCollector.start() if nameTag: self.setupNameTag() nametagCollector.stop() Avatar.initShadow(self) if self.variant != Variant.SKELETON: # We've already done all manipulating to the cog, we can just flatten it. self.getPart('body').flattenStrong() self.postFlatten() self.headModel.flattenStrong() if isinstance(self.headModel, Actor): self.headModel.postFlatten() #endTime = globalClock.getRealTime() #print("GenerateCog took {0} seconds".format(endTime - startTime)) generateCollector.stop() def cleanup(self): if self.footstepSound: self.footstepSound.stop() self.footstepSound = None self.cleanupPropeller() self.clearChatbox() if self.shadow: self.deleteShadow() if self.headModel: self.headModel.removeNode() self.headModel = None if self.getPart('body'): self.removePart('body') self.timestampAnimTrack = None def generatePropeller(self): self.cleanupPropeller() self.propeller = Actor( 'phase_4/models/props/propeller-mod.bam', {'chan': 'phase_4/models/props/propeller-chan.bam'}) self.propeller.reparentTo(self.find("**/joint_head")) self.propellerSounds['in'] = base.audio3d.loadSfx( SuitGlobals.propellerInSfx) self.propellerSounds['out'] = base.audio3d.loadSfx( SuitGlobals.propellerOutSfx) self.propellerSounds['neutral'] = base.audio3d.loadSfx( SuitGlobals.propellerNeutSfx) for sound in self.propellerSounds.values(): base.audio3d.attachSoundToObject(sound, self.propeller) def cleanupPropeller(self): for sound in self.propellerSounds.values(): base.audio3d.detachSound(sound) sound.stop() self.propellerSounds = {} if self.propeller and not self.propeller.isEmpty(): self.propeller.cleanup() self.propeller = None def setVoice(self, voice): if not voice: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.voice = Voice.SKELETON else: self.voice = Voice.NORMAL else: self.voice = voice if self.variant == Variant.SKELETON: head = self else: head = self.headModel self.addSound("statement", self.voice.getSoundFile('statement'), node=head) self.addSound("grunt", self.voice.getSoundFile('grunt'), node=head) self.addSound("question", self.voice.getSoundFile('question'), node=head) if self.voice == Voice.NORMAL: self.addSound("question2", self.voice.getSoundFile('question_2'), node=head) self.chatSoundTable[CHAT_SHORT] = "statement" self.chatSoundTable[CHAT_MEDIUM] = "statement" self.chatSoundTable[CHAT_LONG] = "statement" self.chatSoundTable[CHAT_EXCLAIM] = "grunt" self.chatSoundTable[CHAT_HOWL] = "statement" if self.voice == Voice.NORMAL: self.chatSoundTable[CHAT_QUESTION] = ["question", "question2"] else: self.chatSoundTable[CHAT_QUESTION] = "question" def setClothes(self): setClothesCollector.start() if self.variant == Variant.SKELETON: parts = self.findAllMatches('**/pPlane*') for partNum in range(0, parts.getNumPaths()): bb = parts.getPath(partNum) bb.setTwoSided(1) tie = 'phase_5/maps/cog_robot_tie_%s.mat' % self.dept.getTie() #tie.setMinfilter(Texture.FTLinearMipmapLinear) #tie.setMagfilter(Texture.FTLinear) self.find('**/tie').setBSPMaterial(tie, 1) else: texture = 'phase_3.5/maps/tt_t_ene_' + self.dept.getName().lower( ) + '.mat' #texture = 'materials/models/suit/tt_t_ene_police.mat' #if self.variant == Variant.WAITER: # prefix = 'phase_3.5/maps/waiter_m_%s.mat' #elif self.variant == Variant.CORRODED: # prefix = 'phase_3.5/maps/' + self.dept.getClothingPrefix() + '_rust_%s.mat' #legTex = prefix % 'leg' #armTex = prefix % 'sleeve' #blazTex = prefix % 'blazer' #texs = [legTex, armTex, blazTex] #for texture in texs: # texture.setMinfilter(Texture.FTLinearMipmapLinear) # texture.setMagfilter(Texture.FTLinear) #self.find('**/legs').setBSPMaterial(legTex, 1) #self.find('**/arms').setBSPMaterial(armTex, 1) #self.find('**/torso').setBSPMaterial(blazTex, 1) #self.find('**/hands').setBSPMaterial("phase_3.5/maps/tt_t_ene_sellbotRental_hand.mat", 1) body = self.getPart('body') for child in body.getChildren(): if isinstance(child.node(), GeomNode): child.setBSPMaterial(texture, 1) if not self.variant == Variant.CORRODED: self.find('**/hands').setColor(self.handColor) else: self.find('**/hands').setColor(Variant.CORRODED_HAND_COLOR) setClothesCollector.stop() def startFootsteps(self): classAttrs = self.suitPlan.getCogClassAttrs() if not self.footstepSound or not classAttrs.footsteps: return self.footstepSound.setPlayRate(classAttrs.walkMod) self.footstepSound.setLoop(True) self.footstepSound.play() def stopFootsteps(self): if not self.footstepSound: return self.footstepSound.stop() def setSpeed(self, forwardSpeed, rotateSpeed, strafeSpeed=0.0): Avatar.setSpeed(self, forwardSpeed, rotateSpeed, strafeSpeed) currSpeed = self.currentSpeed if self.doingActivity: currSpeed = 0 if self.footstepSound and self.standWalkRunReverse is not None: action = self.getMoveAction(forwardSpeed, rotateSpeed, strafeSpeed) minSpeed = self.standWalkRunReverse[action][2] maxSpeed = self.standWalkRunReverse[action][3] self.footstepSound.setVolume( CIGlobals.clamp( CIGlobals.remapVal(currSpeed, minSpeed, maxSpeed, 0, 1), 0, 1)) self.footstepSound.setPlayRate(max(1, currSpeed / maxSpeed)) def setName(self, nameString, charName): Avatar.setName(self, nameString, charName=charName, createNow=1) def setupNameTag(self, tempName=None): Avatar.setupNameTag(self, tempName=tempName) if self.nametag: if self.level > 0: self.nametag.setText(self.nametag.getText() + '\n%s\nLevel %s %s' % (self.dept.getName(), self.level, self.suitPlan.getCogClassName())) else: self.nametag.setText(self.nametag.getText() + '\n%s' % (self.dept.getName())) def clearChatbox(self): self.clearChat() self.chat = None if self.chatDial: base.audio3d.detachSound(self.chatDial) self.chatDial.stop() self.chatDial = None def getDept(self): return self.dept def getVariant(self): return self.variant def disable(self): if self.suitTrack: self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.animFSM.requestFinalState() self.cleanup() Avatar.disable(self) def delete(self): Avatar.delete(self) self.cleanup()
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 return 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): 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() return def cleanupGag(self): if self.gag: self.gag.removeNode() self.cleanupHat()
class DistributedBattleTrolley(DistributedObject): notify = directNotify.newCategory('DistributedBattleTrolley') STAND_POSITIONS = [ Point3(-4.75, -5, 1.4), Point3(-4.75, -1.6, 1.4), Point3(-4.75, 1.6, 1.4), Point3(-4.75, 5, 1.4), Point3(-4.75, -5, 1.4), Point3(-4.75, -1.6, 1.4), Point3(-4.75, 1.6, 1.4), Point3(-4.75, 5, 1.4) ] TROLLEY_NEUTRAL_POS = Point3(15, 14, -1) TROLLEY_GONE_POS = Point3(50, 14.1588, -0.984615) TROLLEY_ARRIVING_START_POS = Point3(-20, 14.1588, -0.984615) CAM_POS = Point3(-35, 0, 8) CAM_HPR = Vec3(-90, 0, 0) def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM.ClassicFSM('DistributedBattleTrolley', [State.State('off', self.enterOff, self.exitOff), State.State('wait', self.enterWait, self.exitWait), State.State('waitCountdown', self.enterWaitCountdown, self.exitWaitCountdown), State.State('leaving', self.enterLeaving, self.exitLeaving), State.State('arriving', self.enterArriving, self.exitArriving)], 'off', 'off') self.fsm.enterInitialState() self.trolleyStation = None self.trolleyCar = None self.trolleyKey = None self.countdownText = None self.trolleyAwaySfx = base.audio3d.loadSfx('phase_4/audio/sfx/SZ_trolley_away.ogg') if self.cr.holidayManager.getHoliday() == HolidayType.CHRISTMAS: self.trolleyAwaySfx = base.audio3d.loadSfx('winter/audio/sfx/SZ_trolley_away.mp3') self.trolleyBellSfx = base.audio3d.loadSfx('phase_4/audio/sfx/SZ_trolley_bell.ogg') self.toZone = 0 self.localAvOnTrolley = False self.trolleyEnterTrack = None self.trolleyExitTrack = None self.hoodAbbr = "" self.index = 0 self.mySlot = -1 def setIndex(self, index): self.index = index hood = self.cr.playGame.hood hoodAbbr = None if self.index == 0: hoodAbbr = hood.abbr elif self.index == 1: hoodAbbr = 'TT' #ZoneUtil.ZoneId2HoodAbbr[self.toZone] self.hoodAbbr = hoodAbbr findStr = '**/prop_trolley_station_' + hoodAbbr + '_DNARoot' self.trolleyStation = hood.loader.geom.find(findStr) self.trolleyStation.flattenStrong() self.trolleyCar = self.trolleyStation.find('**/trolley_car') self.trolleyKey = self.trolleyStation.find('**/key') base.audio3d.attachSoundToObject(self.trolleyAwaySfx, self.trolleyCar) base.audio3d.attachSoundToObject(self.trolleyBellSfx, self.trolleyCar) exitFog = Fog('TrolleyExitFog') exitFog.setColor(0.0, 0.0, 0.0) exitFog.setLinearOnsetPoint(30.0, 14.0, 0.0) exitFog.setLinearOpaquePoint(37.0, 14.0, 0.0) exitFog.setLinearFallback(70.0, 999.0, 1000.0) self.trolleyExitFog = self.trolleyStation.attachNewNode(exitFog) self.trolleyExitFogNode = exitFog enterFog = Fog('TrolleyEnterFog') enterFog.setColor(0.0, 0.0, 0.0) enterFog.setLinearOnsetPoint(0.0, 14.0, 0.0) enterFog.setLinearOpaquePoint(-7.0, 14.0, 0.0) enterFog.setLinearFallback(70.0, 999.0, 1000.0) self.trolleyEnterFog = self.trolleyStation.attachNewNode(enterFog) self.trolleyEnterFogNode = enterFog self.trolleyCar.setFogOff() tn = TextNode('trolleycountdowntext') tn.setFont(CIGlobals.getMickeyFont()) tn.setTextColor(1, 0, 0, 1) tn.setAlign(TextNode.ACenter) self.keys = self.trolleyCar.findAllMatches('**/key') self.numKeys = self.keys.getNumPaths() self.keyInit = [] self.keyRef = [] for i in range(self.numKeys): key = self.keys[i] key.setTwoSided(1) ref = self.trolleyCar.attachNewNode('key' + `i` + 'ref') ref.setPosHpr(key, 0, 0, 0, 0, 0, 0) self.keyRef.append(ref) self.keyInit.append(key.getTransform()) self.frontWheels = self.trolleyCar.findAllMatches('**/front_wheels') self.numFrontWheels = self.frontWheels.getNumPaths() self.frontWheelInit = [] self.frontWheelRef = [] for i in range(self.numFrontWheels): wheel = self.frontWheels[i] ref = self.trolleyCar.attachNewNode('frontWheel' + `i` + 'ref') ref.setPosHpr(wheel, 0, 0, 0, 0, 0, 0) self.frontWheelRef.append(ref) self.frontWheelInit.append(wheel.getTransform()) self.backWheels = self.trolleyCar.findAllMatches('**/back_wheels') self.numBackWheels = self.backWheels.getNumPaths() self.backWheelInit = [] self.backWheelRef = [] for i in range(self.numBackWheels): wheel = self.backWheels[i] ref = self.trolleyCar.attachNewNode('backWheel' + `i` + 'ref') ref.setPosHpr(wheel, 0, 0, 0, 0, 0, 0) self.backWheelRef.append(ref) self.backWheelInit.append(wheel.getTransform()) trolleyAnimationReset = Func(self.resetAnimation) trolleyEnterStartPos = Point3(-20, 14, -1) trolleyEnterEndPos = Point3(15, 14, -1) trolleyEnterPos = Sequence(name='TrolleyEnterPos') trolleyEnterPos.append(Func(self.trolleyCar.setFog, self.trolleyEnterFogNode)) trolleyEnterPos.append(self.trolleyCar.posInterval(TROLLEY_ENTER_TIME, trolleyEnterEndPos, startPos=trolleyEnterStartPos, blendType='easeOut')) trolleyEnterPos.append(Func(self.trolleyCar.setFogOff)) trolleyEnterTrack = Sequence(trolleyAnimationReset, trolleyEnterPos, name='trolleyEnter') keyAngle = round(TROLLEY_ENTER_TIME) * 360 dist = Vec3(trolleyEnterEndPos - trolleyEnterStartPos).length() wheelAngle = dist / (2.0 * math.pi * 0.95) * 360 trolleyEnterAnimateInterval = LerpFunctionInterval(self.animateTrolley, duration=TROLLEY_ENTER_TIME, blendType='easeOut', extraArgs=[keyAngle, wheelAngle], name='TrolleyAnimate') trolleyEnterSoundTrack = SoundInterval(self.trolleyAwaySfx, node=self.trolleyCar) self.trolleyEnterTrack = Parallel(trolleyEnterTrack, trolleyEnterAnimateInterval, trolleyEnterSoundTrack) trolleyExitStartPos = Point3(15, 14, -1) trolleyExitEndPos = Point3(50, 14, -1) trolleyExitPos = Sequence(name='TrolleyExitPos') trolleyExitPos.append(Func(self.trolleyCar.setFog, self.trolleyExitFogNode)) trolleyExitPos.append(self.trolleyCar.posInterval(TROLLEY_EXIT_TIME, trolleyExitEndPos, startPos=trolleyExitStartPos, blendType='easeIn')) trolleyExitPos.append(Func(self.trolleyCar.setFogOff)) trolleyExitStartPos = Point3(15, 14, -1) trolleyExitEndPos = Point3(50, 14, -1) trolleyExitBellInterval = SoundInterval(self.trolleyBellSfx, node=self.trolleyCar) trolleyExitAwayInterval = SoundInterval(self.trolleyAwaySfx, node=self.trolleyCar) keyAngle = round(TROLLEY_EXIT_TIME) * 360 dist = Vec3(trolleyExitEndPos - trolleyExitStartPos).length() wheelAngle = dist / (2.0 * math.pi * 0.95) * 360 trolleyExitAnimateInterval = LerpFunctionInterval(self.animateTrolley, duration=TROLLEY_EXIT_TIME, blendType='easeIn', extraArgs=[keyAngle, wheelAngle], name='TrolleyAnimate') self.trolleyExitTrack = Parallel(trolleyExitPos, trolleyExitBellInterval, trolleyExitAwayInterval, trolleyExitAnimateInterval, name=self.uniqueName('trolleyExit')) self.countdownText = self.trolleyStation.attachNewNode(tn) self.countdownText.setScale(3.0) self.countdownText.setPos(14.58, 10.77, 11.17) try: self.trolleySphere = self.trolleyStation.find('**/trolley_sphere') self.trolleySphere.setName('trolley{0}_sphere'.format(hoodAbbr)) except: pass def getIndex(self): return self.index def putAvatarInTrolley(self, avId, slot): av = self.cr.doId2do.get(avId) if av: print "putAvatarInTrolley:", av.node().getName() av.stopSmooth() av.wrtReparentTo(self.trolleyCar) av.setAnimState('off') slotPos = self.STAND_POSITIONS[slot] av.setPos(slotPos) if slot <= 3: av.loop('sit') else: av.loop('neutral') av.setHpr(90, 0, 0) def headOff(self): if self.index == 1: zoneId = base.localAvatar.getLastHood() hoodId = ZoneUtil.getHoodId(zoneId) else: zoneId = self.toZone hoodId = ZoneUtil.getHoodId(self.toZone) requestStatus = {'zoneId': zoneId, 'hoodId': hoodId, 'where': 'playground', 'avId': base.localAvatar.doId, 'loader': 'safeZoneLoader', 'shardId': None, 'wantLaffMeter': 1, 'how': 'teleportIn', 'prevZoneId': base.localAvatar.zoneId, 'slot': self.mySlot} self.cr.playGame.getPlace().doneStatus = requestStatus messenger.send(self.cr.playGame.getPlace().doneEvent) base.localAvatar.reparentTo(render) base.localAvatar.setPos(0, 0, 0) base.localAvatar.setHpr(0, 0, 0) base.localAvatar.walkControls.setCollisionsActive(1) self.localAvOnTrolley = False def setToZone(self, zone): self.toZone = zone def getToZone(self): return self.toZone def enterOff(self, ts = 0): pass def exitOff(self): pass def __maybeAcceptCollisions(self): if self.fsm.getCurrentState().getName() in ['wait', 'waitCountdown'] and not self.localAvOnTrolley: self.acceptOnce('entertrolley{0}_sphere'.format(self.hoodAbbr), self.__handleTrolleyTrigger) def __ignoreCollisions(self): self.ignore('entertrolley{0}_sphere'.format(self.hoodAbbr)) def enterWait(self, ts = 0): self.trolleyCar.setPos(self.TROLLEY_NEUTRAL_POS) self.__maybeAcceptCollisions() def exitWait(self): self.__ignoreCollisions() def enterWaitCountdown(self, ts = 0): self.trolleyCar.setPos(self.TROLLEY_NEUTRAL_POS) self.__maybeAcceptCollisions() if self.countdownText: self.countdownTrack = Sequence() for i in range(10): self.countdownTrack.append(Func(self.countdownText.node().setText, str(10 - i))) self.countdownTrack.append(Wait(1.0)) self.countdownTrack.start() def exitWaitCountdown(self): self.__ignoreCollisions() if hasattr(self, 'countdownTrack'): self.countdownTrack.finish() del self.countdownTrack if self.countdownText: self.countdownText.node().setText('') self.disableExitButton() def enterArriving(self, ts = 0): if self.localAvOnTrolley == True: CIGlobals.hideWaitForOthers() camera.wrtReparentTo(self.trolleyCar) camera.setPos(0, -18.55, 3.75) camera.setHpr(0, 0, 0) Sequence(Wait(2.0), camera.posHprInterval(3, self.CAM_POS, self.CAM_HPR, startPos = (0, -18.55, 3.75), startHpr = (0, 0, 0), blendType='easeInOut')).start() self.trolleyEnterTrack.start(ts) def exitArriving(self): if self.trolleyEnterTrack: self.trolleyEnterTrack.finish() def enterLeaving(self, ts = 0): base.playSfx(self.trolleyBellSfx, node = self.trolleyCar) if self.localAvOnTrolley == True: camera.posHprInterval(3, (0, 18.55, 3.75), (-180, 0, 0), blendType='easeInOut').start() self.trolleyExitTrack.append(Sequence(Wait(4.0), Func(base.transitions.fadeOut), Wait(1.0), Func(self.headOff))) self.trolleyExitTrack.start(ts) self.__ignoreCollisions() def exitLeaving(self): if self.trolleyExitTrack: self.trolleyExitTrack.finish() def setState(self, stateName, timestamp): ts = globalClockDelta.localElapsedTime(timestamp) self.fsm.request(stateName, [ts]) def __handleTrolleyTrigger(self, collNp): # workaround for a bug that i don't understand why it happens if not hasattr(self, 'cr') or not self.cr: self.cr = base.cr self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.disableGags() self.notify.info('Waiting for response from server to enter trolley') self.sendUpdate('requestBoard') base.localAvatar.walkControls.setCollisionsActive(0) def rejectBoard(self): base.localAvatar.walkControls.setCollisionsActive(1) self.cr.playGame.getPlace().fsm.request('walk') self.__maybeAcceptCollisions() def fillSlot(self, index, avId): if avId == base.localAvatar.doId: self.localAvOnTrolley = True base.localAvatar.stopSmartCamera() base.camera.wrtReparentTo(self.trolleyCar) camTrack = Sequence(Parallel( LerpPosInterval( base.camera, duration = 1.5, pos = self.CAM_POS, startPos = base.camera.getPos(), blendType = 'easeOut' ), LerpQuatInterval( base.camera, duration = 1.5, hpr = self.CAM_HPR, startHpr = base.camera.getHpr(), blendType = 'easeOut' ) ), Func(self.enableExitButton)) camTrack.start() self.mySlot = index toon = self.cr.doId2do.get(avId) toon.stopSmooth() if toon: toon.wrtReparentTo(self.trolleyCar) slotPos = self.STAND_POSITIONS[index] toon.headsUp(slotPos) track = Sequence( Func(toon.setAnimState, 'run'), LerpPosInterval(toon, 0.75, slotPos), LerpHprInterval(toon, 0.25, Point3(90, 0, 0))) if index <= 3: sitStartDuration = toon.getDuration('start-sit') track.append(Parallel(ActorInterval(toon, 'start-sit'), Sequence(Wait(sitStartDuration * 0.25), LerpPosInterval(toon, sitStartDuration * 0.25, Point3(-3.9, -4.5 + index * 3, 3.0))))) track.append(Func(toon.loop, 'sit')) else: track.append(Func(toon.loop, 'neutral')) track.start() def enableExitButton(self): if self.fsm.getCurrentState().getName() != 'leaving': self.exitButton = CIGlobals.getExitButton(cmd = self.__handleExitButton, pos = (0, 0, -0.8)) def __handleExitButton(self): if self.fsm.getCurrentState().getName() == 'waitCountdown' and self.localAvOnTrolley == True: self.disableExitButton() self.sendUpdate('requestHopOff') def disableExitButton(self): if hasattr(self, 'exitButton'): self.exitButton.destroy() del self.exitButton def emptySlot(self, index, avId): toon = self.cr.doId2do.get(avId) toon.stopSmooth() currToonPos = toon.getPos(render) toon.wrtReparentTo(render) slotPos = self.STAND_POSITIONS[index] endPos = (-20, slotPos.getY(), 1.4) toon.setPos(self.trolleyCar, endPos) endPosWrtRender = toon.getPos(render) toon.setPos(currToonPos) toon.headsUp(self.trolleyCar, endPos) if index <= 3: track = Sequence(Parallel( ActorInterval(toon, 'start-sit', startTime=1, endTime=0.0), Sequence(Wait(0.5), LerpPosInterval(toon, 0.25, Point3(-5, -4.5 + index * 3, 1.4), other=self.trolleyCar))), Func(toon.setAnimState, 'run'), LerpPosInterval(toon, 1, Point3(21 - index * 3, -5, 0.02), other=self.trolleyStation), Func(toon.setAnimState, 'neutral'), Func(toon.startSmooth), name=toon.uniqueName('emptyTrolley'), autoPause=1) else: track = Sequence( Func(toon.setAnimState, 'run'), LerpPosInterval( toon, duration = 1.0, pos = endPosWrtRender, startPos = currToonPos ), Func(toon.setAnimState, 'neutral'), Func(toon.startSmooth) ) if avId == base.localAvatar.doId: self.localAvOnTrolley = False track.append(Func(self.__hoppedOffTrolley)) track.start() def __hoppedOffTrolley(self): #self.acceptOnce('entertrolley_sphere', self.__handleTrolleyTrigger) base.localAvatar.walkControls.setCollisionsActive(1) self.cr.playGame.getPlace().fsm.request('walk') def resetAnimation(self): if self.keys: for i in range(self.numKeys): self.keys[i].setTransform(self.keyInit[i]) for i in range(self.numFrontWheels): self.frontWheels[i].setTransform(self.frontWheelInit[i]) for i in range(self.numBackWheels): self.backWheels[i].setTransform(self.backWheelInit[i]) def animateTrolley(self, t, keyAngle, wheelAngle): if self.keys: for i in range(self.numKeys): key = self.keys[i] ref = self.keyRef[i] key.setH(ref, t * keyAngle) for i in range(self.numFrontWheels): frontWheel = self.frontWheels[i] ref = self.frontWheelRef[i] frontWheel.setH(ref, t * wheelAngle) for i in range(self.numBackWheels): backWheel = self.backWheels[i] ref = self.backWheelRef[i] backWheel.setH(ref, t * wheelAngle) def delete(self): self.__ignoreCollisions() self.trolleyStation = None self.trolleyKey = None self.soundMoving = None self.soundBell = None self.troleyCar = None self.backWheelInit = None self.backWheelRef = None self.backWheels = None self.frontWheelInit = None self.frontWheelRef = None self.frontWheels = None self.keyInit = None self.keyRef = None self.keys = None self.trolleyEnterTrack = None self.trolleyExitTrack = None self.trolleyExitFog = None self.trolleyExitFogNode = None self.trolleyEnterFogNode = None self.trolleyEnterFog = None if self.countdownText: self.countdownText.removeNode() self.countdownText = None DistributedObject.delete(self)
class DistributedCityCart(DistributedNode): notify = directNotify.newCategory('DistributedCityCart') def __init__(self, cr): DistributedNode.__init__(self, cr) self.fsm = ClassicFSM('DistributedCityCart', [State('off', self.enterOff, self.exitOff), State('pathFollow', self.enterPathFollow, self.exitPathFollow), State('collision', self.enterCollision, self.exitCollision)], 'off', 'off') self.fsm.enterInitialState() self.suitInCar = None self.cart = None self.honkSfxPath = 'phase_14/audio/sfx/cogtropolis_citycar_driveby_horn.mp3' self.cartModelPath = 'phase_12/models/bossbotHQ/Coggolf_cart3.bam' self.moPaths = ['phase_14/models/paths/ct-citycar-drivepath-1.egg', 'phase_14/models/paths/ct-citycar-drivepath-2.egg', 'phase_14/models/paths/ct-citycar-drivepath-3.egg', 'phase_14/models/paths/ct-citycar-drivepath-4.egg', 'phase_14/models/paths/ct-citycar-drivepath-5.egg', 'phase_14/models/paths/ct-citycar-drivepath-6.egg'] self.moPath = None self.soundEngineLoop = None self.soundDriveByHorn = None self.ivalTDisplace = None self.pathIndex = None self.wheelSpinTrack = None self.collNodePath = None self.soundDriveBy = None return def setIvalTDisplace(self, displace): self.ivalTDisplace = displace def setPathIndex(self, index): self.pathIndex = index def setState(self, state, timestamp): ts = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.fsm.request(state, [ts]) def enterOff(self): pass def exitOff(self): pass def enterPathFollow(self, ts): duration = CityCartGlobals.index2Duration[self.pathIndex] self.moPath = NURBSMopath.NURBSMopath(self.moPaths[self.pathIndex], name=self.uniqueName('DCityCart_moPath')) startT = 0.0 if ts > 0.0: startT = ts % duration * (1.0 / duration) self.moPath.play(self, loop=True, duration=duration, startT=startT) base.taskMgr.add(self.__drive, self.uniqueName('DCityCart.drive')) self.wheelSpinTrack = Parallel() for name in ['leftFrontWheel', 'rightBackWheel', 'rightFrontWheel', 'leftBackWheel']: wheel = self.find('**/' + name) self.wheelSpinTrack.append(LerpHprInterval(wheel, duration=0.1, hpr=(0, 360, 0), startHpr=(0, 0, 0))) self.wheelSpinTrack.loop() self.accept('enter' + self.collNodePath.node().getName(), self.__handleRanOver) def __handleRanOver(self, entry): self.suitInCar.setChat(CityCartGlobals.SuitRanOverTaunt) self.sendUpdate('hitByCar') self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.b_setAnimState('squish', callback=self.cr.playGame.getPlace().fsm.request, extraArgs=['walk']) def __drive(self, task): if base.localAvatar.getDistance(self) < 10.0: if self.soundDriveByHorn.status() == self.soundDriveByHorn.READY: wantsToHonk = random.randint(0, 3) if wantsToHonk == 3: base.playSfx(self.soundDriveByHorn) return task.cont elif base.localAvatar.getDistance(self) < 20.0: if self.soundDriveBy.status() == self.soundDriveBy.READY: base.playSfx(self.soundDriveBy) return task.cont return task.cont def exitPathFollow(self): self.ignore('enter' + self.collNodePath.node().getName()) if self.wheelSpinTrack: self.wheelSpinTrack.finish() self.wheelSpinTrack = None if self.moPath: self.moPath.stop() self.moPath = None return def enterCollision(self, ts): pass def exitCollision(self): pass def generate(self): DistributedNode.generate(self) self.cart = loader.loadModel(self.cartModelPath) self.cart.reparentTo(self) self.cart.setH(180) heads = [] for head in CIGlobals.SuitBodyData.keys(): if CIGlobals.SuitBodyData[head][0] != 'B': heads.append(head) head = random.choice(heads) suitType = CIGlobals.SuitBodyData[head][0] suitDept = CIGlobals.SuitBodyData[head][1] self.suitInCar = Suit() self.suitInCar.generateSuit(suitType, head, suitDept, 137, 0, False) self.suitInCar.loop('sit') self.suitInCar.disableRay() self.suitInCar.setScale(0.7) self.suitInCar.setH(180) self.suitInCar.setPos(0, -1, -1.5) self.suitInCar.reparentTo(self.cart.find('**/seat1')) self.soundEngineLoop = base.audio3d.loadSfx('phase_6/audio/sfx/KART_Engine_loop_0.wav') base.audio3d.attachSoundToObject(self.soundEngineLoop, self) base.playSfx(self.soundEngineLoop, looping=1) self.soundDriveByHorn = base.audio3d.loadSfx(self.honkSfxPath) base.audio3d.attachSoundToObject(self.soundDriveByHorn, self) self.soundDriveBy = base.audio3d.loadSfx('phase_14/audio/sfx/cogtropolis_citycar_driveby.mp3') base.audio3d.attachSoundToObject(self.soundDriveBy, self) sphere = CollisionSphere(0, 0, 0, 2.5) sphere.setTangible(0) node = CollisionNode(self.uniqueName('cartSphere')) node.setCollideMask(CIGlobals.WallBitmask) node.addSolid(sphere) self.collNodePath = self.attachNewNode(node) self.collNodePath.setZ(1.5) self.collNodePath.setSy(2.0) self.collNodePath.setSx(1.75) def disable(self): self.fsm.requestFinalState() if self.moPath: self.moPath.stop() self.moPath = None self.moPaths = None self.honkSfxPath = None self.cartModelPath = None self.soundEngineLoop = None self.soundDriveBy = None if self.suitInCar: self.suitInCar.disable() self.suitInCar.delete() self.suitInCar = None if self.cart: self.cart.removeNode() self.cart = None del self.fsm DistributedNode.disable(self) return
class CogThief(DirectObject): notify = directNotify.newCategory('CogThief') DefaultSpeedWalkAnim = 4.0 CollisionRadius = 1.25 MaxFriendsVisible = 4 Infinity = 100000.0 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) 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 self.velocity = Vec3(0, 0, 0) self.oldVelocity = Vec3(0, 0, 0) self.acceleration = Vec3(0, 0, 0) self.bodyLength = self.CollisionRadius * 2 self.cruiseDistance = 2 * self.bodyLength self.maxVelocity = self.cogSpeed 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): 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() self.suit.loop('neutral') def initCollisions(self): self.collSphere = CollisionSphere(0, 0, 0, 1.25) 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.accept('enter' + self.collSphereName, self.handleEnterSphere) self.pieCollSphere = CollisionTube(0, 0, 0, 0, 0, 4, self.CollisionRadius) 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) 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): self.notify.debug('self.netTimeSentToStartByHit =%s' % self.netTimeSentToStartByHit) if not self.game: self.notify.debug('updateGoal self.game is None, just returning') return None if not self.suit: self.notify.debug('updateGoal self.suit is None, just returning') return None 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: pass 1 if inResponseClientStamp < self.netTimeSentToStartByHit and self.goal == CTGG.NoGoal and goalType == CTGG.RunAwayGoal: 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 def startWalkAnim(self): if self.suit: self.suit.loop('walk') speed = self.cogSpeed self.defaultPlayRate = float(self.cogSpeed / self.DefaultSpeedWalkAnim) self.suit.setPlayRate(self.defaultPlayRate, 'walk') def think(self): 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 None 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): 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): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) gameTime = self.game.local2GameTime(localStamp) return gameTime def respondToToonHit(self, timestamp): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) if self.netTimeSentToStartByHit < timestamp: self.clearGoal() self.showKaboom() 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): self.goal = CTGG.NoGoal self.goalId = CTGG.InvalidGoalId def thinkAboutGettingBarrel(self): if not self.game: return None if not hasattr(self.game, 'barrels'): return None if self.goalId not in xrange(len(self.game.barrels)): return None 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) self.doneAdjust = True displacement = barrelPos - myPos distanceToToon = displacement.length() self.suit.headsUp(barrel) lengthTravelled = diffTime * self.cogSpeed if lengthTravelled > distanceToToon: lengthTravelled = distanceToToon displacement.normalize() dirVector = displacement dirVector *= lengthTravelled newPos = myPos + dirVector newPos.setZ(0) self.suit.setPos(newPos) self.adjustPlayRate(newPos, myPos, diffTime) self.lastThinkTime = globalClock.getFrameTime() def stopWalking(self, timestamp): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) if localStamp > self.lastLocalTimeStampFromAI: self.suit.loop('neutral') self.clearGoal() def thinkAboutRunAway(self): if not self.game: return None 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) self.doneAdjust = True displacement = returnPos - myPos distanceToToon = displacement.length() tempNp = render.attachNewNode('tempRet') tempNp.setPos(returnPos) self.suit.headsUp(tempNp) tempNp.removeNode() lengthTravelled = diffTime * self.cogSpeed if lengthTravelled > distanceToToon: lengthTravelled = distanceToToon displacement.normalize() dirVector = displacement dirVector *= lengthTravelled newPos = myPos + dirVector 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: self.game.sendCogAtReturnPos(self.cogIndex, self.barrel) self.signalledAtReturnPos = True self.lastThinkTime = globalClock.getFrameTime() def makeCogCarryBarrel(self, timestamp, inResponseClientStamp, barrelModel, barrelIndex, cogPos): if not self.game: return None localTimeStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) 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): localTimeStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) self.lastLocalTimeStampFromAI = localTimeStamp barrelModel.reparentTo(render) barrelModel.setPos(barrelPos) self.barrel = CTGG.NoBarrelCarried def respondToPieHit(self, timestamp): localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32) if self.netTimeSentToStartByHit < timestamp: self.clearGoal() self.showSplat() 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): 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): 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): if not self.lastThinkTime: self.lastThinkTime = globalClock.getFrameTime() dt = globalClock.getFrameTime() - self.lastThinkTime self.oldpos = self.suit.getPos() pos = self.suit.getPos() pos += self.velocity * dt self.suit.setPos(pos) self.seeFriends() acc = Vec3(0, 0, 0) self.accumulate(acc, self.getTargetVector()) if self.numFlockmatesSeen > 0: keepDistanceVector = self.keepDistance() oldAcc = Vec3(acc) self.accumulate(acc, keepDistanceVector) if self.cogIndex == 0: pass if acc.length() > self.maxAcceleration: acc.normalize() acc *= self.maxAcceleration self.oldVelocity = self.velocity self.velocity += acc if self.velocity.length() > self.maxVelocity: self.velocity.normalize() self.velocity *= self.maxVelocity forwardVec = Vec3(1, 0, 0) heading = rad2Deg(math.atan2(self.velocity[1], self.velocity[0])) heading -= 90 self.suit.setH(heading) def getTargetVector(self): 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): accumulator += valueToAdd return accumulator.length() def seeFriends(self): 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 dist != self.Infinity return self.numFlockmatesSeen def clearVisibleList(self): self.visibleFriendsList = [] self.numFlockmatesSeen = 0 self.nearestFlockmate = None self.distToNearestFlockmate = self.Infinity def addToVisibleList(self, cogIndex): if self.numFlockmatesSeen < self.MaxFriendsVisible: self.visibleFriendsList.append(cogIndex) self.numFlockmatesSeen += 1 if self.cogIndex == 0: pass def canISee(self, cogIndex): if self.cogIndex == cogIndex: return self.Infinity cogThief = self.game.getCogThief(cogIndex) distance = self.suit.getDistance(cogThief.suit) if distance < self.perceptionRange: return distance return self.Infinity def sameGoal(self, cogIndex): cogThief = self.game.getCogThief(cogIndex) if cogThief.goalId == self.goalId: pass result = cogThief.goal == self.goal return result def keepDistance(self): 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 if self.distToNearestFlockmate < self.SeparationDistance: change.normalize() change *= -(1 - ratio) elif self.distToNearestFlockmate > self.SeparationDistance: change.normalize() change *= ratio else: change = Vec3(0, 0, 0) return change def showKaboom(self): 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): 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.10000000000000001, 0.10000000000000001, 0.10000000000000001), blendType='easeOut'), Func(self.splat.hide))) self.kaboomTrack.start()
class LightDropGag(DropGag): def __init__(self, name, model, anim, damage, hitSfx, missSfx, rotate90=False, sphereSize=2, sphereZ=0): DropGag.__init__(self, name, model, anim, damage, hitSfx, missSfx, scale=1, playRate=1) DropGag.setShadowData(self, isCircle=True, shadowScale=0.5) self.stunTime = 1.5 self.objTrack = None self.rotate90 = rotate90 self.sphereSize = sphereSize self.sphereZ = sphereZ def startDrop(self): if self.gag and self.dropLoc: x, y, z = self.dropLoc startPos = Point3(x, y, z + 20) self.gag.setPos(x, y + 2, z) self.gag.node().setBounds(OmniBoundingVolume()) self.gag.node().setFinal(1) self.gag.headsUp(self.avatar) if self.rotate90: self.gag.setH(self.gag.getH() - 90) self.buildCollisions() objectTrack = Sequence() animProp = LerpPosInterval(self.gag, self.fallDuration, self.dropLoc, startPos=startPos) bounceProp = Effects.createZBounce(self.gag, 2, self.dropLoc, 0.5, 1.5) objAnimShrink = Sequence(Wait(0.5), Func(self.gag.reparentTo, render), animProp, bounceProp) objectTrack.append(objAnimShrink) dropShadow = loader.loadModel( 'phase_3/models/props/drop_shadow.bam') dropShadow.reparentTo(render) dropShadow.setPos(self.dropLoc) dropShadow.setScale(self.getShadowScale()) shadowTrack = Sequence( LerpScaleInterval(dropShadow, self.fallDuration + 0.1, dropShadow.getScale(), startScale=Point3(0.01, 0.01, 0.01)), Wait(0.3), Func(dropShadow.removeNode)) self.objTrack = Parallel( Sequence(Wait(self.fallDuration), Func(self.completeDrop)), objectTrack, shadowTrack) self.objTrack.start() self.dropLoc = None def onActivate(self, ignore, suit): self.objTrack.finish() self.objTrack = None if not suit.isDead(): suit.setAnimState('drop-react') suit.d_disableMovement(wantRay=True) if not self.gag or self.gag.isEmpty(): self.build() self.gag.setPos(suit.find('**/joint_head').getPos(render)) if self.name == CIGlobals.FlowerPot: self.gag.setZ(self.gag, 3) bounce = Effects.createScaleZBounce(self.gag, 1, self.gag.getScale(render), 0.3, 0.75) dummyNode = suit.attachNewNode('fallOffNode') dummyNode.setX(2) dummyNode.setY(-2) flightIval = FlightProjectileInterval(self.gag, startPos=self.gag.getPos(render), endPos=dummyNode.getPos(render), duration=0.8, gravityMult=.35) Sequence(Parallel(bounce, flightIval), Wait(self.stunTime), Func(suit.d_enableMovement)).start() dummyNode.removeNode() del dummyNode def buildCollisions(self): gagSph = CollisionSphere(0, 0, self.sphereZ, self.sphereSize) gagSensor = CollisionNode('gagSensor') gagSensor.addSolid(gagSph) sensorNP = self.gag.attachNewNode(gagSensor) sensorNP.setCollideMask(BitMask32(0)) sensorNP.node().setFromCollideMask(CIGlobals.WallBitmask | CIGlobals.FloorBitmask) event = CollisionHandlerEvent() event.set_in_pattern("%fn-into") event.set_out_pattern("%fn-out") base.cTrav.addCollider(sensorNP, event) self.avatar.acceptOnce('gagSensor-into', self.onCollision)
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.track = None self.state = None self.animBoat1Track = None self.animBoatTrack = None # Variables that handle the winter collision node. self.crashColl = None self.crashCollNP = None def __handleOnBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPDonaldsBoat) def __handleOffBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPRender) base.localAvatar.setR(0) base.localAvatar.setP(0) def generate(self): DistributedObject.generate(self) self.soundFogHorn = base.audio3d.loadSfx(self.fogHorn) self.soundShipBell = base.audio3d.loadSfx(self.shipBell) self.soundWaterLap = base.audio3d.loadSfx(self.waterLap) self.soundDockCreak = base.audio3d.loadSfx(self.dockCreak) geom = self.cr.playGame.hood.loader.geom self.boatMdl = geom.find('**/*donalds_boat*') self.boat = geom.find("**/ddBoatRoot") self.boatMdl1 = geom.find("**/ddBoatMdl1") base.audio3d.attachSoundToObject(self.soundFogHorn, self.boat) base.audio3d.attachSoundToObject(self.soundShipBell, self.boat) base.audio3d.attachSoundToObject(self.soundWaterLap, self.boat) base.audio3d.attachSoundToObject(self.soundDockCreak, self.boat) self.soundWaterLap.setLoop(True) self.soundWaterLap.play() 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.boatMdl) self.accept('enterdonalds_boat_floor', self.__handleOnBoat) self.accept('exitdonalds_boat_floor', self.__handleOffBoat) self.d_requestCurrentStateAndTimestamp() self.fsm.enterInitialState() speedFactor = 2 self.animBoatTrack = Sequence( LerpHprInterval(self.boatMdl, duration=1 * speedFactor, hpr=(0, 0, -1), startHpr=(0, 0, 1), blendType='easeInOut'), LerpHprInterval(self.boatMdl, duration=1 * speedFactor, hpr=(0, 0, 1), startHpr=(0, 0, -1), blendType='easeInOut')) import math self.animBoat1Track = Sequence( LerpHprInterval(self.boatMdl1, duration=math.pi * speedFactor, hpr=(0, 1, 0), startHpr=(0, -1, 0), blendType='easeInOut'), LerpHprInterval(self.boatMdl1, duration=math.pi * speedFactor, hpr=(0, -1, 0), startHpr=(0, 1, 0), blendType='easeInOut')) self.animBoat1Track.loop() self.animBoatTrack.loop() if base.cr.holidayManager.getHoliday() == HolidayType.CHRISTMAS: self.boat.setPosHpr(12.73, -1.6, -4.7, 341.57, 350.0, 26.5) self.fsm.request('off') self.crashColl = CollisionSphere(0, 0, 0, 15) self.crashCollNP = self.boat.attachNewNode( CollisionNode('crashed_boat_collision')) self.crashCollNP.node().addSolid(self.crashColl) self.crashCollNP.node().setCollideMask(CIGlobals.WallBitmask) self.crashCollNP.setSz(2) self.crashCollNP.setSx(0.75) self.crashCollNP.setSy(1.25) self.crashCollNP.setPosHpr(2.05, 3.21, 1.66, 8.44, 6.93, 332.61) 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() if self.animBoat1Track: self.animBoat1Track.finish() self.animBoat1Track = None if self.animBoatTrack: self.animBoatTrack.finish() self.animBoatTrack = None if self.crashCollNP: self.crashCollNP.removeNode() del self.crashCollNP del self.crashColl del self.fsm del self.soundFogHorn del self.soundShipBell self.soundWaterLap.stop() del self.soundWaterLap del self.soundDockCreak self.fogHorn = None self.shipBell = None self.waterLap = None self.dockCreak = None self.boat = None self.boatMdl = None self.boatMdl1 = 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 is None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.state = state if self.boat and base.cr.holidayManager.getHoliday( ) != HolidayType.CHRISTMAS: self.fsm.request(state, [ts]) def enterEastToWest(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.eastWest) moIval = MopathInterval(moPath, self.boat, blendType='easeInOut') 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), blendType='easeInOut'), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierUpP, 0), startHpr=(-90, self.pierDownP, 0), blendType='easeInOut'), 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, blendType='easeInOut') 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), blendType='easeInOut'), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierUpP, 0), startHpr=(90, self.pierDownP, 0), blendType='easeInOut'), 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
class Place(StateData): notify = directNotify.newCategory('Place') def __init__(self, loader, doneEvent): StateData.__init__(self, doneEvent) self.loader = loader self.zoneId = None self.track = None return def maybeUpdateAdminPage(self): if self.fsm: if self.fsm.getCurrentState(): if self.fsm.getCurrentState().getName() == 'shtickerBook': if hasattr(self, 'shtickerBookStateData'): if self.shtickerBookStateData.fsm.getCurrentState().getName() == 'adminPage': if base.cr.playGame.suitManager: text2Change2 = 'Turn Suit Spawner ' if base.cr.playGame.suitManager.getSpawner(): text2Change2 += 'Off' else: text2Change2 += 'On' self.shtickerBookStateData.adminPageStateData.suitSpawnerBtn['text'] = text2Change2 def enterStart(self): pass def exitStart(self): pass def enterFinal(self): pass def exitFinal(self): pass def enter(self): StateData.enter(self) base.localAvatar.createChatInput() def exit(self): base.localAvatar.disableChatInput() StateData.exit(self) def enterDoorIn(self, distDoor): base.localAvatar.attachCamera() requestStatus = {} requestStatus['zoneId'] = distDoor.getToZone() requestStatus['hoodId'] = base.cr.playGame.hood.id requestStatus['how'] = 'doorOut' requestStatus['shardId'] = None requestStatus['doorIndex'] = distDoor.getDoorIndex() foundBlock = False for interior in base.cr.doFindAll('DistributedToonInterior'): if interior.zoneId == base.localAvatar.zoneId: foundBlock = True requestStatus['block'] = interior.getBlock() break if not foundBlock: requestStatus['block'] = distDoor.getBlock() requestStatus['where'] = ZoneUtil.getWhereName(requestStatus['zoneId']) requestStatus['loader'] = base.cr.playGame.hood.fsm.getCurrentState().getName() requestStatus['avId'] = base.localAvatar.doId self.acceptOnce('DistributedDoor_localAvatarWentInDoor', self.handleDoorInDone, [requestStatus]) self.acceptOnce('DistributedDoor_localAvatarGoingInDoor', base.transitions.irisOut) return def exitDoorIn(self): base.localAvatar.detachCamera() self.ignore('DistributedDoor_localAvatarWentInDoor') self.ignore('DistributedDoor_localAvatarGoingInDoor') def handleDoorInDone(self, requestStatus): self.doneStatus = requestStatus messenger.send(self.doneEvent) def __waitOnDoor(self, door, task): if door.ready: self.__doorReady(door) return task.done return task.cont def enterDoorOut(self, requestStatus): base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.d_clearSmoothing() base.localAvatar.stopPosHprBroadcast() base.localAvatar.walkControls.setCollisionsActive(0) block = requestStatus['block'] zoneId = requestStatus['zoneId'] doorIndex = requestStatus['doorIndex'] doorToExitFrom = None for door in base.cr.doFindAll('DistributedDoor'): if door.zoneId == zoneId: if door.getBlock() == block: if door.getDoorIndex() == doorIndex: doorToExitFrom = door break if not doorToExitFrom: self.notify.error('Could not find a DistributedDoor to exit from!') elif not doorToExitFrom.ready: base.taskMgr.add(self.__waitOnDoor, 'Place.waitOnDoor', extraArgs=[doorToExitFrom], appendTask=True) return self.__doorReady(doorToExitFrom) return def __doorReady(self, door): door.sendUpdate('requestExit', []) self.nextState = 'walk' self.acceptOnce('DistributedDoor_localAvatarCameOutOfDoor', self.handleDoorOutDone) def exitDoorOut(self): base.taskMgr.remove('Place.waitOnDoor') base.localAvatar.stopSmartCamera() base.localAvatar.detachCamera() self.ignore('DistributedDoor_localAvatarCameOutOfDoor') def handleDoorOutDone(self): base.transitions.irisIn() base.localAvatar.walkControls.setCollisionsActive(1) self.fsm.request(self.nextState) def enterShtickerBook(self): base.localAvatar.attachCamera() base.localAvatar.createLaffMeter() base.localAvatar.startSmartCamera() base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.b_setAnimState('openBook', self.enterShtickerBookGui) def enterShtickerBookGui(self): doneEvent = 'shtickerBookDone' self.shtickerBookStateData = ShtickerBook(self.fsm, doneEvent) self.acceptOnce(doneEvent, self.__shtickerBookDone) self.shtickerBookStateData.load() self.shtickerBookStateData.enter() base.localAvatar.showBookButton(1) base.localAvatar.b_setAnimState('readBook') def __shtickerBookDone(self): doneStatus = self.shtickerBookStateData.getDoneStatus() base.localAvatar.hideBookButton() self.shtickerBookStateData.exit() if doneStatus['mode'] == 'exit': base.localAvatar.b_setAnimState('closeBook', self.__handleBookCloseExit) elif doneStatus['mode'] == 'teleport': base.localAvatar.b_setAnimState('closeBook', self.__handleBookCloseTeleport, [doneStatus]) elif doneStatus['mode'] == 'resume': base.localAvatar.b_setAnimState('closeBook', self.__handleBookCloseResume) elif doneStatus['mode'] == 'switchShard': base.localAvatar.b_setAnimState('closeBook', self.__handleBookCloseSwitchShard, [doneStatus]) def __handleBookCloseSwitchShard(self, requestStatus): base.localAvatar.b_setAnimState('teleportOut', self.__handleBookSwitchShard, [requestStatus]) def __handleBookSwitchShard(self, requestStatus): params = [] params.append(requestStatus['shardId']) params.append(base.cr.playGame.hood.id) params.append(ZoneUtil.getZoneId(base.cr.playGame.hood.id)) params.append(base.localAvatar.doId) base.cr.gameFSM.request('switchShards', params) def __handleBookCloseResume(self): self.fsm.request('walk') def __handleBookCloseTeleport(self, requestStatus): self.fsm.request('teleportOut', [requestStatus]) def __teleportOutDone(self, requestStatus): self.doneStatus = requestStatus messenger.send(self.doneEvent) def __handleBookCloseExit(self): base.localAvatar.b_setAnimState('teleportOut', self.__handleBookExitTeleport) def __handleBookExitTeleport(self): base.transitions.fadeOut(0.0) base.cr.gameFSM.request('closeShard') def exitShtickerBook(self): base.localAvatar.detachCamera() base.localAvatar.stopSmartCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.disableLaffMeter() self.ignore(self.shtickerBookStateData.doneEvent) self.shtickerBookStateData.exit() self.shtickerBookStateData.unload() del self.shtickerBookStateData base.localAvatar.hideBookButton() def enterStop(self, doNeutral = 1): if doNeutral: base.localAvatar.b_setAnimState('neutral') base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.createLaffMeter() base.localAvatar.createMoney() base.localAvatar.enablePies(0) def exitStop(self): base.localAvatar.stopSmartCamera() base.localAvatar.detachCamera() base.localAvatar.disableLaffMeter() base.localAvatar.disableMoney() base.localAvatar.disablePies() def load(self): StateData.load(self) self.walkDoneEvent = 'walkDone' self.walkStateData = PublicWalk(self.fsm, self.walkDoneEvent) self.walkStateData.load() def unload(self): StateData.unload(self) del self.walkDoneEvent self.walkStateData.unload() del self.walkStateData del self.loader def enterTeleportIn(self, requestStatus): if requestStatus['avId'] != base.localAvatar.doId: av = base.cr.doId2do.get(requestStatus['avId']) if av: base.localAvatar.gotoNode(av) base.localAvatar.b_setChat('Hi, %s.' % av.getName()) base.transitions.irisIn() self.nextState = requestStatus.get('nextState', 'walk') base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.startPosHprBroadcast() globalClock.tick() base.localAvatar.b_setAnimState('teleportIn', callback=self.teleportInDone) base.localAvatar.d_broadcastPositionNow() base.localAvatar.b_setParent(CIGlobals.SPRender) def exitTeleportIn(self): base.localAvatar.stopSmartCamera() base.localAvatar.detachCamera() base.localAvatar.stopPosHprBroadcast() def teleportInDone(self): if hasattr(self, 'fsm'): self.fsm.request(self.nextState, [1]) def enterAcknowledgeDeath(self, foo = 0): base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() message = 'You were defeated by the Cogs! Collect treasures in the Playground to refill your Laff meter.' self.dialog = GlobalDialog(message=message, style=3, doneEvent='ackDeathDone') self.dialog.show() self.acceptOnce('ackDeathDone', self.handleAckDeathDone) def handleAckDeathDone(self): self.fsm.request('walk', [1]) def exitAcknowledgeDeath(self): self.ignore('ackDeathDone') self.dialog.cleanup() del self.dialog base.localAvatar.stopSmartCamera() base.localAvatar.detachCamera() def enterDied(self, requestStatus, callback = None): if callback == None: callback = self.__diedDone base.localAvatar.createLaffMeter() base.localAvatar.attachCamera() base.localAvatar.b_setAnimState('died', callback, [requestStatus]) return def __diedDone(self, requestStatus): self.doneStatus = requestStatus messenger.send(self.doneEvent) def exitDied(self): base.localAvatar.disableLaffMeter() base.localAvatar.detachCamera() def enterWalk(self, teleportIn = 0): self.walkStateData.enter() if teleportIn == 0: self.walkStateData.fsm.request('walking') self.acceptOnce(self.walkDoneEvent, self.handleWalkDone) self.walkStateData.fsm.request('walking') self.watchTunnelSeq = Sequence(Wait(1.0), Func(LinkTunnel.globalAcceptCollisions)) self.watchTunnelSeq.start() base.localAvatar.setBusy(0) base.localAvatar.enablePicking() base.localAvatar.showFriendButton() def exitWalk(self): self.walkStateData.exit() self.ignore(self.walkDoneEvent) if base.cr.playGame.hood.titleText != None: base.cr.playGame.hood.hideTitleText() self.watchTunnelSeq.pause() del self.watchTunnelSeq base.localAvatar.setBusy(1) base.localAvatar.disablePicking() base.localAvatar.hideFriendButton() base.localAvatar.friendsList.fsm.requestFinalState() base.localAvatar.panel.fsm.requestFinalState() return def handleWalkDone(self, doneStatus): pass def enterTeleportOut(self, requestStatus, callback = None): if not callback: callback = self.__teleportOutDone base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.b_setAnimState('teleportOut', callback, [requestStatus]) def exitTeleportOut(self): base.localAvatar.disableLaffMeter() base.localAvatar.stopSmartCamera() base.localAvatar.detachCamera() base.localAvatar.stopPosHprBroadcast() def enterTunnelIn(self, linkTunnel): base.localAvatar.attachCamera() base.localAvatar.playMovementSfx('run') pivotPoint = linkTunnel.inPivotPoint self.pivotPointNode = linkTunnel.tunnel.attachNewNode('tunnelPivotPoint') self.pivotPointNode.setPos(pivotPoint) currCamPos = camera.getPos(linkTunnel.tunnel) currCamHpr = camera.getHpr(linkTunnel.tunnel) currPos = base.localAvatar.getPos(self.pivotPointNode) currHpr = base.localAvatar.getHpr(self.pivotPointNode) if linkTunnel.__class__.__name__ == 'SafeZoneLinkTunnel': base.localAvatar.setHpr(180, 0, 0) else: base.localAvatar.setHpr(0, 0, 0) base.localAvatar.setPos(currPos) base.localAvatar.reparentTo(self.pivotPointNode) base.localAvatar.walkControls.setCollisionsActive(0) base.localAvatar.detachCamera() camera.reparentTo(linkTunnel.tunnel) tunnelCamPos = linkTunnel.camPos tunnelCamHpr = linkTunnel.camHpr self.track = Parallel(LerpPosInterval(camera, duration=0.7, pos=tunnelCamPos, startPos=currCamPos, blendType='easeOut'), LerpQuatInterval(camera, duration=0.7, quat=tunnelCamHpr, startHpr=currCamHpr, blendType='easeOut'), Sequence(Func(base.localAvatar.b_setAnimState, 'run'), Wait(2.0), Func(base.transitions.irisOut)), Sequence(LerpHprInterval(self.pivotPointNode, duration=2.0, hpr=linkTunnel.inPivotEndHpr, startHpr=linkTunnel.inPivotStartHpr), LerpPosInterval(self.pivotPointNode, duration=1.0, pos=(linkTunnel.inPivotEndX, self.pivotPointNode.getY(), self.pivotPointNode.getZ()), startPos=(linkTunnel.inPivotStartX, self.pivotPointNode.getY(), self.pivotPointNode.getZ()))), name='Place.enterTunnelIn') requestStatus = {} requestStatus['zoneId'] = linkTunnel.data['zoneId'] if linkTunnel.__class__.__name__ == 'SafeZoneLinkTunnel': requestStatus['where'] = 'street' requestStatus['loader'] = 'townLoader' requestStatus['hoodId'] = base.cr.playGame.hood.id requestStatus['shardId'] = None requestStatus['avId'] = base.localAvatar.doId requestStatus['how'] = 'tunnelOut' requestStatus['fromZone'] = base.localAvatar.zoneId elif linkTunnel.__class__.__name__ == 'StreetLinkTunnel': requestStatus['where'] = 'playground' requestStatus['loader'] = 'safeZoneLoader' requestStatus['hoodId'] = base.cr.playGame.hood.id requestStatus['shardId'] = None requestStatus['avId'] = base.localAvatar.doId requestStatus['how'] = 'tunnelOut' requestStatus['fromZone'] = base.localAvatar.zoneId elif linkTunnel.__class__.__name__ == 'NeighborhoodLinkTunnel': requestStatus['where'] = 'street' requestStatus['loader'] = 'townLoader' hoodId = ZoneUtil.getHoodId(linkTunnel.data['zoneId'], 1) requestStatus['hoodId'] = hoodId requestStatus['shardId'] = None requestStatus['avId'] = base.localAvatar.doId requestStatus['how'] = 'tunnelOut' requestStatus['fromZone'] = base.localAvatar.zoneId self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__handleTunnelInDone, [requestStatus]) self.track.start() return def __handleTunnelInDone(self, requestStatus): self.doneStatus = requestStatus messenger.send(self.doneEvent) def exitTunnelIn(self): base.localAvatar.playMovementSfx(None) if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None base.localAvatar.reparentTo(render) self.pivotPointNode.removeNode() del self.pivotPointNode base.localAvatar.detachCamera() base.localAvatar.walkControls.setCollisionsActive(1) return def enterTunnelOut(self, requestStatus): base.localAvatar.playMovementSfx('run') base.transitions.irisIn() self.nextState = requestStatus.get('nextState', 'walk') linkTunnel = LinkTunnel.getTunnelThatGoesToZone(requestStatus['fromZone']) pivotPoint = linkTunnel.outPivotPoint self.pivotPointNode = linkTunnel.tunnel.attachNewNode('tunnelPivotPoint') self.pivotPointNode.setPos(pivotPoint) self.pivotPointNode.setHpr(linkTunnel.outPivotStartHpr) base.localAvatar.walkControls.setCollisionsActive(0) base.localAvatar.reparentTo(self.pivotPointNode) base.localAvatar.setHpr(linkTunnel.toonOutHpr) base.localAvatar.setPos(linkTunnel.toonOutPos) base.localAvatar.detachCamera() camera.reparentTo(linkTunnel.tunnel) tunnelCamPos = linkTunnel.camPos tunnelCamHpr = linkTunnel.camHpr camera.setPos(tunnelCamPos) camera.setHpr(tunnelCamHpr) self.track = Parallel(Sequence(Func(base.localAvatar.b_setAnimState, 'run'), LerpPosInterval(self.pivotPointNode, duration=1.0, pos=(linkTunnel.outPivotEndX, self.pivotPointNode.getY(), self.pivotPointNode.getZ()), startPos=(linkTunnel.outPivotStartX, self.pivotPointNode.getY(), self.pivotPointNode.getZ())), LerpHprInterval(self.pivotPointNode, duration=2.0, hpr=linkTunnel.outPivotEndHpr, startHpr=linkTunnel.outPivotStartHpr)), name='Place.enterTunnelOut') self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__handleTunnelOutDone) self.track.start() def __handleTunnelOutDone(self): base.localAvatar.walkControls.setCollisionsActive(1) self.fsm.request(self.nextState) def exitTunnelOut(self): base.localAvatar.playMovementSfx(None) base.localAvatar.walkControls.setCollisionsActive(1) if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None base.localAvatar.setPos(base.localAvatar.getPos(render)) base.localAvatar.setHpr(base.localAvatar.getHpr(render)) base.localAvatar.reparentTo(render) self.pivotPointNode.removeNode() del self.pivotPointNode base.localAvatar.detachCamera() del self.nextState return
class DistributedPartyGate(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyGate') def __init__(self, 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.loadSfx('phase_4/audio/sfx/clock%s.ogg' % si)) def generate(self): 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.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): 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) return def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) if ToontownGlobals.dnaMap.has_key(self.zoneId): 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 return 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 return def __handleAskDone(self): DistributedPartyGate.notify.debug('__handleAskDone') self.ignore(self.publicPartyChooseGuiDoneEvent) doneStatus = self.publicPartyGui.doneStatus self.publicPartyGui.stash() if doneStatus is None: self.freeAvatar() return self.sendUpdate('partyChoiceRequest', [base.localAvatar.doId, doneStatus[0], doneStatus[1]]) return def partyRequestDenied(self, reason): DistributedPartyGate.notify.debug('partyRequestDenied( reason=%s )' % PartyGlobals.PartyGateDenialReasons.getString(reason)) if reason == PartyGlobals.PartyGateDenialReasons.Unavailable: self.showMessage(TTLocalizer.PartyGatePartyUnavailable) elif reason == PartyGlobals.PartyGateDenialReasons.Full: self.showMessage(TTLocalizer.PartyGatePartyFull) def setParty(self, partyInfoTuple, hostId): DistributedPartyGate.notify.debug('setParty') self.freeAvatar() if partyInfoTuple[0] == 0: DistributedPartyGate.notify.debug('Public Party closed before toon could get to it.') return shardId, zoneId, numberOfGuests, hostName, activityIds, lane = partyInfoTuple #For some reason, the party gate is attempting to teleport to the host of a party rather than a random spot in the party. #This temporarily fixes a hang on the loading screen if base.localAvatar.defaultShard != shardId: shardId = None base.cr.playGame.getPlace().requestLeave({'loader': 'safeZoneLoader', 'where': 'party', 'how': 'teleportIn', 'hoodId': ToontownGlobals.PartyHood, 'zoneId': zoneId, 'shardId': None, 'avId': hostId}) return def freeAvatar(self): base.localAvatar.posCamera(0, 0) base.cr.playGame.getPlace().setState('walk') def hourChange(self, currentHour): currentHour %= 12 if currentHour == 0: currentHour = 12 self.hourSoundInterval = Parallel() seq1 = Sequence() for i in range(currentHour): seq1.append(SoundInterval(self.clockSounds[i])) seq1.append(Wait(0.2)) 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')) self.hourSoundInterval.append(seq1) self.hourSoundInterval.append(seq2) self.hourSoundInterval.start() def handleEnterGateSphere(self, collEntry): self.notify.debug('Entering steps Sphere....') base.cr.playGame.getPlace().fsm.request('stopped') self.sendUpdate('getPartyList', [base.localAvatar.doId]) def listAllPublicParties(self, publicPartyInfo): self.notify.debug('listAllPublicParties : publicPartyInfo = %s' % publicPartyInfo) self.acceptOnce(self.publicPartyChooseGuiDoneEvent, self.__handleAskDone) self.publicPartyGui.refresh(publicPartyInfo) self.publicPartyGui.unstash() def __enableCollisions(self): self.accept('enterPartyGateSphere', self.handleEnterGateSphere) self.partyGateSphere.setCollideMask(OTPGlobals.WallBitmask) def __disableCollisions(self): self.ignore('enterPartyGateSphere') self.partyGateSphere.setCollideMask(BitMask32(0)) def handleSleep(self): if hasattr(self, 'messageGui') and self.messageGui: self.__handleMessageDone()
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.mp3' self.shipBell = 'phase_6/audio/sfx/SZ_DD_shipbell.mp3' self.waterLap = 'phase_6/audio/sfx/SZ_DD_waterlap.mp3' self.dockCreak = 'phase_6/audio/sfx/SZ_DD_dockcreak.mp3' 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 return 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) 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) return 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]) return 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 return 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 return def enterOff(self): pass def exitOff(self): pass
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()
class DistributedPlayerToon(DistributedToon, DistributedPlayerToonShared): notify = directNotify.newCategory('DistributedPlayerToon') def __init__(self, cr): try: self.DistributedPlayerToon_initialized return except: self.DistributedPlayerToon_initialized = 1 DistributedToon.__init__(self, cr) DistributedPlayerToonShared.__init__(self) self.role = None self.ghost = 0 self.puInventory = [] self.equippedPU = -1 self.backpack = Backpack(self) self.battleMeter = None self.headMeter = None self.firstTimeChangingHP = True # Quest-related variables. self.quests = "" self.tier = None self.questHistory = None self.busy = 1 self.friends = None self.tutDone = 0 self.hoodsDiscovered = [] self.teleportAccess = [] self.lastHood = 0 self.defaultShard = 0 self.tunnelTrack = None self.trackExperience = dict(GagGlobals.DefaultTrackExperiences) self.takeDmgSfx = base.audio3d.loadSfx( 'phase_5/audio/sfx/tt_s_ara_cfg_toonHit.ogg') base.audio3d.attachSoundToObject(self.takeDmgSfx, self) return def getHealth(self): return DistributedPlayerToonShared.getHealth(self) def getMaxHealth(self): return DistributedPlayerToonShared.getMaxHealth(self) def stopSmooth(self): DistributedToon.stopSmooth(self) localAvatarReachable = (hasattr(base, 'localAvatar') and base.localAvatar) if localAvatarReachable and self.doId != base.localAvatar.doId: self.resetTorsoRotation() def handleHealthChange(self, hp, oldHp): if hp < oldHp and not self.firstTimeChangingHP: # We took damage, make oof sound. self.takeDmgSfx.play() def setHealth(self, health): self.handleHealthChange(health, self.getHealth()) DistributedToon.setHealth(self, health) if self.doId != base.localAvatar.doId: if not self.firstTimeChangingHP: if health < self.getMaxHealth(): if not self.headMeter: self.__makeHeadMeter() else: self.__updateHeadMeter() else: self.__removeHeadMeter() self.firstTimeChangingHP = False def announceHealthAndPlaySound(self, level, hp, extraId=-1): DistributedToon.announceHealth(self, level, hp, extraId) hpSfx = base.audio3d.loadSfx('phase_11/audio/sfx/LB_toonup.ogg') base.audio3d.attachSoundToObject(hpSfx, self) SoundInterval(hpSfx, node=self).start() del hpSfx def setChat(self, chat): chat = ChatGlobals.filterChat(chat, self.animal) DistributedToon.setChat(self, chat) def goThroughTunnel(self, toZone, inOrOut, requestStatus=None): # inOrOut: 0 = in; 1 = out if self.tunnelTrack: self.ignore(self.tunnelTrack.getDoneEvent()) self.tunnelTrack.finish() self.tunnelTrack = None linkTunnel = LinkTunnel.getTunnelThatGoesToZone(toZone) if not linkTunnel: return self.tunnelTrack = Parallel( name=self.uniqueName('Place.goThroughTunnel')) if inOrOut == 0: # Going in a tunnel! pivotPoint = linkTunnel.inPivotPoint pivotPointNode = linkTunnel.tunnel.attachNewNode( 'tunnelPivotPoint') pivotPointNode.setPos(pivotPoint) pivotPointNode.setHpr(linkTunnel.inPivotStartHpr) x, y, z = self.getPos(render) surfZ = PhysicsUtils.getNearestGroundSurfaceZ( self, self.getHeight() + self.getHeight() / 2.0) if not surfZ == -1: # Let's use the ray-tested surface z-point instead so we don't come out of the tunnel hovering. # This is just in case the user jumped into the tunnel, which in that case would mean that they are # airborne and we can't depend on their current Z value. z = surfZ if base.localAvatar.doId == self.doId: doneMethod = self._handleWentInTunnel extraArgs = [requestStatus] base.localAvatar.walkControls.setCollisionsActive( 0, andPlaceOnGround=1) self.resetHeadHpr(override=True) camera.wrtReparentTo(linkTunnel.tunnel) currCamPos = camera.getPos() currCamHpr = camera.getHpr() tunnelCamPos = linkTunnel.camPos tunnelCamHpr = linkTunnel.camHpr camera.setPos(tunnelCamPos) camera.setHpr(tunnelCamHpr) self.tunnelTrack.append( LerpPosInterval(camera, duration=0.7, pos=tunnelCamPos, startPos=currCamPos, blendType='easeOut')) self.tunnelTrack.append( LerpQuatInterval(camera, duration=0.7, quat=tunnelCamHpr, startHpr=currCamHpr, blendType='easeOut')) self.wrtReparentTo(pivotPointNode) self.setPos(x, y, z) self.resetTorsoRotation() self.stopLookAround() if linkTunnel.__class__.__name__ == "SafeZoneLinkTunnel": self.setHpr(180, 0, 0) else: self.setHpr(0, 0, 0) exitSeq = Sequence(Func(self.loop, 'run')) if base.localAvatar.doId == self.doId: exitSeq.append(Wait(2.0)) exitSeq.append(Func(base.transitions.irisOut)) self.tunnelTrack.append(exitSeq) self.tunnelTrack.append( Sequence( LerpHprInterval( pivotPointNode, duration=2.0, hpr=linkTunnel.inPivotEndHpr, startHpr=linkTunnel.inPivotStartHpr, ), LerpPosInterval(pivotPointNode, duration=1.0, pos=(linkTunnel.inPivotEndX, pivotPointNode.getY(), pivotPointNode.getZ()), startPos=(linkTunnel.inPivotStartX, pivotPointNode.getY(), pivotPointNode.getZ())), Func(self.reparentTo, hidden))) elif inOrOut == 1: # Going out! pivotPoint = linkTunnel.outPivotPoint pivotPointNode = linkTunnel.tunnel.attachNewNode( 'tunnelPivotPoint') pivotPointNode.setPos(pivotPoint) pivotPointNode.setHpr(linkTunnel.outPivotStartHpr) exitSeq = Sequence() if base.localAvatar.doId == self.doId: base.localAvatar.walkControls.setCollisionsActive( 0, andPlaceOnGround=1) base.localAvatar.detachCamera() camera.reparentTo(linkTunnel.tunnel) tunnelCamPos = linkTunnel.camPos tunnelCamHpr = linkTunnel.camHpr camera.setPos(tunnelCamPos) camera.setHpr(tunnelCamHpr) doneMethod = self._handleCameOutTunnel extraArgs = [] exitSeq.append(Func(base.transitions.irisIn)) else: self.stopSmooth() self.reparentTo(pivotPointNode) self.setHpr(linkTunnel.toonOutHpr) self.setPos(linkTunnel.toonOutPos) seq = Sequence( Func(self.loop, 'run'), LerpPosInterval(pivotPointNode, duration=1.0, pos=(linkTunnel.outPivotEndX, pivotPointNode.getY(), pivotPointNode.getZ()), startPos=(linkTunnel.outPivotStartX, pivotPointNode.getY(), pivotPointNode.getZ())), LerpHprInterval( pivotPointNode, duration=2.0, hpr=linkTunnel.outPivotEndHpr, startHpr=linkTunnel.outPivotStartHpr, )) if base.localAvatar.doId != self.doId: seq.append(Func(self.startSmooth)) seq.append(Func(self.wrtReparentTo, render)) exitSeq.append(seq) self.tunnelTrack.append(exitSeq) if base.localAvatar.doId == self.doId: self.tunnelTrack.setDoneEvent(self.tunnelTrack.getName()) self.acceptOnce(self.tunnelTrack.getDoneEvent(), doneMethod, extraArgs) self.tunnelTrack.start() def setDefaultShard(self, shardId): self.defaultShard = shardId def getDefaultShard(self): return self.defaultShard def setLastHood(self, zoneId): self.lastHood = zoneId def b_setLastHood(self, zoneId): self.sendUpdate('setLastHood', [zoneId]) self.setLastHood(zoneId) def getLastHood(self): return self.lastHood def setTeleportAccess(self, array): self.teleportAccess = array def getTeleportAccess(self): return self.teleportAccess def setHoodsDiscovered(self, array): self.hoodsDiscovered = array def b_setHoodsDiscovered(self, array): self.sendUpdate('setHoodsDiscovered', [array]) self.setHoodsDiscovered(array) def getHoodsDiscovered(self): return self.hoodsDiscovered def setTutorialCompleted(self, value): self.tutDone = value def getTutorialCompleted(self): return self.tutDone def setFriendsList(self, friends): self.friends = friends def getFriendsList(self): return self.friends def setBusy(self, busy): self.busy = busy def getBusy(self): return self.busy def setTier(self, tier): self.tier = tier def getTier(self): return self.tier def setQuestHistory(self, array): self.questHistory = array def getQuestHistory(self): return self.questHistory def setQuests(self, dataStr): self.quests = dataStr def getQuests(self): return self.quests def maybeMakeHeadMeter(self): if base.localAvatar.doId != self.doId: if self.getHealth() < self.getMaxHealth(): if not self.headMeter: self.__makeHeadMeter() def __makeHeadMeter(self): self.headMeter = LaffOMeter(forRender=True) r, g, b, _ = self.getHeadColor() animal = self.getAnimal() maxHp = self.getMaxHealth() hp = self.getHealth() self.headMeter.generate(r, g, b, animal, maxHP=maxHp, initialHP=hp) self.headMeter.reparentTo(self) self.headMeter.setZ(self.getHeight() + 2) self.headMeter.setScale(0.4) self.headMeter.setBillboardAxis() self.__updateHeadMeter() def __removeHeadMeter(self): if self.headMeter: self.headMeter.disable() self.headMeter.delete() self.headMeter = None def __updateHeadMeter(self): if self.headMeter: self.headMeter.updateMeter(self.getHealth()) def d_createBattleMeter(self): self.sendUpdate('makeBattleMeter', []) def b_createBattleMeter(self): self.makeBattleMeter() self.d_createBattleMeter() def d_cleanupBattleMeter(self): self.sendUpdate('destroyBattleMeter', []) def b_cleanupBattleMeter(self): self.destroyBattleMeter() self.d_cleanupBattleMeter() def makeBattleMeter(self): if self.getHealth() < self.getMaxHealth(): if not self.battleMeter: self.battleMeter = LaffOMeter() r, g, b, _ = self.getHeadColor() animal = self.getAnimal() maxHp = self.getMaxHealth() hp = self.getHealth() self.battleMeter.generate(r, g, b, animal, maxHP=maxHp, initialHP=hp) self.battleMeter.reparentTo(self) self.battleMeter.setZ(self.getHeight() + 5) self.battleMeter.setScale(0.5) self.battleMeter.start() def destroyBattleMeter(self): if self.battleMeter: self.battleMeter.stop() self.battleMeter.disable() self.battleMeter.delete() self.battleMeter = None def setEquippedPU(self, index): self.equippedPU = index def getEquippedPU(self): return self.equippedPU def setPUInventory(self, array): self.puInventory = array def getPUInventory(self): return self.puInventory def setGhost(self, value): self.ghost = value self.handleGhost(value) def d_setGhost(self, value): self.sendUpdate("setGhost", [value]) def b_setGhost(self, value): self.d_setGhost(value) self.setGhost(value) def getGhost(self): return self.ghost def getBackpack(self): return self.backpack def setEquippedAttack(self, attackID): try: self.backpack.setCurrentGag(attackID) except: # If we couldn't do this, it means that the avatar was most likely disabled. pass DistributedToon.setEquippedAttack(self, attackID) def getCurrentGag(self): return self.getEquippedAttack() def setLoadout(self, gagIds): if self.backpack: loadout = [] for i in range(len(gagIds)): gagId = gagIds[i] gag = self.backpack.getGagByID(gagId) if gag: loadout.append(gag) self.backpack.setLoadout(loadout) def setBackpackAmmo(self, netString): if len(self.attackIds) != 0 or len(self.attacks) != 0: self.cleanupAttacks() self.clearAttackIds() return self.backpack.updateSuppliesFromNetString(netString) def getBackpackAmmo(self): if self.backpack: return self.backpack.netString return GagGlobals.getDefaultBackpack().toNetString() def setTrackExperience(self, netString): self.trackExperience = GagGlobals.getTrackExperienceFromNetString( netString) if GagGlobals.processTrackData( self.trackExperience, self.backpack) and self == base.localAvatar: if base.localAvatar.invGui: base.localAvatar.reloadInvGui() def getTrackExperience(self): return GagGlobals.trackExperienceToNetString(self.trackExperience) def updateAttackAmmo(self, gagId, ammo, maxAmmo, ammo2, maxAmmo2, clip, maxClip): if self.useBackpack(): self.backpack.setSupply(gagId, ammo) else: DistributedToon.updateAttackAmmo(self, gagId, ammo, maxAmmo, ammo2, maxAmmo2, clip, maxClip) def setMoney(self, money): self.money = money def getMoney(self): return self.money def setAccessLevel(self, value): prevLevel = self.getAccessLevel() self.role = AdminCommands.Roles.get(value, None) if prevLevel != AdminCommands.NoAccess: # Let's remove any tokens that already are showing up. DistributedToon.removeAdminToken(self) if self.role: # Let's put a new token above our head. DistributedToon.setAdminToken(self, self.role.token) def getAccessLevel(self): return AdminCommands.NoAccess if not self.role else self.role.accessLevel def disable(self): base.audio3d.detachSound(self.takeDmgSfx) self.takeDmgSfx = None if self.tunnelTrack: self.ignore(self.tunnelTrack.getDoneEvent()) self.tunnelTrack.finish() self.tunnelTrack = None self.role = None self.ghost = None self.puInventory = None self.equippedPU = None if self.backpack: self.backpack.cleanup() self.backpack = None self.firstTimeChangingHP = None self.quests = None self.tier = None self.questHistory = None self.busy = None self.friends = None self.tutDone = None self.hoodsDiscovered = None self.teleportAccess = None self.lastHood = None self.defaultShard = None self.trackExperience = None self.__removeHeadMeter() self.destroyBattleMeter() DistributedToon.disable(self) def delete(self): try: self.DistributedPlayerToon_deleted except: self.DistributedPlayerToon_deleted = 1 DistributedPlayerToonShared.delete(self) del self.takeDmgSfx del self.tunnelTrack del self.role del self.ghost del self.puInventory del self.equippedPU del self.backpack del self.firstTimeChangingHP del self.quests del self.tier del self.questHistory del self.busy del self.friends del self.tutDone del self.hoodsDiscovered del self.teleportAccess del self.lastHood del self.defaultShard del self.trackExperience del self.battleMeter del self.headMeter DistributedToon.delete(self) return
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
class CharSelection(DirectObject): notify = directNotify.newCategory('CharSelection') NO_TOON = "Empty Slot" PLAY = "Play" CREATE = "Create" TITLE = "Pick A Toon To Play" def __init__(self, avChooser): self.avChooser = avChooser self.choice = None self.charList = None self.charNameLabel = None self.charButtons = [] self.playOrCreateButton = None self.deleteButton = None self.quitButton = None self.title = None self.stageToon = None self.stageToonRoot = None self.deleteConf = None self.frame = None self.stageFSM = ClassicFSM.ClassicFSM('StageFSM', [ State.State('off', self.enterOff, self.exitOff), State.State('loadSZ', self.enterLoadSZ, self.exitLoadSZ), State.State('onStage', self.enterOnStage, self.exitOnStage) ], 'off', 'off') self.stageFSM.enterInitialState() self.selectionFSM = ClassicFSM.ClassicFSM('CharSelection', [ State.State('off', self.enterOff, self.exitOff), State.State('character', self.enterCharSelected, self.exitCharSelected), State.State('empty', self.enterEmptySelected, self.exitEmptySelected) ], 'off', 'off') self.selectionFSM.enterInitialState() self.szGeom = None self.olc = None self.asyncSZLoadStatus = False self.isNewToon = False self.newToonSlot = None self.camIval = None self.stAnimSeq = None self.newToonAnnounceSfx = base.loadSfx( "phase_4/audio/sfx/King_Crab.ogg") self.newToonDrumrollSfx = base.loadSfx( "phase_5/audio/sfx/SZ_MM_drumroll.ogg") self.newToonRevealSfx = base.loadSfx( "phase_5/audio/sfx/SZ_MM_fanfare.ogg") self.dnaStore = DNAStorage() loader.loadDNAFile(self.dnaStore, 'phase_4/dna/pickatoon/storage_pickatoon.pdna') def __setupStageToon(self): self.stageToonRoot = render.attachNewNode('stageToonRoot') self.stageToon = Toon(base.cr) self.stageToon.setPosHpr(0, 0, 0, 0, 0, 0) self.stageToon.reparentTo(self.stageToonRoot) def cleanupStageToon(self): if self.stageToon != None: self.stageToon.disable() self.stageToon.delete() self.stageToon = None if self.stageToonRoot != None: self.stageToonRoot.removeNode() self.stageToonRoot = None def enterOff(self): pass def exitOff(self): pass def __async_loadSZTask(self, task=None): dnas = HOOD_ID_2_DNA[self.choice.lastHood] for i in xrange(len(dnas)): dnaFile = dnas[i] if i == len(dnas) - 1: node = loader.loadDNAFile(self.dnaStore, dnaFile) if node.getNumParents() == 1: self.szGeom = NodePath(node.getParent(0)) self.szGeom.reparentTo(render) else: self.szGeom = render.attachNewNode(node) # The 2D trees should not be flattened, to do that, we're going to traverse # the scene graph for all trees, use #wrtReparentTo(render) on them, flatten # the scene with #flattenStrong(), and finally #wrtReparentTo(self.szGeom) # the trees back to the main scene node so they get cleaned up properly. trees = self.szGeom.findAllMatches('**/*tree*') #self.szGeom.find("**/shadow").removeNode() #from panda3d.core import CullBinAttrib #self.szGeom.find("**/shadow_crack").setAttrib(CullBinAttrib.make("foreground", 10), 10) #shs = self.szGeom.findAllMatches("**/*shadow*") #for sh in shs: # sh.removeNode() # self.szGeom.ls() for tree in trees: tree.wrtReparentTo(render) self.szGeom.flattenStrong() for tree in trees: tree.wrtReparentTo(self.szGeom) else: loader.loadDNAFile(self.dnaStore, dnaFile) self.olc = ZoneUtil.getOutdoorLightingConfig(self.choice.lastHood) self.olc.setup() self.olc.apply() CIGlobals.preRenderScene(render) self.asyncSZLoadStatus = True #base.accept('l', render.ls) if task: return task.done def enterLoadSZ(self): self.loadingDlg = Dialog.GlobalDialog("Loading...") self.loadingDlg.show() base.cr.renderFrame() base.cr.renderFrame() self.notify.info("Polling for SZ to load") self.asyncSZLoadStatus = False self.__async_loadSZTask() base.doNextFrame(self.stageFSM.request, ['onStage']) def exitLoadSZ(self): if hasattr(self, 'loadingDlg'): self.loadingDlg.cleanup() del self.loadingDlg def __changeCamFOV(self, val): base.camLens.setMinFov(val / (4. / 3.)) def enterOnStage(self): dna = self.choice.dna name = self.choice.name self.stageToon.setName(name) self.stageToon.setDNAStrand(dna) self.stageToon.nametag.setNametagColor( NametagGlobals.NametagColors[NametagGlobals.CCLocal]) self.stageToon.nametag.setActive(0) self.stageToon.nametag.nametag3d.request('Rollover') self.stageToon.nametag.unmanage(base.marginManager) self.stageToon.nametag.updateAll() self.stageToon.animFSM.request('neutral') self.stageToon.setPosHpr(0, 0, 0, 10, 0, 0) self.stageToon.show() dat = HOOD_STAGE_DATA[self.choice.lastHood] self.stageToonRoot.setPos(dat[2]) self.stageToonRoot.setHpr(dat[3]) camera.reparentTo(self.stageToonRoot) camera.setPos(dat[0]) camera.lookAt(self.stageToonRoot, 0, 0, 3) startHpr = camera.getHpr() camera.setPos(dat[1]) camera.lookAt(self.stageToonRoot, 0, 0, 3) endHpr = camera.getHpr() self.camIval = Parallel( LerpPosInterval(camera, 5.0, dat[1] - (1.6, 0, 0), dat[0] - (1.6, 0, 0), blendType='easeInOut'), LerpQuatInterval(camera, 5.0, hpr=endHpr, startHpr=startHpr, blendType='easeInOut'), LerpFunc(self.__changeCamFOV, duration=5.0, fromData=80.0, toData=CIGlobals.DefaultCameraFov, blendType='easeInOut')) if self.isNewToon: self.camIval.append( Sequence( Func(self.stageToon.hide), Func(base.stopMusic), SoundInterval(self.newToonAnnounceSfx, startTime=1.674, duration=4.047), SoundInterval(self.newToonDrumrollSfx), Func(self.stageToon.pose, 'tele', self.stageToon.getNumFrames('tele')), Func(self.newToonAppear), Func(self.stageToon.show), SoundInterval(self.newToonRevealSfx), Func(base.cr.playTheme))) else: self.camIval.append( Sequence(Func(self.showActionButtons), Func(self.enableAllCharButtons), Wait(5.0), Func(self.beginRandomAnims))) self.camIval.start() def hideActionButtons(self): self.playOrCreateButton.hide() self.deleteButton.hide() def showActionButtons(self): self.playOrCreateButton.show() self.deleteButton.show() def newToonAppear(self): self.stopSTAnimSeq() self.stAnimSeq = Sequence( Func(self.stageToon.animFSM.request, 'teleportIn'), Wait(2.0), ActorInterval(self.stageToon, 'wave'), Func(self.stageToon.loop, 'neutral'), Func(self.beginRandomAnims), Func(self.enableAllCharButtons), Func(self.showActionButtons)) self.stAnimSeq.start() def stopSTAnimSeq(self): if self.stAnimSeq: self.stAnimSeq.finish() self.stAnimSeq = None def unloadSZGeom(self): if self.szGeom: self.szGeom.removeNode() self.szGeom = None if self.olc: self.olc.cleanup() self.olc = None def beginRandomAnims(self): self.stageToon.startLookAround() taskMgr.doMethodLater(random.uniform(*ST_ANIM_IVAL), self.__doRandomSTAnim, "doRandomSTAnim") def __doRandomSTAnim(self, task): anim = random.choice(ST_RANDOM_ANIMS) self.stopSTAnimSeq() self.stageToon.stopLookAround() head = self.stageToon.getPart('head') if anim == 'read': self.stAnimSeq = Sequence( Func(self.stageToon.lerpLookAt, head, (0, -15, 0)), Func(self.stageToon.animFSM.request, 'openBook'), Wait(0.5), Func(self.stageToon.animFSM.request, 'readBook'), Wait(2.0), Func(self.stageToon.lerpLookAt, head, (0, 0, 0)), Func(self.stageToon.animFSM.request, 'closeBook'), Wait(1.75), Func(self.stageToon.loop, 'neutral'), Func(self.stageToon.startLookAround)) else: self.stageToon.lerpLookAt(head, (0, 0, 0)) self.stAnimSeq = Sequence(ActorInterval(self.stageToon, anim), Func(self.stageToon.loop, 'neutral'), Func(self.stageToon.startLookAround)) self.stAnimSeq.start() task.delayTime = random.uniform(*ST_ANIM_IVAL) return task.again def endRandomAnims(self): taskMgr.remove("doRandomSTAnim") self.stopSTAnimSeq() def exitOnStage(self): self.isNewToon = False if self.camIval: self.camIval.finish() self.camIval = None self.endRandomAnims() self.stopSTAnimSeq() camera.reparentTo(render) camera.setPosHpr(0, 0, 0, 0, 0, 0) #base.transitions.fadeScreen(1.0) self.unloadSZGeom() self.stageToon.hide() def enterCharSelected(self): self.playOrCreateButton['text'] = self.PLAY self.playOrCreateButton['extraArgs'] = ['play'] #aspect2d.hide() def exitCharSelected(self): self.playOrCreateButton.hide() self.deleteButton.hide() def enterEmptySelected(self): self.charNameLabel.setText(self.NO_TOON) self.playOrCreateButton['text'] = self.CREATE self.playOrCreateButton['extraArgs'] = ['create'] self.playOrCreateButton.show() def exitEmptySelected(self): self.playOrCreateButton.hide() def __action(self, action): for btn in self.charButtons: if btn['state'] == DGG.DISABLED: self.slot = btn.getPythonTag('slot') break func = None arg = None doFade = True if action == 'delete': func = self.deleteToon arg = self.choice.avId doFade = False elif action == 'play': func = self.playGame arg = self.choice.slot elif action == 'create': func = self.enterMAT elif action == 'quit': func = sys.exit doFade = False if doFade: base.transitions.fadeOut(0.3) if arg != None: Sequence(Wait(0.31), Func(func, arg)).start() else: Sequence(Wait(0.31), Func(func)).start() else: if arg != None: func(arg) else: func() def playGame(self, slot): messenger.send("avChooseDone", [self.avChooser.getAvChoiceBySlot(slot)]) def enterMAT(self): messenger.send("enterMakeAToon", [self.slot]) def deleteToon(self, avId): # Show a confirmation message self.deleteConf = Dialog.GlobalDialog( message='This will delete {0} forever.\n\nAre you sure?'.format( self.avChooser.getNameFromAvId(avId)), style=Dialog.YesNo, doneEvent='deleteConfResponse', extraArgs=[avId]) self.acceptOnce('deleteConfResponse', self.__handleDeleteConfResponse) self.deleteConf.show() def __handleDeleteConfResponse(self, avId): doneStatus = self.deleteConf.getValue() if doneStatus: # Alright, they pressed yes. No complaining to us. self.avChooser.avChooseFSM.request("waitForToonDelResponse", [avId]) else: self.deleteConf.cleanup() self.deleteConf = None def __handleCharButton(self, slot): for btn in self.charButtons: if btn.getPythonTag('slot') == slot: btn['state'] = DGG.DISABLED else: btn['state'] = DGG.NORMAL if self.avChooser.hasToonInSlot(slot): self.choice = self.avChooser.getAvChoiceBySlot(slot) self.selectionFSM.request('character') self.stageFSM.request('loadSZ') else: self.selectionFSM.request('empty') self.stageFSM.request('off') def disableAllCharButtons(self): for btn in self.charButtons: btn['state'] = DGG.DISABLED def enableAllCharButtons(self): for btn in self.charButtons: if not self.choice or btn.getPythonTag('slot') != self.choice.slot: btn['state'] = DGG.NORMAL def load(self, newToonSlot=None): self.isNewToon = newToonSlot is not None self.newToonSlot = newToonSlot base.transitions.noTransitions() base.cr.renderFrame() base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4. / 3.)) self.__setupStageToon() self.title = DirectLabel(text=self.TITLE, text_font=CIGlobals.getMickeyFont(), text_fg=(1, 0.9, 0.1, 1), relief=None, text_scale=0.13, pos=(0, 0, 0.82)) self.charNameLabel = OnscreenText(text="", font=CIGlobals.getMickeyFont(), pos=(-0.25, 0.5, 0), fg=(1, 0.9, 0.1, 1.0)) self.charNameLabel.hide() self.frame = DirectFrame() self.frame['image'] = DGG.getDefaultDialogGeom() self.frame['image_color'] = CIGlobals.DialogColor self.frame['image_scale'] = (-0.9, -0.9, 0.8) self.frame['image_pos'] = (0.82, 0, -0.125) self.playOrCreateButton = DirectButton( text="", pos=(0.8125, 0, -0.35), command=self.__action, geom=CIGlobals.getDefaultBtnGeom(), text_scale=0.06, relief=None, text_pos=(0, -0.01)) self.playOrCreateButton.hide() self.deleteButton = DirectButton(text="Delete", pos=(0.8125, 0, -0.45), command=self.__action, extraArgs=['delete'], geom=CIGlobals.getDefaultBtnGeom(), text_scale=0.06, relief=None, text_pos=(0, -0.01)) self.deleteButton.hide() self.quitButton = DirectButton(text="Quit", pos=(-1.10, 0, -0.925), command=self.__action, extraArgs=['quit'], text_scale=0.06, geom=CIGlobals.getDefaultBtnGeom(), relief=None, text_pos=(0, -0.01)) for slot in range(6): if self.avChooser.hasToonInSlot(slot): choice = self.avChooser.getAvChoiceBySlot(slot) text = choice.name else: text = self.NO_TOON btn = CIGlobals.makeDefaultScrolledListBtn( text=text, text_scale=0.06, command=self.__handleCharButton, extraArgs=[slot]) btn.setPythonTag('slot', slot) self.charButtons.append(btn) btn['state'] = DGG.NORMAL self.charList = CIGlobals.makeDefaultScrolledList( pos=(0.75, 0, -0.225), listZorigin=-0.43, listFrameSizeZ=0.51, arrowButtonScale=0.0, items=self.charButtons, parent=self.frame) if self.isNewToon: self.__handleCharButton(self.newToonSlot) self.disableAllCharButtons() def unload(self): self.selectionFSM.requestFinalState() self.stageFSM.requestFinalState() self.cleanupStageToon() self.choice = None if self.frame: self.frame.destroy() self.frame = None if self.charButtons: for btn in self.charButtons: btn.destroy() self.charButtons = None if self.deleteConf: self.deleteConf.cleanup() self.deleteConf = None if self.charList: self.charList.destroy() self.charList = None if self.charNameLabel: self.charNameLabel.destroy() self.charNameLabel = None if self.playOrCreateButton: self.playOrCreateButton.destroy() self.playOrCreateButton = None if self.deleteButton: self.deleteButton.destroy() self.deleteButton = None if self.quitButton: self.quitButton.destroy() self.quitButton = None if self.title: self.title.destroy() self.title = None base.camera.setPos(0, 0, 0) base.camera.setHpr(0, 0, 0) base.transitions.noTransitions() del self.selectionFSM
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()
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('lockOn', self.enterLockOn, self.exitLockOn), State('shoot', self.enterShoot, self.exitShoot) ], 'off', 'off' ) self.fsm.enterInitialState() self.cannon = None self.track = None self.avatar = None self.readyPie = None self.explosion = None self.wallCollNode = None self.eventCollNode = None self.event = None self.piesInFlight = [] def setHealth(self, hp): DistributedAvatar.setHealth(self, hp) if self.getAvatar() == base.localAvatar.doId: 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, 1)) sfx = base.localAvatar.audio3d.loadSfx("phase_3.5/audio/sfx/ENC_cogfall_apart.mp3") base.localAvatar.audio3d.attachSoundToObject(sfx, self) base.playSfx(sfx) 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() def enterOff(self): pass def exitOff(self): pass def makeSplat(self, pos): splat = Actor("phase_3.5/models/props/splat-mod.bam", {"chan": "phase_3.5/models/props/splat-chan.bam"}) splat.setScale(0.5) splat.reparentTo(render) splat.setBillboardPointEye() splat.setColor(VBase4(1, 1, 0, 1)) x, y, z = pos splat.setPos(x, y, z) sfx = base.localAvatar.audio3d.loadSfx("phase_4/audio/sfx/AA_wholepie_only.mp3") base.localAvatar.audio3d.attachSoundToObject(sfx, splat) base.playSfx(sfx) track = Sequence( ActorInterval(splat, "chan"), Func(splat.cleanup), Func(splat.removeNode) ) track.start() def d_makeSplat(self, pos): self.sendUpdate("makeSplat", [pos]) def b_makeSplat(self, pos): self.d_makeSplat(pos) self.makeSplat(pos) def shoot(self, suitId): self.fsm.request('shoot', [suitId]) 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.eventId = random.uniform(0, 100000000) track = Sequence(Parallel(LerpScaleInterval(smoke, 0.5, 3), LerpColorScaleInterval(smoke, 0.5, Vec4(2, 2, 2, 0))), Func(smoke.removeNode)) track.start() self.createAndShootPie() def loadPieInTurret(self): if self.cannon: if self.readyPie: self.readyPie.removeNode() self.readyPie = None pie = loader.loadModel("phase_3.5/models/props/tart.bam") pie.reparentTo(self.cannon.find('**/cannon')) pie.setY(5.2) pie.setHpr(90, -90, 90) self.readyPie = pie def removePieInTurret(self): if self.readyPie: self.readyPie.removeNode() self.readyPie = None def createAndShootPie(self): if not self.readyPie: self.loadPieInTurret() local = 0 if base.localAvatar.doId == self.getAvatar(): local = 1 proj = ProjectilePie(self.uniqueName('pieTurretCollision') + str(self.eventId), self.cannon.find('**/cannon'), self.readyPie, Point3(0, 200, -90), 0.9, 2.5, local, self) self.readyPie = None self.piesInFlight.append(proj) if local: self.acceptOnce(self.uniqueName('pieTurretCollision') + str(self.eventId), self.handlePieCollision) Sequence(Wait(0.25), Func(self.loadPieInTurret)).start() def handlePieCollision(self, entry, proj): x, y, z = proj.pie.getPos(render) self.b_makeSplat([x, y, z]) proj.cleanup() if base.localAvatar.doId == self.getAvatar(): 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: base.localAvatar.sendUpdate('suitHitByPie', [obj.doId, GagGlobals.getIDByName(CIGlobals.WholeCreamPie)]) def exitShoot(self): del self.suit del self.eventId 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 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.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'), ) ) self.track.loop(ts) def _afterShootTrackDone(self): 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'), ) ) self.track.loop() def exitScan(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None def setAvatar(self, avId): self.avatar = avId def getAvatar(self): return self.avatar def makeTurret(self): self.cannon = loader.loadModel("phase_4/models/minigames/toon_cannon.bam") self.cannon.reparentTo(self) self.loadPieInTurret() self.setupWallSphere() if self.getAvatar() == base.localAvatar.doId: self.setupEventSphere() 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 removeTurret(self): self.removeWallSphere() self.removePieInTurret() if self.cannon: self.cannon.removeNode() self.cannon = None def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def announceGenerate(self): DistributedAvatar.announceGenerate(self) DistributedSmoothNode.announceGenerate(self) self.healthLabel.setScale(1.1) self.makeTurret() def disable(self): self.fsm.requestFinalState() del self.fsm for projs in self.piesInFlight: projs.cleanup() self.piesInFlight = None if self.explosion: self.explosion.removeNode() self.explosion = None self.removeTurret() DistributedSmoothNode.disable(self) DistributedAvatar.disable(self)
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_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() elif 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 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() self.nameTag.setClickable(0) 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
class DodgeballFirstPerson(FirstPerson): """The first person controls for the local player in Winter Dodgeball""" notify = directNotify.newCategory("DodgeballFirstPerson") MaxPickupDistance = 5.0 def __init__(self, mg): self.mg = mg self.crosshair = None self.soundCatch = None self.vModelRoot = None self.vModel = None self.ival = None self.soundPickup = base.loadSfx( 'phase_4/audio/sfx/MG_snowball_pickup.ogg') self.fakeSnowball = loader.loadModel( "phase_5/models/props/snowball.bam") self.hasSnowball = False self.mySnowball = None self.waitingOnPickupResp = False self.camPivotNode = base.localAvatar.attachNewNode('cameraPivotNode') self.camFSM = ClassicFSM.ClassicFSM("DFPCamera", [ State.State('off', self.enterCamOff, self.exitCamOff), State.State('frozen', self.enterFrozen, self.exitFrozen), State.State('unfrozen', self.enterUnFrozen, self.exitUnFrozen) ], 'off', 'off') self.camFSM.enterInitialState() self.fsm = ClassicFSM.ClassicFSM("DodgeballFirstPerson", [ State.State("off", self.enterOff, self.exitOff), State.State("hold", self.enterHold, self.exitHold), State.State("catch", self.enterCatch, self.exitCatch), State.State("throw", self.enterThrow, self.exitThrow) ], "off", "off") self.fsm.enterInitialState() FirstPerson.__init__(self) def enterCamOff(self): self.releaseSnowball() def exitCamOff(self): pass def releaseSnowball(self): if self.hasSnowball: if self.mySnowball and not self.mySnowball.isAirborne: self.hasSnowball = False self.mySnowball.resetSnowball() self.mySnowball = None self.fsm.request('off') def enterFrozen(self): self.releaseSnowball() self.vModel.hide() base.localAvatar.getGeomNode().show() camera.wrtReparentTo(self.camPivotNode) camHeight = max(base.localAvatar.getHeight(), 3.0) nrCamHeight = base.localAvatar.getHeight() heightScaleFactor = camHeight * 0.3333333333 defLookAt = Point3(0.0, 1.5, camHeight) idealData = (Point3(0.0, -12.0 * heightScaleFactor, camHeight), defLookAt) self.camTrack = Parallel( LerpPosInterval(camera, duration=1.0, pos=idealData[0], startPos=camera.getPos(), blendType='easeOut'), LerpQuatInterval(camera, duration=1.0, hpr=idealData[1], startHpr=camera.getHpr(), blendType='easeOut')) self.camTrack.start() self.max_camerap = 0.0 self.disableMouse() def cameraMovement(self, task): if not self.camFSM: return task.done if self.camFSM.getCurrentState().getName() == 'frozen': if hasattr(self, 'min_camerap') and hasattr(self, 'max_camerap'): md = base.win.getPointer(0) x = md.getX() y = md.getY() if base.win.movePointer(0, base.win.getXSize() / 2, base.win.getYSize() / 2): self.camPivotNode.setP(self.camPivotNode.getP() - (y - base.win.getYSize() / 2) * 0.1) self.camPivotNode.setH(self.camPivotNode.getH() - (x - base.win.getXSize() / 2) * 0.1) if self.camPivotNode.getP() < self.min_camerap: self.camPivotNode.setP(self.min_camerap) elif self.camPivotNode.getP() > self.max_camerap: self.camPivotNode.setP(self.max_camerap) return task.cont else: return task.done return FirstPerson.cameraMovement(self, task) def exitFrozen(self): self.camTrack.finish() del self.camTrack self.max_camerap = 90.0 self.vModel.show() self.enableMouse() base.localAvatar.stopSmartCamera() def enterUnFrozen(self): base.localAvatar.getGeomNode().hide() self.reallyStart() camera.setPosHpr(0, 0, 0, 0, 0, 0) camera.reparentTo(self.player_node) camera.setZ(base.localAvatar.getHeight()) def exitUnFrozen(self): self.end() self.enableMouse() def enterOff(self): if self.vModel: self.vModel.hide() if self.waitingOnPickupResp: taskMgr.add(self.__waitForPickupRespTask, "waitForPickupRespTask") def __waitForPickupRespTask(self, task): if not self.waitingOnPickupResp: if self.hasSnowball: self.fsm.request('hold') return task.done return task.cont def exitOff(self): if self.vModel: self.vModel.show() taskMgr.remove("waitForPickupRespTask") def enterHold(self): self.ival = Sequence(ActorInterval(self.vModel, "hold-start"), Func(self.vModel.loop, "hold")) self.ival.start() def exitHold(self): if self.ival: self.ival.finish() self.ival = None self.vModel.stop() def enterThrow(self): self.ival = Parallel( Sequence(Wait(0.4), Func(self.mySnowball.b_throw)), Sequence(ActorInterval(self.vModel, "throw"), Func(self.fsm.request, 'off'))) self.ival.start() def exitThrow(self): if self.ival: self.ival.pause() self.ival = None self.vModel.stop() def enterCatch(self): self.ival = Parallel( Sequence(Wait(0.2), Func(self.__tryToCatchOrGrab)), Sequence(ActorInterval(self.vModel, "catch"), Func(self.__maybeHold))) self.ival.start() def __maybeHold(self): if self.hasSnowball: self.fsm.request('hold') else: self.fsm.request('off') def __tryToCatchOrGrab(self): snowballs = list(self.mg.snowballs) snowballs.sort( key=lambda snowball: snowball.getDistance(base.localAvatar)) for i in xrange(len(snowballs)): snowball = snowballs[i] if (not snowball.hasOwner() and not snowball.isAirborne and snowball.getDistance(base.localAvatar) <= DodgeballFirstPerson.MaxPickupDistance): self.waitingOnPickupResp = True self.mg.sendUpdate('reqPickupSnowball', [snowball.index]) break def snowballPickupResp(self, flag, idx): if flag: snowball = self.mg.snowballs[idx] snowball.b_pickup() self.mySnowball = snowball self.fakeSnowball.setPosHpr(0, 0.73, 0, 0, 0, 0) self.fakeSnowball.reparentTo( self.vModel.exposeJoint(None, "modelRoot", "Bone.011")) base.playSfx(self.soundPickup) self.hasSnowball = True self.waitingOnPickupResp = False def exitCatch(self): self.vModel.stop() if self.ival: self.ival.pause() self.ival = None def start(self): # Black crosshair because basically the entire arena is white. self.crosshair = getCrosshair(color=(0, 0, 0, 1), hidden=False) self.soundCatch = base.loadSfx( "phase_4/audio/sfx/MG_sfx_vine_game_catch.ogg") self.vModelRoot = camera.attachNewNode('vModelRoot') self.vModelRoot.setPos(-0.09, 1.38, -2.48) self.vModel = Actor( "phase_4/models/minigames/v_dgm.egg", { "hold": "phase_4/models/minigames/v_dgm-ball-hold.egg", "hold-start": "phase_4/models/minigames/v_dgm-ball-hold-start.egg", "throw": "phase_4/models/minigames/v_dgm-ball-throw.egg", "catch": "phase_4/models/minigames/v_dgm-ball-catch.egg" }) self.vModel.setBlend(frameBlend=True) self.vModel.reparentTo(self.vModelRoot) self.vModel.setBin("fixed", 40) self.vModel.setDepthTest(False) self.vModel.setDepthWrite(False) self.vModel.hide() base.localAvatar.walkControls.setWalkSpeed(ToonForwardSpeed, ToonJumpForce, ToonReverseSpeed, ToonRotateSpeed) FirstPerson.start(self) def reallyStart(self): FirstPerson.reallyStart(self) base.localAvatar.startTrackAnimToSpeed() self.accept('mouse3', self.__handleCatchOrGrabButton) self.accept('mouse1', self.__handleThrowButton) def end(self): base.localAvatar.stopTrackAnimToSpeed() self.ignore('mouse3') self.ignore('mouse1') FirstPerson.end(self) def __handleThrowButton(self): if self.hasSnowball and self.mySnowball and self.fsm.getCurrentState( ).getName() == 'hold': self.fakeSnowball.reparentTo(hidden) self.fsm.request('throw') def __handleCatchOrGrabButton(self): if not self.hasSnowball and not self.mySnowball and self.fsm.getCurrentState( ).getName() == 'off': self.fsm.request('catch') def reallyEnd(self): base.localAvatar.setWalkSpeedNormal() if self.camFSM: self.camFSM.requestFinalState() self.camFSM = None if self.fsm: self.fsm.requestFinalState() self.fsm = None if self.crosshair: self.crosshair.destroy() self.crosshair = None if self.vModel: self.vModel.removeNode() self.vModel = None if self.vModelRoot: self.vModelRoot.removeNode() self.vModelRoot = None self.soundCatch = None FirstPerson.reallyEnd(self)
class DistributedPartyGate(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedPartyGate') def __init__(self, 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.loadSfx('phase_4/audio/sfx/clock%s.mp3' % si)) def generate(self): 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.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): 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) return def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) if ToontownGlobals.dnaMap.has_key(self.zoneId): 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 return 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 return def __handleAskDone(self): DistributedPartyGate.notify.debug('__handleAskDone') self.ignore(self.publicPartyChooseGuiDoneEvent) doneStatus = self.publicPartyGui.doneStatus self.publicPartyGui.stash() if doneStatus is None: self.freeAvatar() return self.sendUpdate('partyChoiceRequest', [base.localAvatar.doId, doneStatus[0], doneStatus[1]]) return def partyRequestDenied(self, reason): DistributedPartyGate.notify.debug( 'partyRequestDenied( reason=%s )' % PartyGlobals.PartyGateDenialReasons.getString(reason)) if reason == PartyGlobals.PartyGateDenialReasons.Unavailable: self.showMessage(TTLocalizer.PartyGatePartyUnavailable) elif reason == PartyGlobals.PartyGateDenialReasons.Full: self.showMessage(TTLocalizer.PartyGatePartyFull) def setParty(self, partyInfoTuple): DistributedPartyGate.notify.debug('setParty') self.freeAvatar() if partyInfoTuple[0] == 0: DistributedPartyGate.notify.debug( 'Public Party closed before toon could get to it.') return 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 }) return 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() seq1 = Sequence() for i in range(currentHour): seq1.append(SoundInterval(self.clockSounds[i])) seq1.append(Wait(0.2)) 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')) self.hourSoundInterval.append(seq1) self.hourSoundInterval.append(seq2) self.hourSoundInterval.start() def handleEnterGateSphere(self, collEntry): self.notify.debug('Entering steps Sphere....') base.cr.playGame.getPlace().fsm.request('stopped') self.sendUpdate('getPartyList', [base.localAvatar.doId]) def listAllPublicParties(self, publicPartyInfo): self.notify.debug('listAllPublicParties : publicPartyInfo = %s' % publicPartyInfo) self.acceptOnce(self.publicPartyChooseGuiDoneEvent, self.__handleAskDone) self.publicPartyGui.refresh(publicPartyInfo) self.publicPartyGui.unstash() def __enableCollisions(self): self.accept('enterPartyGateSphere', self.handleEnterGateSphere) self.partyGateSphere.setCollideMask(OTPGlobals.WallBitmask) def __disableCollisions(self): self.ignore('enterPartyGateSphere') self.partyGateSphere.setCollideMask(BitMask32(0)) def handleSleep(self): if hasattr(self, 'messageGui') and self.messageGui: self.__handleMessageDone()
class Golem(FSM, DirectObject): def __init__(self): FSM.__init__(self, "FSM-Golem") random.seed() self.golem = loader.loadModel("Golem") self.golem = Actor("Golem", { "Idle":"Golem-Idle", "Walk":"Golem-Walk", "Attack":"Golem-Attack", "Destroyed":"Golem-Destroyed"}) self.golem.setBlend(frameBlend = True) golemViewSphere = CollisionSphere(0, 0, 0.5, 6) golemViewSphere.setTangible(False) golemViewColNP = self.golem.attachNewNode(CollisionNode('golemViewField')) golemViewColNP.node().addSolid(golemViewSphere) golemHitSphere = CollisionSphere(0, 0, 0.5, 1) golemHitColNP = self.golem.attachNewNode(CollisionNode('golemHitField')) golemHitColNP.node().addSolid(golemHitSphere) # a collision segment to check attacks self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1) self.golemAttackRay = self.golem.attachNewNode(CollisionNode("golemAttackCollision")) self.golemAttackRay.node().addSolid(self.attackCheckSegment) self.golemAttackRay.node().setIntoCollideMask(0) self.attackqueue = CollisionHandlerQueue() base.cTrav.addCollider(self.golemAttackRay, self.attackqueue) attackAnim = self.golem.actorInterval("Attack", playRate = 2) self.AttackSeq = Parallel( attackAnim, Sequence( Wait(0.5), Func(self.ceckAttack) )) self.lookatFloater = NodePath(PandaNode("golemTracker")) self.lookatFloater.setPos(self.golem, 0, 0, 3.4) self.lookatFloater.hide() self.lookatFloater.reparentTo(render) self.trackerObject = loader.loadModel("misc/Pointlight") self.trackerObject.setColor(0, 1, 0) self.trackerObject.setScale(0.25) self.trackerObject.reparentTo(self.lookatFloater) def start(self, startPos): self.golem.setPos(startPos.getPos()) self.golem.setHpr(startPos.getHpr()) self.golem.reparentTo(render) self.trackedEnemy = None self.health = 5 self.accept("playerCollision-in-golemViewField", lambda extraArgs: base.messenger.send("golemSeesPlayer", [self.golem])) def stop(self): self.trackedEnemy = None taskMgr.remove("GolemAI_task") self.golem.hide() self.ignoreAll() def cleanup(self): self.stop() self.lookatFloater.removeNode() self.golem.cleanup() self.golem.removeNode() def activate(self, trackedEnemy): self.trackedEnemy = trackedEnemy taskMgr.add(self.aiTask, "GolemAI_task") self.lookatFloater.show() def aiTask(self, task): dt = globalClock.getDt() if self.AttackSeq.isPlaying(): return task.cont self.lookatFloater.setPos(self.golem, 0, 0, 3.4) self.lookatFloater.lookAt(self.trackedEnemy) self.lookatFloater.setH(self.lookatFloater.getH() + 180) self.lookatFloater.setP(0) self.lookatFloater.setR(0) self.golem.lookAt(self.trackedEnemy) self.golem.setH(self.golem.getH() + 180) distanceVec = self.golem.getPos() - self.trackedEnemy.getPos() enemyDist = distanceVec.length() if enemyDist < 2.0: # close enough for combat action = random.choice(["Attack", "Idle"]) if action == "Attack": self.request("Attack") else: if self.state != "Idle": self.request("Idle") else: self.golem.setY(self.golem, -0.5 * dt) if self.state != "Walk": self.request("Walk") return task.cont def hit(self): hitInterval = Sequence( Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15), Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15), Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15), Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15)) self.health -= 1 if self.health == 4: self.trackerObject.setColor(0, 1, 0) hitInterval.start() elif self.health == 3: self.trackerObject.setColor(0.25, 0.75, 0) hitInterval.start() elif self.health == 2: self.trackerObject.setColor(0.5, .5, 0) hitInterval.start() elif self.health == 1: self.trackerObject.setColor(0.75, 0.25, 0) hitInterval.start() elif self.health == 0: self.trackerObject.setColor(0, 0, 0) self.request("Destroyed") def ceckAttack(self): for i in range(self.attackqueue.getNumEntries()): entry = self.attackqueue.getEntry(i) into = entry.getIntoNode() if "playerCollision" in into.getName(): if random.random() > .5: base.messenger.send("HitPlayer") def enterIdle(self): self.golem.loop("Idle") def enterWalk(self): self.golem.setPlayRate(2, "Walk") self.golem.loop("Walk") def enterAttack(self): self.AttackSeq.start() def enterDestroyed(self): self.ignoreAll() taskMgr.remove("GolemAI_task") self.AttackSeq.finish() self.golem.play("Destroyed") self.lookatFloater.hide() base.messenger.send("GolemDestroyed")
class DistributedDodgeballGame(DistributedToonFPSGame, TeamMinigame): """The winter dodgeball minigame (client side)""" notify = directNotify.newCategory("DistributedDodgeballGame") TreeData = [['prop_snow_tree_small_ur', Point3(23.23, 66.52, 7.46)], ['prop_snow_tree_small_ul', Point3(-34.03, 88.02, 24.17)], ['prop_snow_tree_small_ur', Point3(-54.80, 0, 4.19)], ['prop_snow_tree_small_ul', Point3(54.80, -5, 4.19)], ['prop_snow_tree_small_ur', Point3(62.71, 62.66, 16.80)], ['prop_snow_tree_small_ul', Point3(-23.23, -66.52, 6)], ['prop_snow_tree_small_ur', Point3(34.03, -88.02, 23)], ['prop_snow_tree_small_ul', Point3(-62.71, -62.66, 16)]] SnowballData = [ Point3(30, 0, 0.75), Point3(22.5, 0, 0.75), Point3(15, 0, 0.75), Point3(7.5, 0, 0.75), Point3(0, 0, 0.75), Point3(-7.5, 0, 0.75), Point3(-15, 0, 0.75), Point3(-22.5, 0, 0.75), Point3(-30, 0, 0.75) ] GameSong = "phase_4/audio/bgm/MG_Dodgeball.ogg" GameDesc = ( "Welcome to the north! You have been invited to play dodgeball with the penguins!\n\n" "How To Play\nWASD to Move and use the mouse to aim.\nLeft click to Throw!\nThrow a " "snowball at a teammate to unfreeze them!\n\nThe team with the most points after {0} rounds wins!" .format(MaxRounds)) InitCamTrans = [Point3(25, 45, 19.5317), Vec3(154.001, -15, 0)] SnowBallDmg = 25 GetSnowBalls = "Pick up a snowball from the center!" Team2OtherBarrier = {BLUE: "red_barrier_coll", RED: "blue_barrier_coll"} def __init__(self, cr): try: self.DistributedDodgeballGame_initialized return except: self.DistributedDodgeballGame_initialized = 1 DistributedToonFPSGame.__init__(self, cr) TeamMinigame.__init__( self, "BlueSnow", ('phase_4/maps/db_blue_neutral.png', 'phase_4/maps/db_blue_hover.png', 'phase_4/maps/db_blue_hover.png'), "RedIce", ('phase_4/maps/db_red_neutral.png', 'phase_4/maps/db_red_hover.png', 'phase_4/maps/db_red_hover.png')) self.fsm.addState( State('chooseTeam', self.enterChooseTeam, self.exitChooseTeam, ['waitForOthers'])) self.fsm.addState( State('scrollBy', self.enterScrollBy, self.exitScrollBy, ['countdown'])) self.fsm.addState( State('countdown', self.enterCountdown, self.exitCountdown, ['play'])) self.fsm.addState( State('announceGameOver', self.enterAnnGameOver, self.exitAnnGameOver, ['displayWinners', 'countdown'])) self.fsm.addState( State('displayWinners', self.enterDisplayWinners, self.exitDisplayWinners, ['gameOver'])) self.fsm.getStateNamed('waitForOthers').addTransition('chooseTeam') self.fsm.getStateNamed('waitForOthers').addTransition('scrollBy') self.fsm.getStateNamed('play').addTransition('announceGameOver') self.firstPerson = DodgeballFirstPerson(self) self.scrollBySeq = None self.infoText = None self.redScoreLbl = None self.blueScoreLbl = None self.barrierIsStashed = False self.mySpawnPoint = 0 self.infoText = getAlertText() self.spawnPointsByTeam = { BLUE: [[Point3(5, 15, 0), Vec3(180, 0, 0)], [Point3(15, 15, 0), Vec3(180, 0, 0)], [Point3(-5, 15, 0), Vec3(180, 0, 0)], [Point3(-15, 15, 0), Vec3(180, 0, 0)]], RED: [[Point3(5, -15, 0), Vec3(0, 0, 0)], [Point3(15, -15, 0), Vec3(0, 0, 0)], [Point3(-5, -15, 0), Vec3(0, 0, 0)], [Point3(-15, -15, 0), Vec3(0, 0, 0)]] } self.winnerMusic = base.loadMusic( 'phase_9/audio/bgm/encntr_hall_of_fame.ogg') self.loserMusic = base.loadMusic( 'phase_9/audio/bgm/encntr_sting_announce.ogg') self.danceSound = base.loadSfx('phase_3.5/audio/sfx/ENC_Win.ogg') # Environment vars self.arena = None self.olc = None self.trees = [] self.snowballs = [] def snowballPickupResp(self, flag, idx): self.firstPerson.snowballPickupResp(flag, idx) def roundOver(self, time=0): teams = [BLUE, RED] teams.sort(key=lambda team: self.scoreByTeam[team], reverse=True) self.winnerTeam = teams[0] base.localAvatar.disableAvatarControls() self.firstPerson.end() self.deleteTimer() self.fsm.request('announceGameOver', [time]) def getTeamDNAColor(self, team): if team == TEAM1: return ToonDNA.colorDNA2color['18'] elif team == TEAM2: return ToonDNA.colorDNA2color['02'] def enterDisplayWinners(self): base.localAvatar.stopLookAround() base.localAvatar.resetHeadHpr() base.localAvatar.getGeomNode().show() camera.reparentTo(render) camera.setPos((-2.5, 12, 3.5)) camera.setHpr((-175.074, -5.47218, 0)) base.transitions.fadeIn() base.playSfx(self.danceSound, looping=1) if self.winnerTeam == self.team: base.playMusic(self.winnerMusic) else: base.playMusic(self.loserMusic) winnerPositions = [(-2, 0, 0), (2, 0, 0), (6, 0, 0), (-6, 0, 0)] loserPositions = [(-3.5, -10, 0), (-1.5, -15, 0), (3.0, -8, 0), (5.5, -12, 0)] for team in [RED, BLUE]: for avId in self.playerListByTeam[team]: av = self.cr.doId2do.get(avId) if av: av.stopSmooth() av.setHpr(0, 0, 0) if team == self.winnerTeam: posList = winnerPositions av.setAnimState("off") av.stop() if not self.getRemoteAvatar(avId).isFrozen: av.loop("win") else: posList = loserPositions av.setAnimState('off') av.stop() if not self.getRemoteAvatar(avId).isFrozen: av.loop("pout") pos = random.choice(posList) posList.remove(pos) av.setPos(pos) if self.winnerTeam == self.team: text = "YOU WIN!" else: text = "YOU LOSE!" self.gameOverLbl.setText(text) self.track = Sequence(Wait(2.0), Func(self.gameOverLbl.setScale, 0.01), Func(self.gameOverLbl.show), getAlertPulse(self.gameOverLbl, 0.27, 0.25)) self.track.start() base.localAvatar.collisionsOff() def exitDisplayWinners(self): base.localAvatar.collisionsOn() base.transitions.noTransitions() self.danceSound.stop() if hasattr(self, 'track'): self.track.finish() self.track = None self.gameOverLbl.hide() def __prepareForNextRound(self): for av in self.remoteAvatars: av.unFreeze() pos, hpr = self.spawnPointsByTeam[self.team][self.mySpawnPoint] base.localAvatar.setPos(pos) base.localAvatar.setHpr(hpr) self.playMinigameMusic() self.fsm.request('countdown') def enterAnnGameOver(self, timeRanOut=0): self.firstPerson.vModel.hide() text = getGameText() text.setBin('gui-popup', 60) ival = Sequence() if timeRanOut: ival.append(Func(text.setText, "Time's Up!")) ival.append(getRoundIval(text)) ival.append( Func(text.setText, "Round {0} Over!".format(self.getRound()))) ival.append(getRoundIval(text)) team = "Red" if self.winnerTeam == BLUE: team = "Blue" if self.round != MaxRounds: if self.scoreByTeam[RED] == self.scoreByTeam[BLUE]: ival.append(Func(text.setText, "The scores are tied!")) else: ival.append( Func(text.setText, "{0} is in the lead!".format(team))) else: ival.append(Func(text.setText, "{0} wins!".format(team))) ival.append(getRoundIval(text)) ival.setDoneEvent(self.uniqueName('annGameOverDone')) self.acceptOnce(ival.getDoneEvent(), self.__annGameOverTask) self.ival = ival self.ival.start() self.text = text base.transitions.fadeScreen() def __annGameOverTask(self): if self.round == MaxRounds: nextState = Func(self.fsm.request, "displayWinners") else: nextState = Func(self.__prepareForNextRound) self.ival = Sequence(base.transitions.getFadeOutIval(), nextState) self.ival.start() def exitAnnGameOver(self): if hasattr(self, 'ival'): self.ignore(self.ival.getDoneEvent()) self.ival.finish() del self.ival if hasattr(self, 'text'): self.text.destroy() del self.text def teamWon(self, team, time=0): TeamMinigame.teamWon(self, team, time) base.localAvatar.disableAvatarControls() self.firstPerson.end() self.deleteTimer() self.fsm.request('announceGameOver', [time]) def incrementTeamScore(self, team): TeamMinigame.incrementTeamScore(self, team) if team == BLUE: self.blueScoreLbl.setText("BLUE: " + str(self.scoreByTeam[team])) ToontownIntervals.start( ToontownIntervals.getPulseLargerIval(self.blueScoreLbl, 'blueScorePulse')) elif team == RED: self.redScoreLbl.setText("RED: " + str(self.scoreByTeam[team])) ToontownIntervals.start( ToontownIntervals.getPulseLargerIval(self.redScoreLbl, 'redScorePulse')) def getWinterDodgeballScoreText(self, color): text = OnscreenText(fg=color, font=CIGlobals.getMinnieFont(), scale=0.15, shadow=(0, 0, 0, 1)) return text def snowballHitWall(self, snowballIndex): snowball = self.snowballs[snowballIndex] snowball.handleHitWallOrPlayer() base.playSfx(snowball.impactSound, node=snowball, volume=1.5) def snowballHitGround(self, snowballIndex): snowball = self.snowballs[snowballIndex] snowball.handleHitGround() base.playSfx(snowball.impactSound, node=snowball, volume=1.5) def snowballHitPlayer(self, damagedPlayer, throwerTeam, snowballIndex): av = self.getRemoteAvatar(damagedPlayer) if av: if throwerTeam == av.team: # Someone on my team hit me. Unfreeze me if I am frozen. if av.unFreeze(): if damagedPlayer == base.localAvatar.doId: self.showAlert("A team member has unfroze you!") self.firstPerson.camFSM.request('unfrozen') self.sendUpdate('teamMateUnfrozeMe', [self.team]) else: # An enemy hit me. Become frozen if I am not already. if av.freeze(): if damagedPlayer == base.localAvatar.doId: self.showAlert("You've been frozen by an enemy!") self.firstPerson.camFSM.request('frozen') self.sendUpdate('enemyFrozeMe', [self.team, throwerTeam]) snowball = self.snowballs[snowballIndex] snowball.handleHitWallOrPlayer() base.playSfx(snowball.impactSound, node=snowball, volume=1.5) def playerCaughtSnowball(self, snowballIndex, catcherId): av = self.getRemoteAvatar(catcherId) if av: snowball = self.snowballs[snowballIndex] snowball.pauseThrowIval() snowball.pickup(av) def setupRemoteAvatar(self, avId): av = RemoteDodgeballAvatar(self, self.cr, avId) if avId == self.cr.localAvId: self.myRemoteAvatar = av self.remoteAvatars.append(av) def __getSnowTree(self, path): trees = loader.loadModel('phase_8/models/props/snow_trees.bam') tree = trees.find('**/' + path) tree.find('**/*shadow*').removeNode() return tree def load(self): self.setMinigameMusic(DistributedDodgeballGame.GameSong) self.setDescription(DistributedDodgeballGame.GameDesc) self.setWinnerPrize(200) self.setLoserPrize(0) self.createWorld() self.blueScoreLbl = self.getWinterDodgeballScoreText(VBase4( 0, 0, 1, 1)) self.blueScoreLbl.reparentTo(base.a2dTopLeft) self.blueScoreLbl['align'] = TextNode.ALeft self.blueScoreLbl.setText('Blue: 0') self.blueScoreLbl.setZ(-0.17) self.blueScoreLbl.setX(0.05) self.blueScoreLbl.hide() self.redScoreLbl = self.getWinterDodgeballScoreText(VBase4(1, 0, 0, 1)) self.redScoreLbl.reparentTo(base.a2dTopLeft) self.redScoreLbl['align'] = TextNode.ALeft self.redScoreLbl.setText('Red: 0') self.redScoreLbl.setZ(-0.35) self.redScoreLbl.setX(0.05) self.redScoreLbl.hide() trans = DistributedDodgeballGame.InitCamTrans camera.setPos(trans[0]) camera.setHpr(trans[1]) DistributedToonFPSGame.load(self) def createWorld(self): self.deleteWorld() self.arena = loader.loadModel( "phase_4/models/minigames/dodgeball_arena.egg") self.arena.reparentTo(render) self.arena.setScale(0.75) self.arena.find('**/team_divider').setBin('ground', 18) self.arena.find('**/floor').setBin('ground', 18) self.arena.find('**/team_divider_coll').setCollideMask( CIGlobals.FloorBitmask) for data in DistributedDodgeballGame.TreeData: code = data[0] pos = data[1] tree = self.__getSnowTree(code) tree.reparentTo(self.arena) tree.setPos(pos) self.trees.append(tree) for i in xrange(len(DistributedDodgeballGame.SnowballData)): snowdata = DistributedDodgeballGame.SnowballData[i] snowball = Snowball(self, i) snowball.load() snowball.reparentTo(render) snowball.setPos(snowdata) self.snowballs.append(snowball) self.olc = ZoneUtil.getOutdoorLightingConfig(ZoneUtil.TheBrrrgh) self.olc.setupAndApply() def throw(self, snowballIndex, p): snowball = self.snowballs[snowballIndex] snowball.throw(p) def snowballPickup(self, snowballIndex, pickerUpperAvId): remoteAv = self.getRemoteAvatar(pickerUpperAvId) if remoteAv: snowball = self.snowballs[snowballIndex] snowball.pickup(remoteAv) def deleteWorld(self): if self.redScoreLbl: self.redScoreLbl.destroy() self.redScoreLbl = None if self.blueScoreLbl: self.blueScoreLbl.destroy() self.blueScoreLbl = None for snowball in self.snowballs: snowball.removeNode() self.snowballs = [] for tree in self.trees: tree.removeNode() self.trees = [] if self.olc: self.olc.cleanup() self.olc = None if self.arena: self.arena.removeNode() self.arena = None render.clearFog() def enterPlay(self): self.createTimer() self.redScoreLbl.show() self.blueScoreLbl.show() self.firstPerson.camFSM.request('unfrozen') # Stash the other team's barrier. if not self.barrierIsStashed: self.arena.find('**/' + self.Team2OtherBarrier[self.team]).stash() self.barrierIsStashed = True def exitPlay(self): self.firstPerson.crosshair.destroy() self.firstPerson.crosshair = None self.firstPerson.camFSM.request('off') DistributedToonFPSGame.exitPlay(self) def enterCountdown(self): base.transitions.noTransitions() self.firstPerson.start() self.firstPerson.disableMouse() self.setRound(self.getRound() + 1) self.infoText.setText(DistributedDodgeballGame.GetSnowBalls) self.countdownText = getGameText() self.countdownIval = Parallel(Sequence( Func(self.countdownText.setText, "Round {0}".format(self.getRound())), getRoundIval(self.countdownText), Func(self.countdownText.setText, "5"), getCountdownIval(self.countdownText), Func(self.countdownText.setText, "4"), getCountdownIval(self.countdownText), Func(self.countdownText.setText, "3"), getCountdownIval(self.countdownText), Func(self.countdownText.setText, "2"), getCountdownIval(self.countdownText), Func(self.countdownText.setText, "1"), getCountdownIval(self.countdownText)), getAlertPulse(self.infoText), name="COUNTDOWNIVAL") self.countdownIval.setDoneEvent(self.countdownIval.getName()) self.acceptOnce(self.countdownIval.getDoneEvent(), self.__handleCountdownDone) self.countdownIval.start() def __handleCountdownDone(self): self.fsm.request('play') def exitCountdown(self): if hasattr(self, 'countdownIval'): self.ignore(self.countdownIval.getDoneEvent()) self.countdownIval.finish() del self.countdownIval if hasattr(self, 'countdownText'): self.countdownText.destroy() del self.countdownText def enterScrollBy(self): BLUE_START_POS = Point3(-20, 0, 4) BLUE_END_POS = Point3(20, 0, 4) BLUE_HPR = Vec3(0, 0, 0) RED_START_POS = Point3(20, 0, 4) RED_END_POS = Point3(-20, 0, 4) RED_HPR = Vec3(180, 0, 0) self.playMinigameMusic() self.scrollBySeq = Sequence(Func(camera.setHpr, BLUE_HPR), LerpPosInterval(camera, duration=5.0, pos=BLUE_END_POS, startPos=BLUE_START_POS, blendType='easeOut'), Func(base.transitions.fadeOut, 0.4), Wait(0.5), Func(base.transitions.fadeIn, 0.4), Func(camera.setHpr, RED_HPR), LerpPosInterval(camera, duration=5.0, pos=RED_END_POS, startPos=RED_START_POS, blendType='easeOut'), name="SCROLLBYSEQ") self.scrollBySeq.setDoneEvent(self.scrollBySeq.getName()) self.acceptOnce(self.scrollBySeq.getDoneEvent(), self.__handleScrollByDone) self.scrollBySeq.start() def __handleScrollByDone(self): self.fsm.request('countdown') def exitScrollBy(self): if self.scrollBySeq: self.ignore(self.scrollBySeq.getDoneEvent()) self.scrollBySeq.finish() self.scrollBySeq = None def allPlayersReady(self): self.fsm.request('scrollBy') def chooseUrTeam(self): # The AI has told us it's time to choose our team. self.fsm.request('chooseTeam') def enterChooseTeam(self): self.makeSelectionGUI() def acceptedIntoTeam(self, spawnPoint): TeamMinigame.acceptedIntoTeam(self) self.sendUpdate('readyToStart') self.fsm.request('waitForOthers') self.mySpawnPoint = spawnPoint pos, hpr = self.spawnPointsByTeam[self.team][spawnPoint] base.localAvatar.setPos(pos) base.localAvatar.setHpr(hpr) def exitChooseTeam(self): self.destroySelectionGUI() def announceGenerate(self): DistributedToonFPSGame.announceGenerate(self) base.camLens.setMinFov(CIGlobals.GunGameFOV / (4. / 3.)) self.load() def disable(self): base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4. / 3.)) self.fsm.requestFinalState() self.deleteWorld() self.trees = None self.snowballs = None self.spawnPointsByTeam = None if self.firstPerson: self.firstPerson.reallyEnd() self.firstPerson.cleanup() self.firstPerson = None self.scrollBySeq = None self.winnerMusic = None self.loserMusic = None self.danceSound = None self.infoText = None base.localAvatar.setWalkSpeedNormal() DistributedToonFPSGame.disable(self)
class LightDropGag(DropGag): def __init__(self, name, model, anim, damage, hitSfx, missSfx, rotate90=False, sphereSize=2, sphereZ=0): DropGag.__init__(self, name, model, anim, damage, hitSfx, missSfx, scale=1, playRate=1) DropGag.setShadowData(self, isCircle=True, shadowScale=0.5) self.stunTime = 1.5 self.objTrack = None self.rotate90 = rotate90 self.sphereSize = sphereSize self.sphereZ = sphereZ return def startDrop(self): if self.gag and self.dropLoc: x, y, z = self.dropLoc startPos = Point3(x, y, z + 20) self.gag.setPos(x, y + 2, z) self.gag.node().setBounds(OmniBoundingVolume()) self.gag.node().setFinal(1) self.gag.headsUp(self.avatar) if self.rotate90: self.gag.setH(self.gag.getH() - 90) self.buildCollisions() objectTrack = Sequence() animProp = LerpPosInterval(self.gag, self.fallDuration, self.dropLoc, startPos=startPos) bounceProp = Effects.createZBounce(self.gag, 2, self.dropLoc, 0.5, 1.5) objAnimShrink = Sequence(Wait(0.5), Func(self.gag.reparentTo, render), animProp, bounceProp) objectTrack.append(objAnimShrink) dropShadow = loader.loadModel("phase_3/models/props/drop_shadow.bam") dropShadow.reparentTo(render) dropShadow.setPos(self.dropLoc) dropShadow.setScale(self.getShadowScale()) shadowTrack = Sequence( LerpScaleInterval( dropShadow, self.fallDuration + 0.1, dropShadow.getScale(), startScale=Point3(0.01, 0.01, 0.01) ), Wait(0.3), Func(dropShadow.removeNode), ) self.objTrack = Parallel( Sequence(Wait(self.fallDuration), Func(self.completeDrop)), objectTrack, shadowTrack ) self.objTrack.start() self.dropLoc = None return def onActivate(self, ignore, suit): self.objTrack.finish() self.objTrack = None if not suit.isDead(): suit.setAnimState("drop-react") suit.d_disableMovement(wantRay=True) self.gag.setPos(suit.find("**/joint_head").getPos(render)) if self.name == CIGlobals.FlowerPot: self.gag.setZ(self.gag, 3) bounce = Effects.createScaleZBounce(self.gag, 1, self.gag.getScale(render), 0.3, 0.75) dummyNode = suit.attachNewNode("fallOffNode") dummyNode.setX(2) dummyNode.setY(-2) flightIval = FlightProjectileInterval( self.gag, startPos=self.gag.getPos(render), endPos=dummyNode.getPos(render), duration=0.8, gravityMult=0.35 ) Sequence(Parallel(bounce, flightIval), Wait(self.stunTime), Func(suit.d_enableMovement)).start() dummyNode.removeNode() del dummyNode return def buildCollisions(self): gagSph = CollisionSphere(0, 0, self.sphereZ, self.sphereSize) gagSensor = CollisionNode("gagSensor") gagSensor.addSolid(gagSph) sensorNP = self.gag.attachNewNode(gagSensor) sensorNP.setCollideMask(BitMask32(0)) sensorNP.node().setFromCollideMask(CIGlobals.WallBitmask | CIGlobals.FloorBitmask) event = CollisionHandlerEvent() event.set_in_pattern("%fn-into") event.set_out_pattern("%fn-out") base.cTrav.addCollider(sensorNP, event) self.avatar.acceptOnce("gagSensor-into", self.onCollision)