toontown-just-works/toontown/minigame/DistributedCogThiefGame.py
2024-07-07 18:08:39 -05:00

907 lines
38 KiB
Python

from pandac.PandaModules import Point3, CollisionSphere, CollisionNode, CollisionHandlerEvent, NodePath, TextNode
from direct.distributed.ClockDelta import globalClockDelta
from direct.interval.IntervalGlobal import Wait, LerpFunctionInterval, LerpHprInterval, Sequence, Parallel, Func, SoundInterval, ActorInterval, ProjectileInterval, Track, LerpScaleInterval, WaitInterval, LerpPosHprInterval
from direct.gui.DirectGui import DirectLabel
from direct.fsm import ClassicFSM
from direct.fsm import State
from direct.showbase import RandomNumGen
from direct.task import Task
from toontown.toonbase import TTLocalizer
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import ToontownTimer
from toontown.minigame import CogThiefGameToonSD
from toontown.minigame.OrthoDrive import OrthoDrive
from toontown.minigame.OrthoWalk import OrthoWalk
from toontown.minigame import CogThiefGameGlobals
from toontown.minigame import CogThief
from toontown.minigame.DistributedMinigame import DistributedMinigame
from toontown.minigame import Trajectory
from toontown.minigame import MinigameGlobals
from toontown.minigame import CogThiefWalk
CTGG = CogThiefGameGlobals
class DistributedCogThiefGame(DistributedMinigame):
notify = directNotify.newCategory('DistributedCogThiefGame')
ToonSpeed = CTGG.ToonSpeed
StageHalfWidth = 200.0
StageHalfHeight = 100.0
BarrelScale = 0.25
TOON_Z = 0
UPDATE_SUITS_TASK = 'CogThiefGameUpdateSuitsTask'
REWARD_COUNTDOWN_TASK = 'cogThiefGameRewardCountdown'
ControlKeyLimitTime = 1.0
def __init__(self, cr):
DistributedMinigame.__init__(self, cr)
self.gameFSM = ClassicFSM.ClassicFSM('DistributedCogThiefGame', [State.State('off', self.enterOff, self.exitOff, ['play']), State.State('play', self.enterPlay, self.exitPlay, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.addChildGameFSM(self.gameFSM)
self.cameraTopView = (0, 0, 55, 0, -90.0, 0)
self.barrels = []
self.cogInfo = {}
self.lastTimeControlPressed = 0
self.stolenBarrels = []
self.useOrthoWalk = base.config.GetBool('cog-thief-ortho', 1)
self.resultIval = None
self.gameIsEnding = False
self.__textGen = TextNode('cogThiefGame')
self.__textGen.setFont(ToontownGlobals.getSignFont())
self.__textGen.setAlign(TextNode.ACenter)
return
def getTitle(self):
return TTLocalizer.CogThiefGameTitle
def getInstructions(self):
return TTLocalizer.CogThiefGameInstructions
def getMaxDuration(self):
return 0
def load(self):
self.notify.debug('load')
DistributedMinigame.load(self)
self.music = base.loadMusic('phase_4/audio/bgm/MG_CogThief.ogg')
self.initCogInfo()
for barrelIndex in xrange(CTGG.NumBarrels):
barrel = loader.loadModel('phase_4/models/minigames/cogthief_game_gagTank')
barrel.setPos(CTGG.BarrelStartingPositions[barrelIndex])
barrel.setScale(self.BarrelScale)
barrel.reparentTo(render)
barrel.setTag('barrelIndex', str(barrelIndex))
collSphere = CollisionSphere(0, 0, 0, 4)
collSphere.setTangible(0)
name = 'BarrelSphere-%d' % barrelIndex
collSphereName = self.uniqueName(name)
collNode = CollisionNode(collSphereName)
collNode.setFromCollideMask(CTGG.BarrelBitmask)
collNode.addSolid(collSphere)
colNp = barrel.attachNewNode(collNode)
handler = CollisionHandlerEvent()
handler.setInPattern('barrelHit-%fn')
base.cTrav.addCollider(colNp, handler)
self.accept('barrelHit-' + collSphereName, self.handleEnterBarrel)
nodeToHide = '**/gagMoneyTen'
if barrelIndex % 2:
nodeToHide = '**/gagMoneyFive'
iconToHide = barrel.find(nodeToHide)
if not iconToHide.isEmpty():
iconToHide.hide()
self.barrels.append(barrel)
self.gameBoard = loader.loadModel('phase_4/models/minigames/cogthief_game')
self.gameBoard.find('**/floor_TT').hide()
self.gameBoard.find('**/floor_DD').hide()
self.gameBoard.find('**/floor_DG').hide()
self.gameBoard.find('**/floor_MM').hide()
self.gameBoard.find('**/floor_BR').hide()
self.gameBoard.find('**/floor_DL').hide()
zone = self.getSafezoneId()
if zone == ToontownGlobals.ToontownCentral:
self.gameBoard.find('**/floor_TT').show()
elif zone == ToontownGlobals.DonaldsDock:
self.gameBoard.find('**/floor_DD').show()
elif zone == ToontownGlobals.DaisyGardens:
self.gameBoard.find('**/floor_DG').show()
elif zone == ToontownGlobals.MinniesMelodyland:
self.gameBoard.find('**/floor_MM').show()
elif zone == ToontownGlobals.TheBrrrgh:
self.gameBoard.find('**/floor_BR').show()
elif zone == ToontownGlobals.DonaldsDreamland:
self.gameBoard.find('**/floor_DL').show()
else:
self.gameBoard.find('**/floor_TT').show()
self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0)
self.gameBoard.setScale(1.0)
self.toonSDs = {}
avId = self.localAvId
toonSD = CogThiefGameToonSD.CogThiefGameToonSD(avId, self)
self.toonSDs[avId] = toonSD
toonSD.load()
self.loadCogs()
self.toonHitTracks = {}
self.toonPieTracks = {}
self.sndOof = base.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg')
self.sndRewardTick = base.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg')
self.sndPerfect = base.loadSfx('phase_4/audio/sfx/ring_perfect.ogg')
self.timer = ToontownTimer.ToontownTimer()
self.timer.posInTopRightCorner()
self.timer.hide()
purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui')
self.jarImage = purchaseModels.find('**/Jar')
self.jarImage.reparentTo(hidden)
self.rewardPanel = DirectLabel(parent=hidden, relief=None, pos=(-0.173, 0.0, -0.55), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage)
self.rewardPanelTitle = DirectLabel(parent=self.rewardPanel, relief=None, pos=(0, 0, 0.06), scale=0.08, text=TTLocalizer.CannonGameReward, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1))
return
def unload(self):
self.notify.debug('unload')
DistributedMinigame.unload(self)
del self.music
self.removeChildGameFSM(self.gameFSM)
del self.gameFSM
self.gameBoard.removeNode()
del self.gameBoard
for barrel in self.barrels:
barrel.removeNode()
del self.barrels
for avId in self.toonSDs.keys():
toonSD = self.toonSDs[avId]
toonSD.unload()
del self.toonSDs
self.timer.destroy()
del self.timer
self.rewardPanel.destroy()
del self.rewardPanel
self.jarImage.removeNode()
del self.jarImage
del self.sndRewardTick
def onstage(self):
self.notify.debug('onstage')
DistributedMinigame.onstage(self)
self.gameBoard.reparentTo(render)
lt = base.localAvatar
lt.reparentTo(render)
self.__placeToon(self.localAvId)
lt.setSpeed(0, 0)
self.moveCameraToTop()
toonSD = self.toonSDs[self.localAvId]
toonSD.enter()
toonSD.fsm.request('normal')
self.stopGameWalk()
for cogIndex in xrange(self.getNumCogs()):
suit = self.cogInfo[cogIndex]['suit'].suit
pos = self.cogInfo[cogIndex]['pos']
suit.reparentTo(self.gameBoard)
suit.setPos(pos)
suit.nametag3d.stash()
suit.nametag.destroy()
for avId in self.avIdList:
self.toonHitTracks[avId] = Wait(0.1)
self.toonRNGs = []
for i in xrange(self.numPlayers):
self.toonRNGs.append(RandomNumGen.RandomNumGen(self.randomNumGen))
self.sndTable = {'hitBySuit': [None] * self.numPlayers,
'falling': [None] * self.numPlayers}
for i in xrange(self.numPlayers):
self.sndTable['hitBySuit'][i] = base.loadSfx('phase_4/audio/sfx/MG_Tag_C.ogg')
self.sndTable['falling'][i] = base.loadSfx('phase_4/audio/sfx/MG_cannon_whizz.ogg')
base.playMusic(self.music, looping=1, volume=0.8)
self.introTrack = self.getIntroTrack()
self.introTrack.start()
return
def offstage(self):
self.notify.debug('offstage')
self.gameBoard.hide()
self.music.stop()
for barrel in self.barrels:
barrel.hide()
for avId in self.toonSDs.keys():
self.toonSDs[avId].exit()
for avId in self.avIdList:
av = self.getAvatar(avId)
if av:
av.resetLOD()
self.timer.reparentTo(hidden)
self.rewardPanel.reparentTo(hidden)
if self.introTrack.isPlaying():
self.introTrack.finish()
del self.introTrack
DistributedMinigame.offstage(self)
def handleDisabledAvatar(self, avId):
self.notify.debug('handleDisabledAvatar')
self.notify.debug('avatar ' + str(avId) + ' disabled')
self.toonSDs[avId].exit(unexpectedExit=True)
del self.toonSDs[avId]
DistributedMinigame.handleDisabledAvatar(self, avId)
def setGameReady(self):
if not self.hasLocalToon:
return
self.notify.debug('setGameReady')
if DistributedMinigame.setGameReady(self):
return
for avId in self.remoteAvIdList:
toon = self.getAvatar(avId)
if toon:
toon.reparentTo(render)
self.__placeToon(avId)
toon.useLOD(1000)
toonSD = CogThiefGameToonSD.CogThiefGameToonSD(avId, self)
self.toonSDs[avId] = toonSD
toonSD.load()
toonSD.enter()
toonSD.fsm.request('normal')
toon.startSmooth()
def setGameStart(self, timestamp):
if not self.hasLocalToon:
return
self.notify.debug('setGameStart')
DistributedMinigame.setGameStart(self, timestamp)
if not base.config.GetBool('cog-thief-endless', 0):
self.timer.show()
self.timer.countdown(CTGG.GameTime, self.__gameTimerExpired)
self.clockStopTime = None
self.rewardPanel.reparentTo(base.a2dTopRight)
self.scoreMult = MinigameGlobals.getScoreMult(self.cr.playGame.hood.id)
self.__startRewardCountdown()
if self.introTrack.isPlaying():
self.introTrack.finish()
self.gameFSM.request('play')
return
def enterOff(self):
self.notify.debug('enterOff')
def exitOff(self):
pass
def enterPlay(self):
self.notify.debug('enterPlay')
self.startGameWalk()
self.spawnUpdateSuitsTask()
self.accept('control', self.controlKeyPressed)
self.pieHandler = CollisionHandlerEvent()
self.pieHandler.setInPattern('pieHit-%fn')
def exitPlay(self):
self.ignore('control')
if self.resultIval and self.resultIval.isPlaying():
self.resultIval.finish()
self.resultIval = None
return
def enterCleanup(self):
self.__killRewardCountdown()
if hasattr(self, 'jarIval'):
self.jarIval.finish()
del self.jarIval
for key in self.toonHitTracks:
ival = self.toonHitTracks[key]
if ival.isPlaying():
ival.finish()
self.toonHitTracks = {}
for key in self.toonPieTracks:
ival = self.toonPieTracks[key]
if ival.isPlaying():
ival.finish()
self.toonPieTracks = {}
for key in self.cogInfo:
cogThief = self.cogInfo[key]['suit']
cogThief.cleanup()
self.removeUpdateSuitsTask()
self.notify.debug('enterCleanup')
def exitCleanup(self):
pass
def __placeToon(self, avId):
toon = self.getAvatar(avId)
if toon:
index = self.avIdList.index(avId)
toon.setPos(CTGG.ToonStartingPositions[index])
toon.setHpr(0, 0, 0)
def moveCameraToTop(self):
camera.reparentTo(render)
p = self.cameraTopView
camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5])
base.camLens.setMinFov(46/(4./3.))
camera.setZ(camera.getZ() + base.config.GetFloat('cog-thief-z-camera-adjust', 0.0))
def destroyGameWalk(self):
self.notify.debug('destroyOrthoWalk')
if self.useOrthoWalk:
self.gameWalk.destroy()
del self.gameWalk
else:
self.notify.debug('TODO destroyGameWalk')
def initGameWalk(self):
self.notify.debug('startOrthoWalk')
if self.useOrthoWalk:
def doCollisions(oldPos, newPos, self = self):
x = bound(newPos[0], CTGG.StageHalfWidth, -CTGG.StageHalfWidth)
y = bound(newPos[1], CTGG.StageHalfHeight, -CTGG.StageHalfHeight)
newPos.setX(x)
newPos.setY(y)
return newPos
orthoDrive = OrthoDrive(self.ToonSpeed, customCollisionCallback=doCollisions, instantTurn=True)
self.gameWalk = OrthoWalk(orthoDrive, broadcast=not self.isSinglePlayer())
else:
self.gameWalk = CogThiefWalk.CogThiefWalk('walkDone')
forwardSpeed = self.ToonSpeed / 2.0
base.mouseInterfaceNode.setForwardSpeed(forwardSpeed)
multiplier = forwardSpeed / ToontownGlobals.ToonForwardSpeed
base.mouseInterfaceNode.setRotateSpeed(ToontownGlobals.ToonRotateSpeed * 4)
def initCogInfo(self):
for cogIndex in xrange(self.getNumCogs()):
self.cogInfo[cogIndex] = {'pos': Point3(CTGG.CogStartingPositions[cogIndex]),
'goal': CTGG.NoGoal,
'goalId': CTGG.InvalidGoalId,
'suit': None}
return
def loadCogs(self):
suitTypes = ['ds',
'ac',
'bc',
'ms']
for suitIndex in xrange(self.getNumCogs()):
st = self.randomNumGen.choice(suitTypes)
suit = CogThief.CogThief(suitIndex, st, self, self.getCogSpeed())
self.cogInfo[suitIndex]['suit'] = suit
def handleEnterSphere(self, colEntry):
if self.gameIsEnding:
return
intoName = colEntry.getIntoNodePath().getName()
fromName = colEntry.getFromNodePath().getName()
debugInto = intoName.split('/')
debugFrom = fromName.split('/')
self.notify.debug('handleEnterSphere gametime=%s %s into %s' % (self.getCurrentGameTime(), debugFrom[-1], debugInto[-1]))
intoName = colEntry.getIntoNodePath().getName()
if 'CogThiefSphere' in intoName:
parts = intoName.split('-')
suitNum = int(parts[1])
self.localToonHitBySuit(suitNum)
def localToonHitBySuit(self, suitNum):
self.notify.debug('localToonHitBySuit %d' % suitNum)
timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32)
pos = self.cogInfo[suitNum]['suit'].suit.getPos()
self.sendUpdate('hitBySuit', [self.localAvId,
timestamp,
suitNum,
pos[0],
pos[1],
pos[2]])
self.showToonHitBySuit(self.localAvId, timestamp)
self.makeSuitRespondToToonHit(timestamp, suitNum)
def hitBySuit(self, avId, timestamp, suitNum, x, y, z):
if not self.hasLocalToon:
return
if self.gameFSM.getCurrentState().getName() not in ['play']:
self.notify.warning('ignoring msg: av %s hit by suit' % avId)
return
if self.gameIsEnding:
return
self.notify.debug('avatar ' + `avId` + ' hit by a suit')
if avId != self.localAvId:
self.showToonHitBySuit(avId, timestamp)
self.makeSuitRespondToToonHit(timestamp, suitNum)
def showToonHitBySuit(self, avId, timestamp):
toon = self.getAvatar(avId)
if toon == None:
return
rng = self.toonRNGs[self.avIdList.index(avId)]
curPos = toon.getPos(render)
oldTrack = self.toonHitTracks[avId]
if oldTrack.isPlaying():
oldTrack.finish()
toon.setPos(curPos)
toon.setZ(self.TOON_Z)
parentNode = render.attachNewNode('mazeFlyToonParent-' + `avId`)
parentNode.setPos(toon.getPos())
toon.reparentTo(parentNode)
toon.setPos(0, 0, 0)
startPos = parentNode.getPos()
dropShadow = toon.dropShadow.copyTo(parentNode)
dropShadow.setScale(toon.dropShadow.getScale(render))
trajectory = Trajectory.Trajectory(0, Point3(0, 0, 0), Point3(0, 0, 50), gravMult=1.0)
oldFlyDur = trajectory.calcTimeOfImpactOnPlane(0.0)
trajectory = Trajectory.Trajectory(0, Point3(0, 0, 0), Point3(0, 0, 50), gravMult=0.55)
flyDur = trajectory.calcTimeOfImpactOnPlane(0.0)
avIndex = self.avIdList.index(avId)
endPos = CTGG.ToonStartingPositions[avIndex]
def flyFunc(t, trajectory, startPos = startPos, endPos = endPos, dur = flyDur, moveNode = parentNode, flyNode = toon):
u = t / dur
moveNode.setX(startPos[0] + u * (endPos[0] - startPos[0]))
moveNode.setY(startPos[1] + u * (endPos[1] - startPos[1]))
flyNode.setPos(trajectory.getPos(t))
flyTrack = Sequence(LerpFunctionInterval(flyFunc, fromData=0.0, toData=flyDur, duration=flyDur, extraArgs=[trajectory]), name=toon.uniqueName('hitBySuit-fly'))
geomNode = toon.getGeomNode()
startHpr = geomNode.getHpr()
destHpr = Point3(startHpr)
hRot = rng.randrange(1, 8)
if rng.choice([0, 1]):
hRot = -hRot
destHpr.setX(destHpr[0] + hRot * 360)
spinHTrack = Sequence(LerpHprInterval(geomNode, flyDur, destHpr, startHpr=startHpr), Func(geomNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinH'))
parent = geomNode.getParent()
rotNode = parent.attachNewNode('rotNode')
geomNode.reparentTo(rotNode)
rotNode.setZ(toon.getHeight() / 2.0)
oldGeomNodeZ = geomNode.getZ()
geomNode.setZ(-toon.getHeight() / 2.0)
startHpr = rotNode.getHpr()
destHpr = Point3(startHpr)
pRot = rng.randrange(1, 3)
if rng.choice([0, 1]):
pRot = -pRot
destHpr.setY(destHpr[1] + pRot * 360)
spinPTrack = Sequence(LerpHprInterval(rotNode, flyDur, destHpr, startHpr=startHpr), Func(rotNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinP'))
i = self.avIdList.index(avId)
soundTrack = Sequence(Func(base.playSfx, self.sndTable['hitBySuit'][i]), Wait(flyDur * (2.0 / 3.0)), SoundInterval(self.sndTable['falling'][i], duration=flyDur * (1.0 / 3.0)), name=toon.uniqueName('hitBySuit-soundTrack'))
def preFunc(self = self, avId = avId, toon = toon, dropShadow = dropShadow):
forwardSpeed = toon.forwardSpeed
rotateSpeed = toon.rotateSpeed
if avId == self.localAvId:
self.stopGameWalk()
else:
toon.stopSmooth()
if forwardSpeed or rotateSpeed:
toon.setSpeed(forwardSpeed, rotateSpeed)
toon.dropShadow.hide()
def postFunc(self = self, avId = avId, oldGeomNodeZ = oldGeomNodeZ, dropShadow = dropShadow, parentNode = parentNode):
if avId == self.localAvId:
base.localAvatar.setPos(endPos)
if hasattr(self, 'gameWalk'):
toon = base.localAvatar
toon.setSpeed(0, 0)
self.startGameWalk()
dropShadow.removeNode()
del dropShadow
toon = self.getAvatar(avId)
if toon:
toon.dropShadow.show()
geomNode = toon.getGeomNode()
rotNode = geomNode.getParent()
baseNode = rotNode.getParent()
geomNode.reparentTo(baseNode)
rotNode.removeNode()
del rotNode
geomNode.setZ(oldGeomNodeZ)
if toon:
toon.reparentTo(render)
toon.setPos(endPos)
parentNode.removeNode()
del parentNode
if avId != self.localAvId:
if toon:
toon.startSmooth()
preFunc()
slipBack = Parallel(Sequence(ActorInterval(toon, 'slip-backward', endFrame=24), Wait(CTGG.LyingDownDuration - (flyDur - oldFlyDur)), ActorInterval(toon, 'slip-backward', startFrame=24)))
if toon.doId == self.localAvId:
slipBack.append(SoundInterval(self.sndOof))
hitTrack = Sequence(Parallel(flyTrack, spinHTrack, spinPTrack, soundTrack), slipBack, Func(postFunc), name=toon.uniqueName('hitBySuit'))
self.notify.debug('hitTrack duration = %s' % hitTrack.getDuration())
self.toonHitTracks[avId] = hitTrack
hitTrack.start(globalClockDelta.localElapsedTime(timestamp))
return
def updateSuitGoal(self, timestamp, inResponseToClientStamp, suitNum, goalType, goalId, x, y, z):
if not self.hasLocalToon:
return
self.notify.debug('updateSuitGoal gameTime=%s timeStamp=%s cog=%s goal=%s goalId=%s (%.1f, %.1f,%.1f)' % (self.getCurrentGameTime(),
timestamp,
suitNum,
CTGG.GoalStr[goalType],
goalId,
x,
y,
z))
cog = self.cogInfo[suitNum]
cog['goal'] = goalType
cog['goalId'] = goalId
newPos = Point3(x, y, z)
cog['pos'] = newPos
suit = cog['suit']
suit.updateGoal(timestamp, inResponseToClientStamp, goalType, goalId, newPos)
def spawnUpdateSuitsTask(self):
self.notify.debug('spawnUpdateSuitsTask')
for cogIndex in self.cogInfo:
suit = self.cogInfo[cogIndex]['suit']
suit.gameStart(self.gameStartTime)
taskMgr.remove(self.UPDATE_SUITS_TASK)
taskMgr.add(self.updateSuitsTask, self.UPDATE_SUITS_TASK)
def removeUpdateSuitsTask(self):
taskMgr.remove(self.UPDATE_SUITS_TASK)
def updateSuitsTask(self, task):
if self.gameIsEnding:
return task.done
for cogIndex in self.cogInfo:
suit = self.cogInfo[cogIndex]['suit']
suit.think()
return task.cont
def makeSuitRespondToToonHit(self, timestamp, suitNum):
cog = self.cogInfo[suitNum]['suit']
cog.respondToToonHit(timestamp)
def handleEnterBarrel(self, colEntry):
if self.gameIsEnding:
return
intoName = colEntry.getIntoNodePath().getName()
fromName = colEntry.getFromNodePath().getName()
debugInto = intoName.split('/')
debugFrom = fromName.split('/')
self.notify.debug('handleEnterBarrel gameTime=%s %s into %s' % (self.getCurrentGameTime(), debugFrom[-1], debugInto[-1]))
if 'CogThiefSphere' in intoName:
parts = intoName.split('-')
cogIndex = int(parts[1])
barrelName = colEntry.getFromNodePath().getName()
barrelParts = barrelName.split('-')
barrelIndex = int(barrelParts[1])
cog = self.cogInfo[cogIndex]['suit']
if cog.barrel == CTGG.NoBarrelCarried and barrelIndex not in self.stolenBarrels:
timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32)
if cog.suit:
cogPos = cog.suit.getPos()
collisionPos = colEntry.getContactPos(render)
self.sendUpdate('cogHitBarrel', [timestamp,
cogIndex,
barrelIndex,
cogPos[0],
cogPos[1],
cogPos[2]])
def makeCogCarryBarrel(self, timestamp, inResponseToClientStamp, cogIndex, barrelIndex, x, y, z):
if not self.hasLocalToon:
return
if self.gameIsEnding:
return
self.notify.debug('makeCogCarryBarrel gameTime=%s timeStamp=%s cog=%s barrel=%s (%.1f, %.1f,%.1f)' % (self.getCurrentGameTime(),
timestamp,
cogIndex,
barrelIndex,
x,
y,
z))
barrel = self.barrels[barrelIndex]
self.notify.debug('barrelPos= %s' % barrel.getPos())
cog = self.cogInfo[cogIndex]['suit']
cogPos = Point3(x, y, z)
cog.makeCogCarryBarrel(timestamp, inResponseToClientStamp, barrel, barrelIndex, cogPos)
def makeCogDropBarrel(self, timestamp, inResponseToClientStamp, cogIndex, barrelIndex, x, y, z):
if not self.hasLocalToon:
return
self.notify.debug('makeCogDropBarrel gameTime=%s timeStamp=%s cog=%s barrel=%s (%.1f, %.1f,%.1f)' % (self.getCurrentGameTime(),
timestamp,
cogIndex,
barrelIndex,
x,
y,
z))
barrel = self.barrels[barrelIndex]
self.notify.debug('barrelPos= %s' % barrel.getPos())
cog = self.cogInfo[cogIndex]['suit']
cogPos = Point3(x, y, z)
cog.makeCogDropBarrel(timestamp, inResponseToClientStamp, barrel, barrelIndex, cogPos)
def controlKeyPressed(self):
if self.isToonPlayingHitTrack(self.localAvId):
return
if self.gameIsEnding:
return
if self.getCurrentGameTime() - self.lastTimeControlPressed > self.ControlKeyLimitTime:
self.lastTimeControlPressed = self.getCurrentGameTime()
self.notify.debug('controlKeyPressed')
toonSD = self.toonSDs[self.localAvId]
curState = toonSD.fsm.getCurrentState().getName()
toon = self.getAvatar(self.localAvId)
timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32)
pos = toon.getPos()
heading = toon.getH()
self.sendUpdate('throwingPie', [self.localAvId,
timestamp,
heading,
pos[0],
pos[1],
pos[2]])
self.showToonThrowingPie(self.localAvId, timestamp, heading, pos)
def throwingPie(self, avId, timestamp, heading, x, y, z):
if not self.hasLocalToon:
return
if self.gameFSM.getCurrentState().getName() not in ['play']:
self.notify.warning('ignoring msg: av %s hit by suit' % avId)
return
self.notify.debug('avatar ' + `avId` + ' throwing pie')
if avId != self.localAvId:
pos = Point3(x, y, z)
self.showToonThrowingPie(avId, timestamp, heading, pos)
def showToonThrowingPie(self, avId, timestamp, heading, pos):
toon = self.getAvatar(avId)
if toon:
tossTrack, pieTrack, flyPie = self.getTossPieInterval(toon, pos[0], pos[1], pos[2], heading, 0, 0, 0)
def removePieFromTraverser(flyPie = flyPie):
if base.cTrav:
if flyPie:
base.cTrav.removeCollider(flyPie)
if avId == self.localAvId:
flyPie.setTag('throwerId', str(avId))
collSphere = CollisionSphere(0, 0, 0, 0.5)
collSphere.setTangible(0)
name = 'PieSphere-%d' % avId
collSphereName = self.uniqueName(name)
collNode = CollisionNode(collSphereName)
collNode.setFromCollideMask(ToontownGlobals.PieBitmask)
collNode.addSolid(collSphere)
colNp = flyPie.attachNewNode(collNode)
colNp.show()
base.cTrav.addCollider(colNp, self.pieHandler)
self.accept('pieHit-' + collSphereName, self.handlePieHitting)
def matchRunningAnim(toon = toon):
toon.playingAnim = None
toon.setSpeed(toon.forwardSpeed, toon.rotateSpeed)
return
newTossTrack = Sequence(tossTrack, Func(matchRunningAnim))
pieTrack = Parallel(newTossTrack, pieTrack)
elapsedTime = globalClockDelta.localElapsedTime(timestamp)
if elapsedTime < 16.0 / 24.0:
elapsedTime = 16.0 / 24.0
pieTrack.start(elapsedTime)
self.toonPieTracks[avId] = pieTrack
def getTossPieInterval(self, toon, x, y, z, h, p, r, power, beginFlyIval = Sequence()):
from toontown.toonbase import ToontownBattleGlobals
from toontown.battle import BattleProps
pie = toon.getPieModel()
pie.setScale(0.9)
flyPie = pie.copyTo(NodePath('a'))
pieName = ToontownBattleGlobals.pieNames[toon.pieType]
pieType = BattleProps.globalPropPool.getPropType(pieName)
animPie = Sequence()
if pieType == 'actor':
animPie = ActorInterval(pie, pieName, startFrame=48)
sound = loader.loadSfx('phase_3.5/audio/sfx/AA_pie_throw_only.ogg')
t = power / 100.0
dist = 100 - 70 * t
time = 1 + 0.5 * t
proj = ProjectileInterval(None, startPos=Point3(0, 0, 0), endPos=Point3(0, dist, 0), duration=time)
relVel = proj.startVel
def getVelocity(toon = toon, relVel = relVel):
return render.getRelativeVector(toon, relVel) * 0.6
toss = Track((0, Sequence(Func(toon.setPosHpr, x, y, z, h, p, r), Func(pie.reparentTo, toon.rightHand), Func(pie.setPosHpr, 0, 0, 0, 0, 0, 0), Parallel(ActorInterval(toon, 'throw', startFrame=48, partName='torso'), animPie), Func(toon.loop, 'neutral'))), (16.0 / 24.0, Func(pie.detachNode)))
fly = Track((14.0 / 24.0, SoundInterval(sound, node=toon)), (16.0 / 24.0, Sequence(Func(flyPie.reparentTo, render), Func(flyPie.setPosHpr, toon, 0.52, 0.97, 2.24, 0, -45, 0), beginFlyIval, ProjectileInterval(flyPie, startVel=getVelocity, duration=6), Func(flyPie.detachNode))))
return (toss, fly, flyPie)
def handlePieHitting(self, colEntry):
if self.gameIsEnding:
return
into = colEntry.getIntoNodePath()
intoName = into.getName()
if 'CogThiefPieSphere' in intoName:
timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32)
parts = intoName.split('-')
suitNum = int(parts[1])
pos = self.cogInfo[suitNum]['suit'].suit.getPos()
if pos in CTGG.CogStartingPositions:
self.notify.debug('Cog %d hit at starting pos %s, ignoring' % (suitNum, pos))
else:
self.sendUpdate('pieHitSuit', [self.localAvId,
timestamp,
suitNum,
pos[0],
pos[1],
pos[2]])
self.makeSuitRespondToPieHit(timestamp, suitNum)
def pieHitSuit(self, avId, timestamp, suitNum, x, y, z):
if not self.hasLocalToon:
return
if self.gameFSM.getCurrentState().getName() not in ['play']:
self.notify.warning('ignoring msg: av %s hit by suit' % avId)
return
if self.gameIsEnding:
return
self.notify.debug('avatar ' + `avId` + ' hit by a suit')
if avId != self.localAvId:
self.makeSuitRespondToPieHit(timestamp, suitNum)
def makeSuitRespondToPieHit(self, timestamp, suitNum):
cog = self.cogInfo[suitNum]['suit']
cog.respondToPieHit(timestamp)
def sendCogAtReturnPos(self, cogIndex, barrelIndex):
timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime(), bits=32)
self.sendUpdate('cogAtReturnPos', [timestamp, cogIndex, barrelIndex])
def markBarrelStolen(self, timestamp, inResponseToClientStamp, barrelIndex):
if not self.hasLocalToon:
return
if barrelIndex not in self.stolenBarrels:
self.stolenBarrels.append(barrelIndex)
barrel = self.barrels[barrelIndex]
barrel.hide()
if base.config.GetBool('cog-thief-check-barrels', 1):
if not base.config.GetBool('cog-thief-endless', 0):
if len(self.stolenBarrels) == len(self.barrels):
localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32)
gameTime = self.local2GameTime(localStamp)
self.clockStopTime = gameTime
self.notify.debug('clockStopTime = %s' % gameTime)
score = int(self.scoreMult * CTGG.calcScore(gameTime) + 0.5)
self.rewardPanel['text'] = str(score)
self.showResults()
def __gameTimerExpired(self):
self.notify.debug('game timer expired')
self.showResults()
def __startRewardCountdown(self):
taskMgr.remove(self.REWARD_COUNTDOWN_TASK)
taskMgr.add(self.__updateRewardCountdown, self.REWARD_COUNTDOWN_TASK)
def __killRewardCountdown(self):
taskMgr.remove(self.REWARD_COUNTDOWN_TASK)
def __updateRewardCountdown(self, task):
curTime = self.getCurrentGameTime()
if self.clockStopTime is not None:
if self.clockStopTime < curTime:
self.notify.debug('self.clockStopTime < curTime %s %s' % (self.clockStopTime, curTime))
self.__killRewardCountdown()
curTime = self.clockStopTime
if curTime > CTGG.GameTime:
curTime = CTGG.GameTime
score = int(self.scoreMult * CTGG.calcScore(curTime) + 0.5)
if not hasattr(task, 'curScore'):
task.curScore = score
result = Task.cont
if hasattr(self, 'rewardPanel'):
self.rewardPanel['text'] = str(score)
if task.curScore != score:
if hasattr(self, 'jarIval'):
self.jarIval.finish()
s = self.rewardPanel.getScale()
self.jarIval = Parallel(Sequence(self.rewardPanel.scaleInterval(0.15, s * 3.0 / 4.0, blendType='easeOut'), self.rewardPanel.scaleInterval(0.15, s, blendType='easeIn')), SoundInterval(self.sndRewardTick), name='cogThiefGameRewardJarThrob')
self.jarIval.start()
task.curScore = score
else:
result = Task.done
return result
def startGameWalk(self):
if self.useOrthoWalk:
self.gameWalk.start()
else:
self.gameWalk.enter()
self.gameWalk.fsm.request('walking')
def stopGameWalk(self):
if self.useOrthoWalk:
self.gameWalk.stop()
else:
self.gameWalk.exit()
def getCogThief(self, cogIndex):
return self.cogInfo[cogIndex]['suit']
def isToonPlayingHitTrack(self, avId):
if avId in self.toonHitTracks:
track = self.toonHitTracks[avId]
if track.isPlaying():
return True
return False
def getNumCogs(self):
result = base.config.GetInt('cog-thief-num-cogs', 0)
if not result:
safezone = self.getSafezoneId()
result = CTGG.calculateCogs(self.numPlayers, safezone)
return result
def getCogSpeed(self):
result = 6.0
safezone = self.getSafezoneId()
result = CTGG.calculateCogSpeed(self.numPlayers, safezone)
return result
def showResults(self):
if not self.gameIsEnding:
self.gameIsEnding = True
for barrel in self.barrels:
barrel.wrtReparentTo(render)
for key in self.cogInfo:
thief = self.cogInfo[key]['suit']
thief.suit.setPos(100, 0, 0)
thief.suit.hide()
self.__killRewardCountdown()
self.stopGameWalk()
numBarrelsSaved = len(self.barrels) - len(self.stolenBarrels)
resultStr = ''
if numBarrelsSaved == len(self.barrels):
resultStr = TTLocalizer.CogThiefPerfect
elif numBarrelsSaved > 1:
resultStr = TTLocalizer.CogThiefBarrelsSaved % {'num': numBarrelsSaved}
elif numBarrelsSaved == 1:
resultStr = TTLocalizer.CogThiefBarrelSaved % {'num': numBarrelsSaved}
else:
resultStr = TTLocalizer.CogThiefNoBarrelsSaved
perfectTextSubnode = hidden.attachNewNode(self.__genText(resultStr))
perfectText = hidden.attachNewNode('perfectText')
perfectTextSubnode.reparentTo(perfectText)
frame = self.__textGen.getCardActual()
offsetY = -abs(frame[2] + frame[3]) / 2.0
perfectTextSubnode.setPos(0, 0, offsetY)
perfectText.setColor(1, 0.1, 0.1, 1)
def fadeFunc(t, text = perfectText):
text.setColorScale(1, 1, 1, t)
def destroyText(text = perfectText):
text.removeNode()
def safeGameOver(self = self):
if not self.frameworkFSM.isInternalStateInFlux():
self.gameOver()
textTrack = Sequence(Func(perfectText.reparentTo, aspect2d), Parallel(LerpScaleInterval(perfectText, duration=0.5, scale=0.3, startScale=0.0), LerpFunctionInterval(fadeFunc, fromData=0.0, toData=1.0, duration=0.5)), Wait(2.0), Parallel(LerpScaleInterval(perfectText, duration=0.5, scale=1.0), LerpFunctionInterval(fadeFunc, fromData=1.0, toData=0.0, duration=0.5, blendType='easeIn')), Func(destroyText), WaitInterval(0.5), Func(safeGameOver))
if numBarrelsSaved == len(self.barrels):
soundTrack = SoundInterval(self.sndPerfect)
else:
soundTrack = Sequence()
self.resultIval = Parallel(textTrack, soundTrack)
self.resultIval.start()
def __genText(self, text):
self.__textGen.setText(text)
return self.__textGen.generate()
def getIntroTrack(self):
base.camera.setPosHpr(0, -13.66, 13.59, 0, -51.6, 0)
result = Sequence(Wait(2), LerpPosHprInterval(base.camera, 13, Point3(self.cameraTopView[0], self.cameraTopView[1], self.cameraTopView[2]), Point3(self.cameraTopView[3], self.cameraTopView[4], self.cameraTopView[5]), blendType='easeIn'))
return result