1549 lines
64 KiB
Python
1549 lines
64 KiB
Python
from pandac.PandaModules import Point3, ForceNode, LinearVectorForce, CollisionHandlerEvent, CollisionNode, CollisionSphere, Camera, PerspectiveLens, Vec4, Point2, ActorNode, Vec3, BitMask32
|
|
from direct.interval.IntervalGlobal import Sequence, Parallel, Func, Wait, LerpPosInterval, ActorInterval, LerpScaleInterval, ProjectileInterval, SoundInterval
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from direct.gui.DirectFrame import DirectFrame
|
|
from direct.gui.DirectGui import DGG
|
|
from toontown.toonbase import ToontownGlobals
|
|
from direct.task.Task import Task
|
|
from direct.fsm import ClassicFSM, State
|
|
from toontown.toonbase import TTLocalizer
|
|
from toontown.minigame.DistributedMinigame import DistributedMinigame
|
|
from toontown.minigame import SwingVine
|
|
from toontown.minigame import ArrowKeys
|
|
from toontown.minigame import VineGameGlobals
|
|
from toontown.minigame import VineTreasure
|
|
from toontown.minigame import MinigameAvatarScorePanel
|
|
from toontown.toonbase import ToontownTimer
|
|
from toontown.minigame import VineHeadFrame
|
|
from toontown.minigame import VineBat
|
|
|
|
class DistributedVineGame(DistributedMinigame):
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedVineGame')
|
|
UpdateLocalToonTask = 'VineGameUpdateLocalToonTask'
|
|
LocalPhysicsRadius = 1.5
|
|
Gravity = 32
|
|
ToonVerticalRate = 0.25
|
|
FallingNot = 0
|
|
FallingNormal = 1
|
|
FallingSpider = 2
|
|
FallingBat = 3
|
|
JumpingFrame = 128
|
|
ToonMaxRightFrame = 35
|
|
|
|
def __init__(self, cr):
|
|
DistributedMinigame.__init__(self, cr)
|
|
self.JumpSpeed = 64
|
|
self.TwoVineView = True
|
|
self.ArrowToChangeFacing = True
|
|
self.gameFSM = ClassicFSM.ClassicFSM('DistributedVineGame', [State.State('off', self.enterOff, self.exitOff, ['play']),
|
|
State.State('play', self.enterPlay, self.exitPlay, ['cleanup', 'showScores', 'waitShowScores']),
|
|
State.State('waitShowScores', self.enterWaitShowScores, self.exitWaitShowScores, ['cleanup', 'showScores']),
|
|
State.State('showScores', self.enterShowScores, self.exitShowScores, ['cleanup']),
|
|
State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
|
|
self.addChildGameFSM(self.gameFSM)
|
|
self.cameraTopView = (17.6, 6.18756, 43.9956, 0, -89, 0)
|
|
self.cameraThreeQuarterView = (0, -63.2, 16.3, 0, 0, 0)
|
|
self.cameraSidePos = Point3(0, -63.2, 16.3)
|
|
self.cameraTwoVineSidePos = Point3(0, -53, 17.3)
|
|
self.cameraTwoVineAdj = 5
|
|
self.cameraSideView = (-15, -53, 17.3, 0, 0, 0)
|
|
self.localPhysicsNP = None
|
|
self.vines = []
|
|
self.physicsHandler = None
|
|
self.lastJumpVine = -1
|
|
self.lastJumpPos = None
|
|
self.lastJumpT = 0
|
|
self.lastJumpFacingRight = True
|
|
self.lastJumpTime = 0
|
|
self.toonInfo = {}
|
|
self.otherToonPhysics = {}
|
|
self.headFrames = {}
|
|
self.changeFacingInterval = None
|
|
self.attachingToVineCamIval = None
|
|
self.localToonJumpAnimIval = None
|
|
self.endingTracks = {}
|
|
self.endingTrackTaskNames = []
|
|
self.sendNewVineTUpdateAsap = False
|
|
self.lastNewVineTUpdate = 0
|
|
self.defaultMaxX = (VineGameGlobals.NumVines + 1) * VineGameGlobals.VineXIncrement
|
|
return
|
|
|
|
def getClimbDir(self, avId):
|
|
retval = 0
|
|
if avId in self.toonInfo:
|
|
retval = self.toonInfo[avId][5]
|
|
return retval
|
|
|
|
def moveCameraToSide(self):
|
|
camera.reparentTo(render)
|
|
p = self.cameraSideView
|
|
camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5])
|
|
|
|
def getTitle(self):
|
|
return TTLocalizer.VineGameTitle
|
|
|
|
def getInstructions(self):
|
|
return TTLocalizer.VineGameInstructions
|
|
|
|
def getMaxDuration(self):
|
|
return 0
|
|
|
|
def defineConstants(self):
|
|
self.ShowToonSpheres = 0
|
|
|
|
def load(self):
|
|
self.notify.debug('load')
|
|
DistributedMinigame.load(self)
|
|
self.defineConstants()
|
|
self.music = base.loadMusic('phase_4/audio/bgm/MG_Vine.ogg')
|
|
self.gameAssets = loader.loadModel('phase_4/models/minigames/vine_game')
|
|
self.gameBoard = self.gameAssets.find('**/background')
|
|
self.gameBoard.reparentTo(render)
|
|
self.gameBoard.show()
|
|
self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0)
|
|
self.gameBoard.setTransparency(1)
|
|
self.gameBoard.setColorScale(1, 1, 1, 0.5)
|
|
self.gameBoard.setScale(1.0)
|
|
self.gameBoard.hide(VineGameGlobals.RadarCameraBitmask)
|
|
self.gameBoardL = self.gameBoard.copyTo(render)
|
|
self.gameBoardL.setPos(-635, 0, 0)
|
|
self.gameBoardR = self.gameBoard.copyTo(render)
|
|
self.gameBoardR.setPos(635, 0, 0)
|
|
self.treasureModel = self.gameAssets.find('**/bananas')
|
|
self.setupVineCourse()
|
|
self.grabSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_bananas.ogg')
|
|
self.jumpSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_jump.ogg')
|
|
self.catchSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_catch.ogg')
|
|
self.spiderHitSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_spider_hit.ogg')
|
|
self.batHitVineSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_bat_hit.ogg')
|
|
self.batHitMidairSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_bat_hit_midair.ogg')
|
|
self.winSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_finish.ogg')
|
|
self.fallSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_fall.ogg')
|
|
self.loadBats()
|
|
self.createBatIvals()
|
|
bothPlatform = loader.loadModel('phase_4/models/minigames/vine_game_shelf')
|
|
self.startPlatform = bothPlatform.find('**/start1')
|
|
self.startPlatform.setPos(-16, 0, 15)
|
|
self.startPlatform.reparentTo(render)
|
|
self.startPlatform.setScale(1.0, 1.0, 0.75)
|
|
self.endPlatform = bothPlatform.find('**/end1')
|
|
endPos = self.vines[VineGameGlobals.NumVines - 1].getPos()
|
|
self.endPlatform.setPos(endPos[0] + 20, 0, 15)
|
|
self.endPlatform.reparentTo(render)
|
|
self.endPlatform.setScale(1.0, 1.0, 0.75)
|
|
|
|
def unload(self):
|
|
self.notify.debug('unload')
|
|
DistributedMinigame.unload(self)
|
|
self.removeChildGameFSM(self.gameFSM)
|
|
del self.gameFSM
|
|
del self.music
|
|
self.gameAssets.removeNode()
|
|
self.gameBoard.removeNode()
|
|
self.gameBoardL.removeNode()
|
|
self.gameBoardR.removeNode()
|
|
del self.gameBoard
|
|
del self.gameBoardL
|
|
del self.gameBoardR
|
|
self.treasureModel.removeNode()
|
|
del self.treasureModel
|
|
for vine in self.vines:
|
|
vine.unload()
|
|
del vine
|
|
|
|
self.vines = []
|
|
self.destroyBatIvals()
|
|
for bat in self.bats:
|
|
bat.destroy()
|
|
del bat
|
|
|
|
self.bats = []
|
|
del self.grabSound
|
|
del self.jumpSound
|
|
del self.catchSound
|
|
del self.spiderHitSound
|
|
del self.batHitVineSound
|
|
del self.batHitMidairSound
|
|
del self.winSound
|
|
del self.fallSound
|
|
if self.localToonJumpAnimIval:
|
|
self.localToonJumpAnimIval.finish()
|
|
del self.localToonJumpAnimIval
|
|
self.startPlatform.removeNode()
|
|
self.endPlatform.removeNode()
|
|
|
|
def onstage(self):
|
|
self.notify.debug('onstage')
|
|
DistributedMinigame.onstage(self)
|
|
for avId in self.avIdList:
|
|
self.updateToonInfo(avId, vineIndex=0, vineT=VineGameGlobals.VineStartingT, posX=0, posZ=0, facingRight=0, climbDir=0, fallingInfo=self.FallingNot)
|
|
|
|
self.scorePanels = []
|
|
self.gameBoard.reparentTo(render)
|
|
self.moveCameraToSide()
|
|
self.arrowKeys = ArrowKeys.ArrowKeys()
|
|
handlers = [self.upArrowKeyHandler,
|
|
self.downArrowKeyHandler,
|
|
self.leftArrowKeyHandler,
|
|
self.rightArrowKeyHandler,
|
|
None]
|
|
self.arrowKeys.setPressHandlers(handlers)
|
|
self.numTreasures = len(self.vines) - 1
|
|
self.treasures = []
|
|
for i in xrange(self.numTreasures):
|
|
height = self.randomNumGen.randrange(10, 25)
|
|
xPos = self.randomNumGen.randrange(12, 18)
|
|
pos = Point3(self.vines[i].getX() + 15, 0, height)
|
|
self.treasures.append(VineTreasure.VineTreasure(self.treasureModel, pos, i, self.doId))
|
|
|
|
gravityFN = ForceNode('world-forces')
|
|
gravityFNP = render.attachNewNode(gravityFN)
|
|
gravityForce = LinearVectorForce(0, 0, -self.Gravity)
|
|
gravityFN.addForce(gravityForce)
|
|
base.physicsMgr.addLinearForce(gravityForce)
|
|
self.gravityForce = gravityForce
|
|
self.gravityForceFNP = gravityFNP
|
|
lt = base.localAvatar
|
|
radius = 0.7
|
|
handler = CollisionHandlerEvent()
|
|
handler.setInPattern('ltCatch-%fn')
|
|
self.bodyColEventNames = []
|
|
self.ltLegsCollNode = CollisionNode('catchLegsCollNode')
|
|
self.bodyColEventNames.append('ltCatch-%s' % 'catchLegsCollNode')
|
|
self.ltLegsCollNode.setCollideMask(VineGameGlobals.SpiderBitmask)
|
|
self.ltTorsoCollNode = CollisionNode('catchTorsoCollNode')
|
|
self.bodyColEventNames.append('ltCatch-%s' % 'catchTorsoCollNode')
|
|
self.ltTorsoCollNode.setCollideMask(VineGameGlobals.SpiderBitmask)
|
|
self.ltHeadCollNode = CollisionNode('catchHeadCollNode')
|
|
self.bodyColEventNames.append('ltCatch-%s' % 'catchHeadCollNode')
|
|
self.ltHeadCollNode.setCollideMask(VineGameGlobals.SpiderBitmask)
|
|
self.ltLHandCollNode = CollisionNode('catchLHandCollNode')
|
|
self.bodyColEventNames.append('ltCatch-%s' % 'catchLHandCollNode')
|
|
self.ltLHandCollNode.setCollideMask(VineGameGlobals.SpiderBitmask)
|
|
self.ltRHandCollNode = CollisionNode('catchRHandCollNode')
|
|
self.bodyColEventNames.append('ltCatch-%s' % 'catchRHandCollNode')
|
|
self.ltRHandCollNode.setCollideMask(VineGameGlobals.SpiderBitmask)
|
|
legsCollNodepath = lt.attachNewNode(self.ltLegsCollNode)
|
|
legsCollNodepath.hide()
|
|
head = base.localAvatar.getHeadParts().getPath(2)
|
|
headCollNodepath = head.attachNewNode(self.ltHeadCollNode)
|
|
headCollNodepath.hide()
|
|
torso = base.localAvatar.getTorsoParts().getPath(2)
|
|
torsoCollNodepath = torso.attachNewNode(self.ltTorsoCollNode)
|
|
torsoCollNodepath.hide()
|
|
self.torso = torsoCollNodepath
|
|
lHand = base.localAvatar.getLeftHands()[0]
|
|
lHandCollNodepath = lHand.attachNewNode(self.ltLHandCollNode)
|
|
lHandCollNodepath.hide()
|
|
rHand = base.localAvatar.getRightHands()[0]
|
|
rHandCollNodepath = rHand.attachNewNode(self.ltRHandCollNode)
|
|
rHandCollNodepath.hide()
|
|
lt.cTrav.addCollider(legsCollNodepath, handler)
|
|
lt.cTrav.addCollider(headCollNodepath, handler)
|
|
lt.cTrav.addCollider(lHandCollNodepath, handler)
|
|
lt.cTrav.addCollider(rHandCollNodepath, handler)
|
|
lt.cTrav.addCollider(torsoCollNodepath, handler)
|
|
if self.ShowToonSpheres:
|
|
legsCollNodepath.show()
|
|
headCollNodepath.show()
|
|
lHandCollNodepath.show()
|
|
rHandCollNodepath.show()
|
|
torsoCollNodepath.show()
|
|
self.ltLegsCollNode.addSolid(CollisionSphere(0, 0, radius, radius))
|
|
self.ltHeadCollNode.addSolid(CollisionSphere(0, 0, 0, radius))
|
|
self.ltLHandCollNode.addSolid(CollisionSphere(0, 0, 0, 2 * radius / 3.0))
|
|
self.ltRHandCollNode.addSolid(CollisionSphere(0, 0, 0, 2 * radius / 3.0))
|
|
self.ltTorsoCollNode.addSolid(CollisionSphere(0, 0, radius, radius * 2))
|
|
self.toonCollNodes = [legsCollNodepath,
|
|
headCollNodepath,
|
|
lHandCollNodepath,
|
|
rHandCollNodepath,
|
|
torsoCollNodepath]
|
|
for eventName in self.bodyColEventNames:
|
|
self.accept(eventName, self.toonHitSomething)
|
|
|
|
self.introTrack = self.getIntroTrack()
|
|
self.introTrack.start()
|
|
return
|
|
|
|
def offstage(self):
|
|
self.notify.debug('offstage')
|
|
for panel in self.scorePanels:
|
|
panel.cleanup()
|
|
|
|
del self.scorePanels
|
|
self.gameBoard.hide()
|
|
DistributedMinigame.offstage(self)
|
|
self.arrowKeys.destroy()
|
|
del self.arrowKeys
|
|
for avId in self.avIdList:
|
|
av = self.getAvatar(avId)
|
|
if av:
|
|
av.dropShadow.show()
|
|
av.resetLOD()
|
|
|
|
for treasure in self.treasures:
|
|
treasure.destroy()
|
|
|
|
del self.treasures
|
|
base.physicsMgr.removeLinearForce(self.gravityForce)
|
|
self.gravityForceFNP.removeNode()
|
|
for collNode in self.toonCollNodes:
|
|
while collNode.node().getNumSolids():
|
|
collNode.node().removeSolid(0)
|
|
|
|
base.localAvatar.cTrav.removeCollider(collNode)
|
|
|
|
del self.toonCollNodes
|
|
for eventName in self.bodyColEventNames:
|
|
self.ignore(eventName)
|
|
|
|
self.ignoreAll()
|
|
if self.introTrack.isPlaying():
|
|
self.introTrack.finish()
|
|
del self.introTrack
|
|
for vine in self.vines:
|
|
vine.stopSwing()
|
|
vine.hide()
|
|
|
|
self.startPlatform.hide()
|
|
self.endPlatform.hide()
|
|
|
|
def handleDisabledAvatar(self, avId):
|
|
self.notify.debug('handleDisabledAvatar')
|
|
self.notify.debug('avatar ' + str(avId) + ' disabled')
|
|
DistributedMinigame.handleDisabledAvatar(self, avId)
|
|
|
|
def updateToonInfo(self, avId, vineIndex = None, vineT = None, posX = None, posZ = None, facingRight = None, climbDir = None, velX = None, velZ = None, fallingInfo = None):
|
|
newVineIndex = vineIndex
|
|
newVineT = vineT
|
|
newPosX = posX
|
|
newPosZ = posZ
|
|
newFacingRight = facingRight
|
|
newClimbDir = climbDir
|
|
newVelX = velX
|
|
newVelZ = velZ
|
|
newFallingInfo = fallingInfo
|
|
oldInfo = None
|
|
if avId in self.toonInfo:
|
|
oldInfo = self.toonInfo[avId]
|
|
if vineIndex == None:
|
|
newVineIndex = oldInfo[0]
|
|
if vineT == None:
|
|
newVineT = oldInfo[1]
|
|
if posX == None:
|
|
newPosX = oldInfo[2]
|
|
if posZ == None:
|
|
newPosZ = oldInfo[3]
|
|
if facingRight == None:
|
|
newFacingRight = oldInfo[4]
|
|
if climbDir == None:
|
|
newClimbDir = oldInfo[5]
|
|
if velX == None:
|
|
newVelX = oldInfo[6]
|
|
if velZ == None:
|
|
newVelZ = oldInfo[7]
|
|
if fallingInfo == None:
|
|
newFallingInfo = oldInfo[8]
|
|
if newVineIndex < -1 or newVineIndex >= len(self.vines):
|
|
self.notify.warning('invalid vineIndex for %d, forcing 0' % avId)
|
|
newVineIndex = 0
|
|
if newVineT < 0 or newVineT > 1:
|
|
self.notify.warning('invalid vineT for %d, setting to 0' % avId)
|
|
if not (newFacingRight == 0 or newFacingRight == 1):
|
|
self.notify.warning('invalid facingRight for %d, forcing to 1' % avId)
|
|
newFacingRight = 1
|
|
if newPosX < -1000 or newPosX > 2000:
|
|
self.notify.warning('invalid posX for %d, forcing to 0' % avId)
|
|
newPosX = 0
|
|
if newPosZ < -100 or newPosZ > 1000:
|
|
self.notify.warning('invalid posZ for %d, forcing to 0' % avId)
|
|
newPosZ = 0
|
|
if newVelX < -1000 or newVelX > 1000:
|
|
self.notify.warning('invalid velX %s for %d, forcing to 0' % (newVelX, avId))
|
|
newVelX = 0
|
|
if newVelZ < -1000 or newVelZ > 1000:
|
|
self.notify.warning('invalid velZ %s for %d, forcing to 0' % (newVelZ, avId))
|
|
newVelZ = 0
|
|
if newFallingInfo < self.FallingNot or newFallingInfo > self.FallingBat:
|
|
self.notify.warning('invalid fallingInfo for %d, forcing to 0' % avId)
|
|
newFallingInfo = 0
|
|
newInfo = [newVineIndex,
|
|
newVineT,
|
|
newPosX,
|
|
newPosZ,
|
|
newFacingRight,
|
|
newClimbDir,
|
|
newVelX,
|
|
newVelZ,
|
|
newFallingInfo]
|
|
self.toonInfo[avId] = newInfo
|
|
if oldInfo:
|
|
self.applyToonInfoChange(avId, newInfo, oldInfo)
|
|
self.sanityCheck()
|
|
return
|
|
|
|
def applyToonInfoChange(self, avId, newInfo, oldInfo):
|
|
if not self.isInPlayState():
|
|
return
|
|
oldVine = oldInfo[0]
|
|
newVine = newInfo[0]
|
|
if not oldVine == newVine:
|
|
self.notify.debug('we have a vine change')
|
|
if oldVine == -1:
|
|
self.notify.debug(' we were jumping and now attaching to a new vine')
|
|
newVineT = newInfo[1]
|
|
newFacingRight = newInfo[4]
|
|
self.vines[newVine].attachToon(avId, newVineT, newFacingRight)
|
|
if newVine == VineGameGlobals.NumVines - 1:
|
|
self.doEndingTrackTask(avId)
|
|
elif newVine == -1:
|
|
self.notify.debug('we were attached to a vine and we are now jumping')
|
|
curInfo = self.vines[oldVine].getAttachedToonInfo(avId)
|
|
self.vines[oldVine].detachToon(avId)
|
|
if not avId == self.localAvId:
|
|
posX = newInfo[2]
|
|
posZ = newInfo[3]
|
|
velX = newInfo[6]
|
|
velZ = newInfo[7]
|
|
self.makeOtherToonJump(avId, posX, posZ, velX, velZ)
|
|
else:
|
|
self.notify.warning('should not happen directly going from one vine to another')
|
|
self.vines[oldVine].detachToon(avId)
|
|
newVineT = newInfo[1]
|
|
newFacingRight = newInfo[4]
|
|
self.vines[newVine].attachToon(avId, newVineT, newFacingRight)
|
|
elif newVine == oldVine and newInfo[4] != oldInfo[4]:
|
|
self.notify.debug('# still on the same vine, but we changed facing')
|
|
self.vines[newVine].changeAttachedToonFacing(avId, newInfo[4])
|
|
elif newVine >= 0:
|
|
self.vines[newVine].changeAttachedToonT(avId, newInfo[1])
|
|
else:
|
|
self.notify.debug('we are still falling')
|
|
if oldInfo[8] != newInfo[8]:
|
|
if not avId == self.localAvId:
|
|
posX = newInfo[2]
|
|
posZ = newInfo[3]
|
|
velX = newInfo[6]
|
|
velZ = newInfo[7]
|
|
self.makeOtherToonFallFromMidair(avId, posX, posZ, velX, velZ)
|
|
|
|
def sanityCheck(self):
|
|
if not self.isInPlayState():
|
|
return
|
|
for avId in self.toonInfo.keys():
|
|
myVineIndex = self.toonInfo[avId][0]
|
|
foundVines = []
|
|
foundVineIndex = -1
|
|
for curVine in xrange(len(self.vines)):
|
|
curInfo = self.vines[curVine].getAttachedToonInfo(avId)
|
|
if curInfo:
|
|
foundVines.append(curVine)
|
|
foundVineIndex = curVine
|
|
|
|
if len(foundVines) > 1:
|
|
self.notify.warning('toon %d is attached to vines %s' % (avId, foundVines))
|
|
if not foundVineIndex == myVineIndex and not myVineIndex == VineGameGlobals.NumVines - 1:
|
|
self.notify.warning('avId=%d foundVineIndex=%d != myVineIndex=%d' % (avId, foundVineIndex, myVineIndex))
|
|
|
|
def getVineAndVineInfo(self, avId):
|
|
retVine = -1
|
|
retInfo = None
|
|
for curVine in xrange(len(self.vines)):
|
|
curInfo = self.vines[curVine].getAttachedToonInfo(avId)
|
|
if curInfo:
|
|
retVine = curVine
|
|
retInfo = curInfo
|
|
break
|
|
|
|
if self.toonInfo[avId][0] != retVine:
|
|
self.notify.warning("getVineAndVineInfo don't agree, toonInfo[%d]=%s, retVine=%d" % (avId, self.toonInfo[avId][0], retVine))
|
|
return (retVine, curInfo)
|
|
|
|
def setGameReady(self):
|
|
if not self.hasLocalToon:
|
|
return
|
|
self.notify.debug('setGameReady')
|
|
if DistributedMinigame.setGameReady(self):
|
|
return
|
|
self.toonOffsets = {}
|
|
self.toonOffsetsFalling = {}
|
|
for index in xrange(self.numPlayers):
|
|
avId = self.avIdList[index]
|
|
toon = self.getAvatar(avId)
|
|
if toon:
|
|
toon.reparentTo(render)
|
|
toon.setPos(0, 0, 0)
|
|
toon.setHpr(0, 0, 0)
|
|
self.toonOffsets[avId] = self.calcToonOffset(toon)
|
|
toon.dropShadow.hide()
|
|
newHeadFrame = VineHeadFrame.VineHeadFrame(toon)
|
|
newHeadFrame.hide()
|
|
self.headFrames[avId] = newHeadFrame
|
|
toon.useLOD(1000)
|
|
toon.setX(-100)
|
|
|
|
def calcToonOffset(self, toon):
|
|
offset = Point3(0, 0, 0)
|
|
toon.pose('swing', 74)
|
|
leftHand = toon.find('**/leftHand')
|
|
if not leftHand.isEmpty():
|
|
offset = leftHand.getPos(toon)
|
|
return offset
|
|
|
|
def setGameStart(self, timestamp):
|
|
if not self.hasLocalToon:
|
|
return
|
|
self.notify.debug('setGameStart')
|
|
DistributedMinigame.setGameStart(self, timestamp)
|
|
if self.introTrack.isPlaying():
|
|
self.introTrack.finish()
|
|
self.gameFSM.request('play')
|
|
|
|
def enterOff(self):
|
|
self.notify.debug('enterOff')
|
|
|
|
def exitOff(self):
|
|
pass
|
|
|
|
def enterPlay(self):
|
|
self.notify.debug('enterPlay')
|
|
if base.localAvatar.laffMeter:
|
|
base.localAvatar.laffMeter.stop()
|
|
self.createRadar()
|
|
self.scores = [0] * self.numPlayers
|
|
spacing = 0.4
|
|
for i in xrange(self.numPlayers):
|
|
avId = self.avIdList[i]
|
|
avName = self.getAvatarName(avId)
|
|
scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel(avId, avName)
|
|
scorePanel.setScale(0.9)
|
|
scorePanel.setPos(-0.583 - spacing * (self.numPlayers - 1 - i), 0.0, -0.15)
|
|
scorePanel.reparentTo(base.a2dTopRight)
|
|
scorePanel.makeTransparent(0.75)
|
|
self.scorePanels.append(scorePanel)
|
|
|
|
for vine in self.vines:
|
|
vine.show()
|
|
vine.startSwing()
|
|
|
|
self.startBatIvals()
|
|
for avId in self.avIdList:
|
|
toon = self.getAvatar(avId)
|
|
if toon:
|
|
if avId == self.localAvId:
|
|
self.attachLocalToonToVine(0, VineGameGlobals.VineStartingT)
|
|
else:
|
|
self.vines[0].attachToon(avId, VineGameGlobals.VineStartingT, self.lastJumpFacingRight)
|
|
|
|
self.timer = ToontownTimer.ToontownTimer()
|
|
self.timer.posInTopRightCorner()
|
|
self.timer.setTime(VineGameGlobals.GameDuration)
|
|
self.timer.countdown(VineGameGlobals.GameDuration, self.timerExpired)
|
|
base.playMusic(self.music, looping=1, volume=0.9)
|
|
self.__spawnUpdateLocalToonTask()
|
|
|
|
def exitPlay(self):
|
|
self.notify.debug('exitPlay')
|
|
if base.localAvatar.laffMeter:
|
|
base.localAvatar.laffMeter.start()
|
|
self.timer.stop()
|
|
self.timer.destroy()
|
|
del self.timer
|
|
self.clearLocalPhysics()
|
|
for ival in self.batIvals:
|
|
ival.finish()
|
|
del ival
|
|
|
|
self.batIvals = []
|
|
self.music.stop()
|
|
|
|
def enterWaitShowScores(self):
|
|
self.notify.debug('enterWaitShowScores')
|
|
|
|
def exitWaitShowScores(self):
|
|
self.notify.debug('exitWaitShowScores')
|
|
|
|
def enterShowScores(self):
|
|
self.notify.debug('enterShowScores')
|
|
lerpTrack = Parallel()
|
|
lerpDur = 0.5
|
|
tY = 0.6
|
|
bY = -.05
|
|
lX = -.5
|
|
cX = 0
|
|
rX = 0.5
|
|
scorePanelLocs = (((cX, bY),),
|
|
((lX, bY), (rX, bY)),
|
|
((cX, tY), (lX, bY), (rX, bY)),
|
|
((lX, tY),
|
|
(rX, tY),
|
|
(lX, bY),
|
|
(rX, bY)))
|
|
scorePanelLocs = scorePanelLocs[self.numPlayers - 1]
|
|
for i in xrange(self.numPlayers):
|
|
panel = self.scorePanels[i]
|
|
pos = scorePanelLocs[i]
|
|
panel.wrtReparentTo(aspect2d)
|
|
lerpTrack.append(Parallel(LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType='easeInOut'), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType='easeInOut')))
|
|
|
|
self.showScoreTrack = Parallel(lerpTrack, Sequence(Wait(VineGameGlobals.ShowScoresDuration), Func(self.gameOver)))
|
|
self.showScoreTrack.start()
|
|
|
|
def exitShowScores(self):
|
|
self.showScoreTrack.pause()
|
|
del self.showScoreTrack
|
|
|
|
def enterCleanup(self):
|
|
self.notify.debug('enterCleanup')
|
|
self.destroyRadar()
|
|
self.__killUpdateLocalToonTask()
|
|
self.cleanupEndingTracks()
|
|
for avId in self.headFrames:
|
|
self.headFrames[avId].destroy()
|
|
|
|
def exitCleanup(self):
|
|
pass
|
|
|
|
def __spawnUpdateLocalToonTask(self):
|
|
taskMgr.remove(self.UpdateLocalToonTask)
|
|
taskMgr.add(self.__updateLocalToonTask, self.UpdateLocalToonTask)
|
|
|
|
def __killUpdateLocalToonTask(self):
|
|
taskMgr.remove(self.UpdateLocalToonTask)
|
|
|
|
def clearLocalPhysics(self):
|
|
if self.localPhysicsNP:
|
|
an = self.localPhysicsNP.node()
|
|
base.physicsMgr.removePhysicalNode(an)
|
|
self.localPhysicsNP.removeNode()
|
|
del self.localPhysicsNP
|
|
self.localPhysicsNP = None
|
|
if hasattr(self, 'treasureCollNodePath') and self.treasureCollNodePath:
|
|
self.treasureCollNodePath.removeNode()
|
|
return
|
|
|
|
def handleLocalToonFellDown(self):
|
|
self.notify.debug('attaching toon back to vine since he fell')
|
|
self.fallSound.play()
|
|
vineToAttach = self.lastJumpVine
|
|
if self.toonInfo[self.localAvId][8] == self.FallingSpider:
|
|
if self.vines[vineToAttach].hasSpider:
|
|
vineToAttach -= 1
|
|
if vineToAttach < 0:
|
|
vineToAttach = 0
|
|
self.attachLocalToonToVine(vineToAttach, VineGameGlobals.VineFellDownT)
|
|
|
|
def makeCameraFollowJumpingToon(self):
|
|
camera.setHpr(0, 0, 0)
|
|
if self.TwoVineView:
|
|
camera.setPos(self.cameraTwoVineSidePos)
|
|
maxVine = self.lastJumpVine + 1
|
|
if maxVine >= len(self.vines):
|
|
maxVine = len(self.vines) - 1
|
|
maxX = self.defaultMaxX
|
|
if self.vines:
|
|
maxX = self.vines[maxVine].getX()
|
|
minVine = self.lastJumpVine - 1
|
|
if minVine < 0:
|
|
minVine = 0
|
|
minX = 0
|
|
if self.vines:
|
|
minX = self.vines[minVine].getX()
|
|
camera.setX(base.localAvatar.getX(render))
|
|
if camera.getX() > maxX:
|
|
camera.setX(maxX)
|
|
if camera.getX() < minX:
|
|
camera.setX(minX)
|
|
else:
|
|
camera.setPos(self.cameraSidePos)
|
|
maxVine = self.lastJumpVine + 1
|
|
if maxVine >= len(self.vines):
|
|
maxVine = len(self.vines) - 1
|
|
maxX = self.vines[maxVine].getX()
|
|
minVine = self.lastJumpVine - 1
|
|
if minVine < 0:
|
|
minVine = 0
|
|
minX = self.vines[minVine].getX()
|
|
camera.setX(base.localAvatar.getX(render))
|
|
if camera.getX() > maxX:
|
|
camera.setX(maxX)
|
|
if camera.getX() < minX:
|
|
camera.setX(minX)
|
|
|
|
def __updateOtherToonsClimbing(self):
|
|
for avId in self.toonInfo.keys():
|
|
if avId == self.localAvId:
|
|
continue
|
|
toonInfo = self.toonInfo[avId]
|
|
vineIndex = toonInfo[0]
|
|
if vineIndex == -1:
|
|
continue
|
|
climbDir = toonInfo[5]
|
|
if climbDir == None or climbDir == 0:
|
|
continue
|
|
curT = toonInfo[1]
|
|
dt = globalClock.getDt()
|
|
diffT = 0
|
|
baseVerticalRate = self.ToonVerticalRate
|
|
if climbDir == -1:
|
|
diffT -= baseVerticalRate * dt
|
|
if climbDir == 1:
|
|
diffT += baseVerticalRate * dt
|
|
newT = curT + diffT
|
|
if newT > 1:
|
|
newT = 1
|
|
if newT < 0:
|
|
newT = 0
|
|
if not newT == curT:
|
|
toonInfo[1] = newT
|
|
self.vines[vineIndex].changeAttachedToonT(avId, newT)
|
|
|
|
return
|
|
|
|
def __updateLocalToonTask(self, task):
|
|
dt = globalClock.getDt()
|
|
self.updateRadar()
|
|
self.__updateOtherToonsClimbing()
|
|
for bat in self.bats:
|
|
bat.checkScreech()
|
|
|
|
if self.localPhysicsNP:
|
|
pos = self.localPhysicsNP.getPos(render)
|
|
if pos[2] < 0:
|
|
self.handleLocalToonFellDown()
|
|
avId = self.localAvId
|
|
curInfo = None
|
|
for vineIndex in xrange(len(self.vines)):
|
|
curInfo = self.vines[vineIndex].getAttachedToonInfo(avId)
|
|
if curInfo:
|
|
break
|
|
|
|
if not curInfo:
|
|
if avId not in self.endingTracks:
|
|
self.makeCameraFollowJumpingToon()
|
|
if self.localPhysicsNP:
|
|
pos = self.localPhysicsNP.getPos(render)
|
|
else:
|
|
curT = curInfo[0]
|
|
diffT = 0
|
|
baseVerticalRate = self.ToonVerticalRate
|
|
onEndVine = vineIndex == len(self.vines) - 1
|
|
if self.arrowKeys.upPressed() and not onEndVine and self.isInPlayState():
|
|
diffT -= baseVerticalRate * dt
|
|
if self.arrowKeys.downPressed() and not onEndVine and self.isInPlayState():
|
|
diffT += baseVerticalRate * dt
|
|
newT = curT + diffT
|
|
if newT > 1:
|
|
newT = 1
|
|
if newT < 0:
|
|
newT = 0
|
|
oldClimbDir = self.getClimbDir(avId)
|
|
climbDir = 0
|
|
if diffT < 0:
|
|
climbDir = -1
|
|
elif diffT > 0:
|
|
climbDir = 1
|
|
if not newT == curT:
|
|
self.vines[vineIndex].changeAttachedToonT(avId, newT)
|
|
if newT != curT or self.getClimbDir(avId) and not curT == 1.0 or oldClimbDir != climbDir:
|
|
if oldClimbDir != climbDir:
|
|
self.sendNewVineTUpdateAsap = True
|
|
self.b_setNewVineT(avId, newT, climbDir)
|
|
return task.cont
|
|
|
|
def setupCollisions(self, anp):
|
|
fromObject = anp.attachNewNode(CollisionNode('colNode'))
|
|
fromObject.node().addSolid(CollisionSphere(0, 0, 0, self.LocalPhysicsRadius))
|
|
fromCollideMask = ToontownGlobals.PieBitmask
|
|
self.notify.debug('fromCollideMask = %s' % fromCollideMask)
|
|
fromObject.node().setFromCollideMask(fromCollideMask)
|
|
self.handler = CollisionHandlerEvent()
|
|
self.handler.addInPattern('%fn-into')
|
|
base.cTrav.setRespectPrevTransform(True)
|
|
base.cTrav.addCollider(fromObject, self.handler)
|
|
eventName = '%s-into' % fromObject.getName()
|
|
self.accept(eventName, self.swingVineEnter)
|
|
height = base.localAvatar.getHeight()
|
|
self.treasureSphereName = 'treasureCollider'
|
|
center = Point3(0, 0, 0)
|
|
radius = VineTreasure.VineTreasure.RADIUS
|
|
self.treasureCollSphere = CollisionSphere(center[0], center[1], center[2], radius)
|
|
self.treasureCollSphere.setTangible(0)
|
|
self.treasureCollNode = CollisionNode(self.treasureSphereName)
|
|
self.treasureCollNode.setFromCollideMask(ToontownGlobals.WallBitmask)
|
|
self.treasureCollNode.addSolid(self.treasureCollSphere)
|
|
self.treasureCollNodePath = self.torso.attachNewNode(self.treasureCollNode)
|
|
self.treasureHandler = CollisionHandlerEvent()
|
|
self.treasureHandler.addInPattern('%fn-intoTreasure')
|
|
base.cTrav.addCollider(self.treasureCollNodePath, self.treasureHandler)
|
|
eventName = '%s-intoTreasure' % self.treasureCollNodePath.getName()
|
|
self.notify.debug('eventName = %s' % eventName)
|
|
self.accept(eventName, self.treasureEnter)
|
|
|
|
def getFocusCameraPos(self, vineIndex, facingRight):
|
|
retPos = Point3(0, 0, 0)
|
|
if self.TwoVineView:
|
|
pos = self.vines[vineIndex].getPos()
|
|
retPos = Point3(self.cameraTwoVineSidePos)
|
|
if vineIndex == 0:
|
|
nextVinePos = self.vines[vineIndex + 1].getPos()
|
|
newX = (pos.getX() + nextVinePos.getX()) / 2.0
|
|
newX -= self.cameraTwoVineAdj
|
|
retPos.setX(newX)
|
|
elif vineIndex == VineGameGlobals.NumVines - 1:
|
|
nextVinePos = self.vines[vineIndex].getPos()
|
|
nextVinePos.setX(nextVinePos.getX() + VineGameGlobals.VineXIncrement)
|
|
newX = (pos.getX() + nextVinePos.getX()) / 2.0
|
|
newX += self.cameraTwoVineAdj
|
|
retPos.setX(newX)
|
|
else:
|
|
otherVineIndex = vineIndex - 1
|
|
if self.lastJumpFacingRight:
|
|
otherVineIndex = vineIndex + 1
|
|
nextVinePos = self.vines[otherVineIndex].getPos()
|
|
newX = (pos.getX() + nextVinePos.getX()) / 2.0
|
|
if self.lastJumpFacingRight:
|
|
newX -= self.cameraTwoVineAdj
|
|
else:
|
|
newX += self.cameraTwoVineAdj
|
|
retPos.setX(newX)
|
|
else:
|
|
pos = self.vines[vineIndex].getPos()
|
|
retPos.setX(pos.getX())
|
|
self.notify.debug('getFocusCameraPos returning %s' % retPos)
|
|
return retPos
|
|
|
|
def focusCameraOnVine(self, vineIndex):
|
|
camera.setHpr(0, 0, 0)
|
|
newCameraPos = self.getFocusCameraPos(vineIndex, self.lastJumpFacingRight)
|
|
camera.setPos(newCameraPos)
|
|
|
|
def attachLocalToonToVine(self, vineIndex, vineT, focusCameraImmediately = True, playSfx = False):
|
|
self.notify.debug('focusCameraImmediately = %s' % focusCameraImmediately)
|
|
if playSfx:
|
|
self.catchSound.play()
|
|
self.clearLocalPhysics()
|
|
vine = self.vines[vineIndex]
|
|
self.lastJumpVine = -1
|
|
self.lastJumpPos = None
|
|
self.lastJumpT = 0
|
|
if focusCameraImmediately:
|
|
self.focusCameraOnVine(vineIndex)
|
|
self.b_setNewVine(self.localAvId, vineIndex, vineT, self.lastJumpFacingRight)
|
|
return
|
|
|
|
def setupJumpingTransitionIval(self, vineIndex):
|
|
self.doingJumpTransition = False
|
|
self.localToonJumpAnimIval = self.createJumpingTransitionIval(vineIndex)
|
|
if self.localToonJumpAnimIval:
|
|
self.doingJumpTransition = True
|
|
|
|
def createJumpingTransitionIval(self, vineIndex):
|
|
retval = None
|
|
curInfo = self.vines[vineIndex].getAttachedToonInfo(base.localAvatar.doId)
|
|
if curInfo:
|
|
swingSeq = curInfo[6]
|
|
if swingSeq:
|
|
curFrame = -1
|
|
for i in xrange(len(swingSeq)):
|
|
self.notify.debug('testing actor interval i=%d' % i)
|
|
actorIval = swingSeq[i]
|
|
if not actorIval.isStopped():
|
|
testFrame = actorIval.getCurrentFrame()
|
|
self.notify.debug('actor ival is not stopped, testFrame=%f' % testFrame)
|
|
if testFrame:
|
|
curFrame = testFrame
|
|
break
|
|
|
|
if curFrame > -1:
|
|
duration = 0.25
|
|
if curFrame > self.ToonMaxRightFrame:
|
|
desiredFps = abs(self.JumpingFrame - curFrame) / duration
|
|
playRate = desiredFps / 24.0
|
|
retval = ActorInterval(base.localAvatar, 'swing', startFrame=curFrame, endFrame=self.JumpingFrame, playRate=playRate)
|
|
else:
|
|
numFrames = curFrame + 1
|
|
numFrames += SwingVine.SwingVine.MaxNumberOfFramesInSwingAnim - self.JumpingFrame + 1
|
|
desiredFps = numFrames / duration
|
|
playRate = desiredFps / 24.0
|
|
toonJump1 = ActorInterval(base.localAvatar, 'swing', startFrame=curFrame, endFrame=0, playRate=playRate)
|
|
toonJump2 = ActorInterval(base.localAvatar, 'swing', startFrame=SwingVine.SwingVine.MaxNumberOfFramesInSwingAnim - 1, endFrame=self.JumpingFrame, playRate=playRate)
|
|
retval = Sequence(toonJump1, toonJump2)
|
|
return retval
|
|
|
|
def detachLocalToonFromVine(self, vineIndex, facingRight):
|
|
vine = self.vines[vineIndex]
|
|
self.lastJumpVine = vineIndex
|
|
self.lastJumpTime = self.getCurrentGameTime()
|
|
self.curFrame = base.localAvatar.getCurrentFrame()
|
|
curInfo = vine.getAttachedToonInfo(base.localAvatar.doId)
|
|
if curInfo:
|
|
self.lastJumpPos = curInfo[1]
|
|
self.lastJumpT = curInfo[0]
|
|
else:
|
|
self.lastJumpPos = None
|
|
self.lastJumpT = 0
|
|
self.notify.warning('vine %d failed get tooninfo %d' % (vineIndex, base.localAvatar.doId))
|
|
self.setupJumpingTransitionIval(vineIndex)
|
|
self.vines[vineIndex].detachToon(base.localAvatar.doId)
|
|
return
|
|
|
|
def treasureEnter(self, entry):
|
|
self.notify.debug('---- treasure Enter ---- ')
|
|
self.notify.debug('%s' % entry)
|
|
name = entry.getIntoNodePath().getName()
|
|
parts = name.split('-')
|
|
if len(parts) < 3:
|
|
self.notify.debug('collided with %s, but returning' % name)
|
|
return
|
|
if not int(parts[1]) == self.doId:
|
|
self.notify.debug("collided with %s, but doId doesn't match" % name)
|
|
return
|
|
treasureNum = int(parts[2])
|
|
self.__treasureGrabbed(treasureNum)
|
|
|
|
def swingVineEnter(self, entry):
|
|
self.notify.debug('%s' % entry)
|
|
self.notify.debug('---- swingVine Enter ---- ')
|
|
name = entry.getIntoNodePath().getName()
|
|
parts = name.split('-')
|
|
if len(parts) < 3:
|
|
self.notify.debug('collided with %s, but returning' % name)
|
|
return
|
|
vineIndex = int(parts[1])
|
|
if vineIndex < 0 or vineIndex >= len(self.vines):
|
|
self.notify.warning('invalid vine index %d' % vineIndex)
|
|
return
|
|
if vineIndex == self.lastJumpVine:
|
|
if self.lastJumpPos:
|
|
diff = self.lastJumpPos - entry.getSurfacePoint(render)
|
|
if diff.length() < self.LocalPhysicsRadius:
|
|
return
|
|
if self.getCurrentGameTime() - self.lastJumpTime < VineGameGlobals.JumpTimeBuffer:
|
|
return
|
|
fallingInfo = self.toonInfo[self.localAvId][8]
|
|
if fallingInfo == self.FallingSpider or fallingInfo == self.FallingBat:
|
|
return
|
|
if abs(self.lastJumpVine - vineIndex) > 1:
|
|
return
|
|
vine = self.vines[vineIndex]
|
|
vineT = vine.calcTFromTubeHit(entry)
|
|
self.attachLocalToonToVine(vineIndex, vineT, False, playSfx=True)
|
|
self.setupAttachingToVineCamIval(vineIndex, self.lastJumpFacingRight)
|
|
|
|
def makeOtherToonJump(self, avId, posX, posZ, velX, velZ):
|
|
if avId not in self.otherToonPhysics:
|
|
an = ActorNode('other-physics%s' % avId)
|
|
anp = render.attachNewNode(an)
|
|
base.physicsMgr.attachPhysicalNode(an)
|
|
self.otherToonPhysics[avId] = (an, anp)
|
|
an, anp = self.otherToonPhysics[avId]
|
|
anp.setPos(posX, 0, posZ)
|
|
av = base.cr.doId2do.get(avId)
|
|
if av:
|
|
av.reparentTo(anp)
|
|
av.setPos(-self.toonOffsets[self.localAvId])
|
|
av.pose('swing', self.JumpingFrame)
|
|
self.notify.debug('pose set to swing jumping frame.')
|
|
if velX >= 0:
|
|
anp.setH(-90)
|
|
else:
|
|
anp.setH(90)
|
|
physObject = an.getPhysicsObject()
|
|
physObject.setVelocity(velX, 0, velZ)
|
|
|
|
def makeOtherToonFallFromMidair(self, avId, posX, posZ, velX, velZ):
|
|
if avId not in self.otherToonPhysics:
|
|
an = ActorNode('other-physics%s' % avId)
|
|
anp = render.attachNewNode(an)
|
|
base.physicsMgr.attachPhysicalNode(an)
|
|
self.otherToonPhysics[avId] = (an, anp)
|
|
an, anp = self.otherToonPhysics[avId]
|
|
anp.setPos(posX, 0, posZ)
|
|
av = base.cr.doId2do.get(avId)
|
|
if av:
|
|
av.reparentTo(anp)
|
|
av.setPos(-self.toonOffsets[self.localAvId])
|
|
if velX >= 0:
|
|
anp.setH(-90)
|
|
else:
|
|
anp.setH(90)
|
|
physObject = an.getPhysicsObject()
|
|
physObject.setVelocity(velX, 0, velZ)
|
|
|
|
def makeLocalToonJump(self, vineIndex, t, pos, normal):
|
|
self.jumpSound.play()
|
|
self.clearChangeFacingInterval()
|
|
self.clearAttachingToVineCamIval()
|
|
an = ActorNode('av-physics')
|
|
anp = render.attachNewNode(an)
|
|
anp.setPos(pos)
|
|
base.localAvatar.reparentTo(anp)
|
|
base.localAvatar.setPos(-self.toonOffsets[self.localAvId])
|
|
if normal.getX() >= 0:
|
|
self.lastJumpFacingRight = True
|
|
anp.setH(-90)
|
|
else:
|
|
anp.setH(90)
|
|
self.lastJumpFacingRight = False
|
|
base.physicsMgr.attachPhysicalNode(an)
|
|
physObject = an.getPhysicsObject()
|
|
velocity = normal * self.JumpSpeed
|
|
velocity *= t
|
|
self.notify.debug('jumping from vine with velocity of %s' % velocity)
|
|
physObject.setVelocity(velocity)
|
|
self.localPhysicsNP = anp
|
|
self.setupCollisions(anp)
|
|
if self.doingJumpTransition:
|
|
self.localToonJumpAnimIval.start()
|
|
else:
|
|
base.localAvatar.pose('swing', self.JumpingFrame)
|
|
self.b_setJumpingFromVine(self.localAvId, vineIndex, self.lastJumpFacingRight, pos[0], pos[2], velocity[0], velocity[2])
|
|
|
|
def makeLocalToonFallFromVine(self, fallingInfo):
|
|
self.clearAttachingToVineCamIval()
|
|
self.clearChangeFacingInterval()
|
|
vineIndex, vineInfo = self.getVineAndVineInfo(self.localAvId)
|
|
if vineIndex == -1:
|
|
self.notify.warning('we are not attached to a vine')
|
|
return
|
|
pos = vineInfo[1]
|
|
self.detachLocalToonFromVine(vineIndex, self.lastJumpFacingRight)
|
|
self.clearChangeFacingInterval()
|
|
an = ActorNode('av-physics')
|
|
anp = render.attachNewNode(an)
|
|
anp.setPos(vineInfo[1])
|
|
base.localAvatar.reparentTo(anp)
|
|
base.localAvatar.setPos(-self.toonOffsets[self.localAvId])
|
|
if self.lastJumpFacingRight:
|
|
anp.setH(-90)
|
|
else:
|
|
anp.setH(90)
|
|
base.physicsMgr.attachPhysicalNode(an)
|
|
physObject = an.getPhysicsObject()
|
|
velocity = Vec3(0, 0, -0.1)
|
|
physObject.setVelocity(velocity)
|
|
self.localPhysicsNP = anp
|
|
self.b_setFallingFromVine(self.localAvId, vineIndex, self.lastJumpFacingRight, pos[0], pos[2], velocity[0], velocity[2], fallingInfo)
|
|
|
|
def makeLocalToonFallFromMidair(self, fallingInfo):
|
|
vineIndex, vineInfo = self.getVineAndVineInfo(self.localAvId)
|
|
if not vineIndex == -1:
|
|
self.notify.warning(' makeLocalToonFallFromMidair we are still attached to a vine')
|
|
return
|
|
if not self.localPhysicsNP:
|
|
self.notify.warning('self.localPhysicsNP is invalid')
|
|
return
|
|
pos = self.localPhysicsNP.getPos()
|
|
an = self.localPhysicsNP.node()
|
|
physObject = an.getPhysicsObject()
|
|
velocity = Vec3(0, 0, -0.1)
|
|
physObject.setVelocity(velocity)
|
|
self.b_setFallingFromMidair(self.localAvId, self.lastJumpFacingRight, pos[0], pos[2], velocity[0], velocity[2], fallingInfo)
|
|
|
|
def changeLocalToonFacing(self, vineIndex, swingVineInfo, newFacingRight):
|
|
self.lastJumpFacingRight = newFacingRight
|
|
self.attachLocalToonToVine(vineIndex, swingVineInfo[0], focusCameraImmediately=False)
|
|
self.setupChangeFacingInterval(vineIndex, newFacingRight)
|
|
|
|
def upArrowKeyHandler(self):
|
|
self.sendNewVineTUpdateAsap = True
|
|
|
|
def downArrowKeyHandler(self):
|
|
self.sendNewVineTUpdateAsap = True
|
|
|
|
def rightArrowKeyHandler(self):
|
|
curInfo = None
|
|
for vineIndex in xrange(len(self.vines)):
|
|
curInfo = self.vines[vineIndex].getAttachedToonInfo(base.localAvatar.doId)
|
|
if curInfo:
|
|
break
|
|
|
|
if not curInfo:
|
|
return
|
|
if vineIndex == len(self.vines) - 1:
|
|
return
|
|
if not self.isInPlayState():
|
|
return
|
|
doJump = True
|
|
if self.ArrowToChangeFacing:
|
|
if not self.lastJumpFacingRight:
|
|
doJump = False
|
|
self.changeLocalToonFacing(vineIndex, curInfo, True)
|
|
if doJump:
|
|
self.detachLocalToonFromVine(vineIndex, 1)
|
|
normal = curInfo[2]
|
|
self.makeLocalToonJump(vineIndex, curInfo[0], curInfo[1], normal)
|
|
return
|
|
|
|
def leftArrowKeyHandler(self):
|
|
curInfo = None
|
|
for vineIndex in xrange(len(self.vines)):
|
|
curInfo = self.vines[vineIndex].getAttachedToonInfo(base.localAvatar.doId)
|
|
if curInfo:
|
|
break
|
|
|
|
curInfo = self.vines[vineIndex].getAttachedToonInfo(base.localAvatar.doId)
|
|
if not curInfo:
|
|
return
|
|
if vineIndex == 0:
|
|
return
|
|
if vineIndex == len(self.vines) - 1:
|
|
return
|
|
if not self.isInPlayState():
|
|
return
|
|
doJump = True
|
|
if self.ArrowToChangeFacing:
|
|
if self.lastJumpFacingRight:
|
|
doJump = False
|
|
self.changeLocalToonFacing(vineIndex, curInfo, False)
|
|
if doJump:
|
|
self.detachLocalToonFromVine(vineIndex, 0)
|
|
normal = curInfo[2]
|
|
normal *= -1
|
|
self.makeLocalToonJump(vineIndex, curInfo[0], curInfo[1], normal)
|
|
return
|
|
|
|
def b_setNewVine(self, avId, vineIndex, vineT, facingRight):
|
|
self.setNewVine(avId, vineIndex, vineT, facingRight)
|
|
self.d_setNewVine(avId, vineIndex, vineT, facingRight)
|
|
|
|
def d_setNewVine(self, avId, vineIndex, vineT, facingRight):
|
|
self.notify.debug('setNewVine avId=%d vineIndex=%s' % (avId, vineIndex))
|
|
self.sendUpdate('setNewVine', [avId,
|
|
vineIndex,
|
|
vineT,
|
|
facingRight])
|
|
|
|
def setNewVine(self, avId, vineIndex, vineT, facingRight):
|
|
self.updateToonInfo(avId, vineIndex=vineIndex, vineT=vineT, facingRight=facingRight, climbDir=0, fallingInfo=self.FallingNot)
|
|
|
|
def b_setNewVineT(self, avId, vineT, climbDir):
|
|
self.setNewVineT(avId, vineT, climbDir)
|
|
self.d_setNewVineT(avId, vineT, climbDir)
|
|
|
|
def d_setNewVineT(self, avId, vineT, climbDir):
|
|
sendIt = False
|
|
curTime = self.getCurrentGameTime()
|
|
if self.sendNewVineTUpdateAsap:
|
|
sendIt = True
|
|
elif curTime - self.lastNewVineTUpdate > 0.2:
|
|
sendIt = True
|
|
if sendIt:
|
|
self.sendUpdate('setNewVineT', [avId, vineT, climbDir])
|
|
self.sendNewVineTUpdateAsap = False
|
|
self.lastNewVineTUpdate = self.getCurrentGameTime()
|
|
|
|
def setNewVineT(self, avId, vineT, climbDir):
|
|
self.updateToonInfo(avId, vineT=vineT, climbDir=climbDir)
|
|
|
|
def b_setJumpingFromVine(self, avId, vineIndex, facingRight, posX, posZ, velX, velZ):
|
|
self.setJumpingFromVine(avId, vineIndex, facingRight, posX, posZ, velX, velZ)
|
|
self.d_setJumpingFromVine(avId, vineIndex, facingRight, posX, posZ, velX, velZ)
|
|
|
|
def d_setJumpingFromVine(self, avId, vineIndex, facingRight, posX, posZ, velX, velZ):
|
|
self.sendUpdate('setJumpingFromVine', [avId,
|
|
vineIndex,
|
|
facingRight,
|
|
posX,
|
|
posZ,
|
|
velX,
|
|
velZ])
|
|
|
|
def setJumpingFromVine(self, avId, vineIndex, facingRight, posX, posZ, velX, velZ):
|
|
self.updateToonInfo(avId, vineIndex=-1, facingRight=facingRight, posX=posX, posZ=posZ, velX=velX, velZ=velZ)
|
|
|
|
def b_setFallingFromVine(self, avId, vineIndex, facingRight, posX, posZ, velX, velZ, fallingInfo):
|
|
self.setFallingFromVine(avId, vineIndex, facingRight, posX, posZ, velX, velZ, fallingInfo)
|
|
self.d_setFallingFromVine(avId, vineIndex, facingRight, posX, posZ, velX, velZ, fallingInfo)
|
|
|
|
def d_setFallingFromVine(self, avId, vineIndex, facingRight, posX, posZ, velX, velZ, fallingInfo):
|
|
self.sendUpdate('setFallingFromVine', [avId,
|
|
vineIndex,
|
|
facingRight,
|
|
posX,
|
|
posZ,
|
|
velX,
|
|
velZ,
|
|
fallingInfo])
|
|
|
|
def setFallingFromVine(self, avId, vineIndex, facingRight, posX, posZ, velX, velZ, fallingInfo):
|
|
self.updateToonInfo(avId, vineIndex=-1, facingRight=facingRight, posX=posX, posZ=posZ, velX=velX, velZ=velZ, fallingInfo=fallingInfo)
|
|
|
|
def b_setFallingFromMidair(self, avId, facingRight, posX, posZ, velX, velZ, fallingInfo):
|
|
self.setFallingFromMidair(avId, facingRight, posX, posZ, velX, velZ, fallingInfo)
|
|
self.d_setFallingFromMidair(avId, facingRight, posX, posZ, velX, velZ, fallingInfo)
|
|
|
|
def d_setFallingFromMidair(self, avId, facingRight, posX, posZ, velX, velZ, fallingInfo):
|
|
self.sendUpdate('setFallingFromMidair', [avId,
|
|
facingRight,
|
|
posX,
|
|
posZ,
|
|
velX,
|
|
velZ,
|
|
fallingInfo])
|
|
|
|
def setFallingFromMidair(self, avId, facingRight, posX, posZ, velX, velZ, fallingInfo):
|
|
self.updateToonInfo(avId=avId, facingRight=facingRight, posX=posX, posZ=posZ, velX=velX, velZ=velZ, fallingInfo=fallingInfo)
|
|
|
|
def d_setFallingPos(self, avId, posX, posZ):
|
|
self.sendUpdate('setFallingPos', [avId, posX, posZ])
|
|
|
|
def setFallingPos(self, avId, posX, posZ):
|
|
self.updateToonInfo(avId, posX=posX, posZ=posZ)
|
|
|
|
def __treasureGrabbed(self, treasureNum):
|
|
self.treasures[treasureNum].showGrab()
|
|
self.grabSound.play()
|
|
self.sendUpdate('claimTreasure', [treasureNum])
|
|
|
|
def setTreasureGrabbed(self, avId, treasureNum):
|
|
if not self.hasLocalToon:
|
|
return
|
|
self.notify.debug('treasure %s grabbed by %s' % (treasureNum, avId))
|
|
if avId != self.localAvId:
|
|
self.treasures[treasureNum].showGrab()
|
|
i = self.avIdList.index(avId)
|
|
self.scores[i] += 1
|
|
self.scorePanels[i].setScore(self.scores[i])
|
|
|
|
def setScore(self, avId, score):
|
|
if not self.hasLocalToon:
|
|
return
|
|
i = self.avIdList.index(avId)
|
|
if hasattr(self, 'scorePanels'):
|
|
self.scores[i] += score
|
|
self.scorePanels[i].setScore(score)
|
|
|
|
def timerExpired(self):
|
|
self.notify.debug('game timer expired')
|
|
if not VineGameGlobals.EndlessGame:
|
|
if hasattr(self, 'gameFSM'):
|
|
self.gameFSM.request('showScores')
|
|
|
|
def allAtEndVine(self):
|
|
if not self.hasLocalToon:
|
|
return
|
|
self.notify.debug('all at end vine')
|
|
if not VineGameGlobals.EndlessGame:
|
|
self.gameFSM.request('showScores')
|
|
|
|
def clearChangeFacingInterval(self):
|
|
if self.changeFacingInterval:
|
|
self.changeFacingInterval.pause()
|
|
del self.changeFacingInterval
|
|
self.changeFacingInterval = None
|
|
return
|
|
|
|
def setupChangeFacingInterval(self, vineIndex, newFacingRight):
|
|
self.clearChangeFacingInterval()
|
|
self.changeFacingInterval = Sequence()
|
|
if not (vineIndex == 0 or vineIndex == VineGameGlobals.NumVines - 1):
|
|
destPos = self.getFocusCameraPos(vineIndex, newFacingRight)
|
|
self.changeFacingInterval.append(LerpPosInterval(base.camera, 0.5, destPos))
|
|
self.changeFacingInterval.append(Func(self.clearChangeFacingInterval))
|
|
self.changeFacingInterval.start()
|
|
|
|
def clearAttachingToVineCamIval(self):
|
|
if self.attachingToVineCamIval:
|
|
self.attachingToVineCamIval.pause()
|
|
del self.attachingToVineCamIval
|
|
self.attachingToVineCamIval = None
|
|
return
|
|
|
|
def setupAttachingToVineCamIval(self, vineIndex, facingRight):
|
|
self.clearAttachingToVineCamIval()
|
|
self.attachingToVineCamIval = Sequence()
|
|
destPos = self.getFocusCameraPos(vineIndex, facingRight)
|
|
self.attachingToVineCamIval.append(LerpPosInterval(base.camera, 0.5, destPos))
|
|
self.attachingToVineCamIval.append(Func(self.clearAttachingToVineCamIval))
|
|
self.attachingToVineCamIval.start()
|
|
|
|
def createRadar(self):
|
|
self.cCamera = render.attachNewNode('cCamera')
|
|
self.cCamNode = Camera('cCam')
|
|
self.cCamNode.setCameraMask(VineGameGlobals.RadarCameraBitmask)
|
|
self.cLens = PerspectiveLens()
|
|
xFov = 40
|
|
yFov = 2.5
|
|
self.cLens.setFov(xFov, yFov)
|
|
self.cLens.setNear(0.1)
|
|
self.cLens.setFar(1300.0)
|
|
self.cCamNode.setLens(self.cLens)
|
|
self.cCamNode.setScene(render)
|
|
self.cCam = self.cCamera.attachNewNode(self.cCamNode)
|
|
self.cCam.setPos(300, -850, 16.3)
|
|
endY = yFov / xFov
|
|
self.endZRadar = 0.09375
|
|
self.cDr = base.win.makeDisplayRegion(0, 1, 0, self.endZRadar)
|
|
self.cDr.setSort(1)
|
|
self.cDr.setClearDepthActive(1)
|
|
self.cDr.setClearColorActive(1)
|
|
self.cDr.setClearColor(Vec4(0.85, 0.95, 0.95, 1))
|
|
self.cDr.setCamera(self.cCam)
|
|
self.radarSeparator = DirectFrame(relief=None, image=DGG.getDefaultDialogGeom(), image_color=(0.2, 0.0, 0.8, 1), image_scale=(2.65, 1.0, 0.01), pos=(0, 0, -0.8125))
|
|
self.oldBaseCameraMask = base.camNode.getCameraMask()
|
|
base.camNode.setCameraMask(BitMask32.bit(0))
|
|
return
|
|
|
|
def destroyRadar(self):
|
|
base.win.removeDisplayRegion(self.cDr)
|
|
self.cCamera.removeNode()
|
|
del self.cCamera
|
|
del self.cCamNode
|
|
del self.cLens
|
|
del self.cCam
|
|
del self.cDr
|
|
self.radarSeparator.destroy()
|
|
del self.radarSeparator
|
|
base.camNode.setCameraMask(self.oldBaseCameraMask)
|
|
|
|
def updateRadar(self):
|
|
for avId in self.headFrames:
|
|
av = base.cr.doId2do.get(avId)
|
|
headFrameShown = False
|
|
if av:
|
|
avPos = av.getPos(render)
|
|
newPoint = self.mapRadarToAspect2d(render, avPos)
|
|
if newPoint:
|
|
headFrameShown = True
|
|
self.headFrames[avId].setPos(newPoint[0], newPoint[1], newPoint[2])
|
|
if headFrameShown:
|
|
self.headFrames[avId].show()
|
|
else:
|
|
self.headFrames[avId].hide()
|
|
|
|
def mapRadarToAspect2d(self, node, point):
|
|
if point[0] > 26:
|
|
pass
|
|
p3 = self.cCam.getRelativePoint(node, point)
|
|
p2 = Point2()
|
|
if not self.cLens.project(p3, p2):
|
|
return None
|
|
r2d = Point3(p2[0], 0, p2[1])
|
|
a2d = aspect2d.getRelativePoint(render2d, r2d)
|
|
zAspect2DRadar = self.endZRadar * 2.0 - 1
|
|
oldZ = a2d.getZ()
|
|
newZ = (oldZ + 1) / 2.0 * (zAspect2DRadar + 1)
|
|
newZ -= 1
|
|
a2d.setZ(newZ)
|
|
return a2d
|
|
|
|
def localToonHitSpider(self, colEntry):
|
|
self.notify.debug('toonHitSpider')
|
|
if self.toonInfo[self.localAvId][0] == -1:
|
|
fallingInfo = self.toonInfo[self.localAvId][8]
|
|
if not (fallingInfo == self.FallingBat or fallingInfo == self.FallingSpider):
|
|
self.spiderHitSound.play()
|
|
self.makeLocalToonFallFromMidair(self.FallingSpider)
|
|
else:
|
|
self.spiderHitSound.play()
|
|
self.makeLocalToonFallFromVine(self.FallingSpider)
|
|
|
|
def localToonHitBat(self, colEntry):
|
|
self.notify.debug('toonHitBat')
|
|
if self.toonInfo[self.localAvId][0] == VineGameGlobals.NumVines - 1:
|
|
return
|
|
if self.toonInfo[self.localAvId][0] == -1:
|
|
self.batHitMidairSound.play()
|
|
fallingInfo = self.toonInfo[self.localAvId][8]
|
|
if not (fallingInfo == self.FallingBat or fallingInfo == self.FallingSpider):
|
|
self.makeLocalToonFallFromMidair(self.FallingBat)
|
|
else:
|
|
self.batHitVineSound.play()
|
|
self.makeLocalToonFallFromVine(self.FallingBat)
|
|
|
|
def toonHitSomething(self, colEntry):
|
|
if not self.isInPlayState():
|
|
return
|
|
intoName = colEntry.getIntoNodePath().getName()
|
|
if 'spider' in intoName:
|
|
self.localToonHitSpider(colEntry)
|
|
elif 'bat' in intoName:
|
|
self.localToonHitBat(colEntry)
|
|
|
|
def setVineSections(self, vineSections):
|
|
self.vineSections = vineSections
|
|
|
|
def setupVineCourse(self):
|
|
vineIndex = 0
|
|
for section in self.vineSections:
|
|
for vineInfo in VineGameGlobals.CourseSections[section]:
|
|
length, baseAngle, vinePeriod, spiderPeriod = vineInfo
|
|
posX = vineIndex * VineGameGlobals.VineXIncrement
|
|
newVine = SwingVine.SwingVine(vineIndex, posX, 0, VineGameGlobals.VineHeight, length=length, baseAngle=baseAngle, period=vinePeriod, spiderPeriod=spiderPeriod)
|
|
self.vines.append(newVine)
|
|
vineIndex += 1
|
|
|
|
def loadBats(self):
|
|
self.bats = []
|
|
szId = self.getSafezoneId()
|
|
self.batInfo = VineGameGlobals.BatInfo[szId]
|
|
batIndex = 0
|
|
for batTuple in self.batInfo:
|
|
newBat = VineBat.VineBat(batIndex, self.batInfo[batIndex][0])
|
|
xPos = VineGameGlobals.VineXIncrement * VineGameGlobals.NumVines + 100
|
|
newBat.setX(xPos)
|
|
self.bats.append(newBat)
|
|
batIndex += 1
|
|
|
|
def createBatIvals(self):
|
|
self.batIvals = []
|
|
for batIndex in xrange(len(self.bats)):
|
|
newBatIval = self.createBatIval(batIndex)
|
|
self.batIvals.append(newBatIval)
|
|
|
|
def startBatIvals(self):
|
|
for batIval in self.batIvals:
|
|
batIval.start()
|
|
|
|
def destroyBatIvals(self):
|
|
for batIval in self.batIvals:
|
|
batIval.finish()
|
|
|
|
self.batIvals = []
|
|
|
|
def createBatIval(self, batIndex):
|
|
timeToTraverseField = self.batInfo[batIndex][0]
|
|
initialDelay = self.batInfo[batIndex][1]
|
|
startMultiplier = 1
|
|
if len(self.batInfo[batIndex]) >= 3:
|
|
startMultiplier = 0.25
|
|
batIval = Sequence()
|
|
batIval.append(Wait(initialDelay))
|
|
batIval.append(Func(self.bats[batIndex].startFlying))
|
|
startX = VineGameGlobals.VineXIncrement * VineGameGlobals.NumVines
|
|
endX = -VineGameGlobals.VineXIncrement
|
|
firstInterval = True
|
|
while batIval.getDuration() < VineGameGlobals.GameDuration:
|
|
batHeight = self.randomNumGen.randrange(VineGameGlobals.BatMinHeight, VineGameGlobals.BatMaxHeight)
|
|
batIval.append(Func(self.bats[batIndex].startLap))
|
|
if firstInterval:
|
|
newIval = LerpPosInterval(self.bats[batIndex], duration=timeToTraverseField * startMultiplier, pos=Point3(endX, 0, batHeight), startPos=Point3(startX * startMultiplier, 0, batHeight))
|
|
else:
|
|
newIval = LerpPosInterval(self.bats[batIndex], duration=timeToTraverseField, pos=Point3(endX, 0, batHeight), startPos=Point3(startX, 0, batHeight))
|
|
batIval.append(newIval)
|
|
firstInterval = False
|
|
|
|
batIval.append(Func(self.bats[batIndex].stopFlying))
|
|
return batIval
|
|
|
|
def isInPlayState(self):
|
|
if not self.gameFSM.getCurrentState():
|
|
return False
|
|
if not self.gameFSM.getCurrentState().getName() == 'play':
|
|
return False
|
|
return True
|
|
|
|
def getIntroTrack(self):
|
|
retval = Sequence()
|
|
toonTakeoffs = Parallel()
|
|
didCameraMove = False
|
|
for index in xrange(len(self.avIdList)):
|
|
avId = self.avIdList[index]
|
|
if avId != self.localAvId:
|
|
continue
|
|
oneSeq = Sequence()
|
|
oneSeqAndHowl = Parallel()
|
|
av = base.cr.doId2do.get(avId)
|
|
if av:
|
|
toonOffset = self.calcToonOffset(av)
|
|
platformPos = self.startPlatform.getPos()
|
|
endPos = self.vines[0].getPos()
|
|
endPos.setZ(endPos.getZ() - toonOffset.getZ() - VineGameGlobals.VineStartingT * self.vines[0].cableLength)
|
|
xPos = platformPos[0] - 0.5
|
|
takeOffPos = Point3(xPos, platformPos[1], platformPos[2])
|
|
leftPos = Point3(xPos - 27, platformPos[1], platformPos[2])
|
|
self.notify.debug('leftPos = %s platformPos=%s' % (leftPos, platformPos))
|
|
startRunningPos = Point3(takeOffPos)
|
|
startRunningPos.setX(startRunningPos.getX() - 7)
|
|
oneSeq.append(Func(av.dropShadow.show))
|
|
oneSeq.append(Func(av.setH, -90))
|
|
oneSeq.append(Func(av.setPos, takeOffPos[0], takeOffPos[1], takeOffPos[2]))
|
|
exclamationSfx = av.getDialogueSfx('exclamation', 0)
|
|
oneSeq.append(Parallel(ActorInterval(av, 'confused', duration=3)))
|
|
questionSfx = av.getDialogueSfx('question', 0)
|
|
oneSeq.append(Parallel(ActorInterval(av, 'think', duration=3.0), SoundInterval(questionSfx, duration=3)))
|
|
oneSeq.append(Func(av.setH, 90))
|
|
oneSeq.append(Func(av.setPlayRate, 1, 'walk'))
|
|
oneSeq.append(Func(av.loop, 'walk'))
|
|
oneSeq.append(Parallel(LerpPosInterval(av, pos=leftPos, duration=5.25), SoundInterval(av.soundWalk, loop=1, duration=5.25)))
|
|
oneSeq.append(Func(av.setH, -90))
|
|
oneSeq.append(Func(av.loop, 'run'))
|
|
oneSeq.append(Parallel(LerpPosInterval(av, pos=takeOffPos, duration=2.5), SoundInterval(av.soundRun, loop=1, duration=2.5)))
|
|
oneSeq.append(Func(av.dropShadow.hide))
|
|
howlTime = oneSeq.getDuration()
|
|
oneSeq.append(Parallel(LerpPosInterval(av, pos=endPos, duration=0.5), Func(av.pose, 'swing', self.JumpingFrame)))
|
|
attachingToVineSeq = Sequence(ActorInterval(av, 'swing', startFrame=self.JumpingFrame, endFrame=143, playRate=2.0), ActorInterval(av, 'swing', startFrame=0, endFrame=86, playRate=2.0))
|
|
attachingToVine = Parallel(attachingToVineSeq, SoundInterval(self.catchSound))
|
|
if didCameraMove:
|
|
oneSeq.append(attachingToVine)
|
|
else:
|
|
attachAndMoveCam = Parallel(attachingToVine, LerpPosInterval(base.camera, pos=self.getFocusCameraPos(0, True), duration=2))
|
|
oneSeq.append(attachAndMoveCam)
|
|
oneSeq.append(Func(av.setPos, 0, 0, 0))
|
|
oneSeq.append(Func(av.setH, 0))
|
|
oneSeq.append(Func(self.vines[0].attachToon, avId, VineGameGlobals.VineStartingT, self.lastJumpFacingRight, setupAnim=False))
|
|
oneSeq.append(Func(self.vines[0].updateAttachedToons))
|
|
howlSfx = av.getDialogueSfx('special', 0)
|
|
howlSeq = Sequence(Wait(howlTime), SoundInterval(howlSfx))
|
|
exclamationSeq = Sequence(Wait(0.5), SoundInterval(exclamationSfx))
|
|
oneSeqAndHowl = Parallel(oneSeq, howlSeq, exclamationSeq)
|
|
toonTakeoffs.append(oneSeqAndHowl)
|
|
|
|
retval.append(toonTakeoffs)
|
|
return retval
|
|
|
|
def doEndingTrackTask(self, avId):
|
|
taskName = 'VineGameEnding-%s' % avId
|
|
if avId not in self.endingTracks:
|
|
taskMgr.doMethodLater(0.5, self.setupEndingTrack, taskName, extraArgs=(avId,))
|
|
self.endingTrackTaskNames.append(taskName)
|
|
|
|
def debugCameraPos(self):
|
|
self.notify.debug('cameraPos = %s' % base.camera.getPos())
|
|
|
|
def setupEndingTrack(self, avId):
|
|
if avId in self.endingTracks:
|
|
self.notify.warning('setupEndingTrack duplicate call avId=%d' % avId)
|
|
return
|
|
if len(self.vines) == 0:
|
|
return
|
|
endVine = VineGameGlobals.NumVines - 1
|
|
platformPos = self.endPlatform.getPos()
|
|
avIndex = self.avIdList.index(avId)
|
|
landingPos = Point3(platformPos)
|
|
landingPos.setX(landingPos.getX() + avIndex * 2)
|
|
endingTrack = Sequence()
|
|
av = base.cr.doId2do.get(avId)
|
|
avPos = av.getPos(render)
|
|
cameraPos = base.camera.getPos()
|
|
self.notify.debug('avPos=%s cameraPos=%s' % (avPos, base.camera.getPos()))
|
|
if av:
|
|
midX = landingPos[0]
|
|
midZ = platformPos[2] + 6
|
|
jumpingTransition = self.createJumpingTransitionIval(endVine)
|
|
endingTrack.append(Func(self.vines[endVine].detachToon, avId))
|
|
endingTrack.append(Func(av.wrtReparentTo, render))
|
|
endingTrack.append(Func(self.debugCameraPos))
|
|
endingTrack.append(Func(av.loop, 'jump-idle'))
|
|
landingIval = Parallel(ProjectileInterval(av, startPos=av.getPos(render), endZ=landingPos[2], wayPoint=Point3(midX, 0, midZ), timeToWayPoint=1))
|
|
endingTrack.append(landingIval)
|
|
endingTrack.append(Func(av.dropShadow.show))
|
|
endingTrack.append(Func(av.play, 'jump-land'))
|
|
endingTrack.append(Func(self.winSound.play))
|
|
endingTrack.append(Func(av.loop, 'victory'))
|
|
self.endingTracks[avId] = endingTrack
|
|
endingTrack.start()
|
|
return Task.done
|
|
|
|
def cleanupEndingTracks(self):
|
|
for taskName in self.endingTrackTaskNames:
|
|
taskMgr.remove(taskName)
|
|
|
|
for endingTrack in self.endingTracks.values():
|
|
endingTrack.finish
|
|
del endingTrack
|
|
|
|
self.endingTracks = {}
|