from pandac.PandaModules import * from toontown.toonbase.ToonBaseGlobal import * from direct.interval.IntervalGlobal import * from toontown.toonbase.ToontownGlobals import * from direct.directnotify import DirectNotifyGlobal from direct.fsm import StateData from direct.fsm import ClassicFSM, State from direct.fsm import State from . import ToonBlitzGlobals from otp.otpbase import OTPGlobals from direct.task.Task import Task from toontown.minigame import TwoDBattleMgr from toontown.racing import RaceHeadFrame COLOR_RED = VBase4(1, 0, 0, 0.3) class TwoDGameToonSD(StateData.StateData): notify = DirectNotifyGlobal.directNotify.newCategory('TwoDGameToonSD') FallBackAnim = 'slip-backward' NeutralAnim = 'neutral' RunAnim = 'run' ShootGun = 'water-gun' Victory = 'victory' animList = [FallBackAnim, NeutralAnim, RunAnim, ShootGun, Victory] ScoreTextGenerator = TextNode('ScoreTextGenerator') def __init__(self, avId, game): self.avId = avId self.game = game self.isLocal = avId == base.localAvatar.doId self.toon = self.game.getAvatar(self.avId) self.unexpectedExit = False self.fallBackIval = None self.fallDownIval = None self.victoryIval = None self.squishIval = None self.fsm = ClassicFSM.ClassicFSM('TwoDGameAnimFSM-%s' % self.avId, [State.State('init', self.enterInit, self.exitInit, ['normal']), State.State('normal', self.enterNormal, self.exitNormal, ['shootGun', 'fallBack', 'fallDown', 'victory', 'squish']), State.State('shootGun', self.enterShootGun, self.exitShootGun, ['normal', 'fallBack', 'fallDown', 'victory', 'squish']), State.State('fallBack', self.enterFallBack, self.exitFallBack, ['normal', 'fallDown', 'squish']), State.State('fallDown', self.enterFallDown, self.exitFallDown, ['normal']), State.State('squish', self.enterSquish, self.exitSquish, ['normal']), State.State('victory', self.enterVictory, self.exitVictory, ['normal', 'fallDown']), State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'init', 'cleanup') self.scoreText = None self.load() self.progressLineLength = self.game.assetMgr.faceEndPos[0] - self.game.assetMgr.faceStartPos[0] self.conversionRatio = self.progressLineLength / self.game.gameLength return def load(self): for anim in self.animList: self.toon.pose(anim, 0) self.battleMgr = TwoDBattleMgr.TwoDBattleMgr(self.game, self.toon) self.squishSound = base.loader.loadSfx('phase_3.5/audio/dial/AV_' + self.toon.style.getAnimal() + '_exclaim.mp3') def destroy(self): if self.fallBackIval != None: self.fallBackIval.finish() self.fallBackIval = None if self.fallDownIval != None: self.fallDownIval.finish() self.fallDownIval = None if self.squishIval != None: self.squishIval.finish() self.squishIval = None if self.victoryIval != None: self.victoryIval.finish() self.victoryIval = None self.hideScoreText() self.headFrame.destroy() self.battleMgr.destroy() del self.battleMgr del self.fsm return def enter(self): self.fsm.enterInitialState() def exit(self, unexpectedExit = False): self.unexpectedExit = unexpectedExit self.fsm.requestFinalState() def enterInit(self): self.notify.debug('enterInit') self.toon.startBlink() self.toon.stopLookAround() self.toon.useLOD(1000) self.toon.dropShadow.hide() def exitInit(self): pass def enterNormal(self): self.notify.debug('enterNormal') def exitNormal(self): pass def enterFallBack(self): self.notify.debug('enterFallBack') fallBackDist = 9 self.blinkRed = self.blinkColor(COLOR_RED, 2) duration = 4 animName = self.FallBackAnim startFrame = 1 endFrame = 22 totalFrames = self.toon.getNumFrames(animName) frames = totalFrames - 1 - startFrame frameRate = self.toon.getFrameRate(animName) newRate = frames / duration playRate = newRate / frameRate fallBackAnim = Sequence(ActorInterval(self.toon, animName, startTime=startFrame / newRate, endTime=endFrame / newRate, playRate=playRate), ActorInterval(self.toon, animName, startFrame=23, playRate=1), FunctionInterval(self.resume)) self.fallBackIval = Parallel(self.blinkRed, fallBackAnim) if self.isLocal: self.game.ignoreInputs() self.toon.controlManager.currentControls.lifter.setVelocity(12) if self.toon.getH() == 90: endPoint = Point3(self.toon.getX() + fallBackDist, self.toon.getY(), self.toon.getZ()) else: endPoint = Point3(self.toon.getX() - fallBackDist, self.toon.getY(), self.toon.getZ()) enemyHitTrajectory = LerpFunc(self.toon.setX, fromData=self.toon.getX(), toData=endPoint.getX(), duration=0.75, name='enemyHitTrajectory') self.fallBackIval.append(enemyHitTrajectory) base.playSfx(self.game.assetMgr.sndOof) self.fallBackIval.start() def exitFallBack(self): self.fallBackIval.pause() self.blinkRed.finish() if self.isLocal: if self.game.gameFSM.getCurrentState().getName() == 'play': self.game.acceptInputs() def shootGun(self): if self.fsm.getCurrentState().getName() == 'shootGun': self.fsm.request('normal') self.fsm.request('shootGun') def enterShootGun(self): self.battleMgr.shoot() self.fsm.request('normal') def exitShootGun(self): pass def enterFallDown(self): self.notify.debug('enterFallDown') self.fallDownIval = Sequence() self.blinkRed = self.blinkColor(COLOR_RED, 2) if self.isLocal: self.game.ignoreInputs() base.playSfx(self.game.assetMgr.fallSound) pos = self.game.sectionMgr.getLastSpawnPoint() toonRespawnIval = Sequence(Wait(1), Func(base.localAvatar.setPos, pos)) self.fallDownIval.append(toonRespawnIval) self.fallDownIval.append(Func(self.resume)) self.fallDownIval.append(self.blinkRed) self.fallDownIval.start() def exitFallDown(self): if self.isLocal: if self.game.gameFSM.getCurrentState().getName() == 'play': self.game.acceptInputs() def enterSquish(self): self.notify.debug('enterSquish') if self.isLocal: self.game.ignoreInputs() self.toon.setAnimState('Squish') self.toon.stunToon() base.playSfx(self.squishSound, node=self.toon, volume=2) self.blinkRed = self.blinkColor(COLOR_RED, 3) self.squishIval = Parallel(self.blinkRed, Sequence(Wait(2.5), Func(self.resume))) self.squishIval.start() def exitSquish(self): if self.isLocal: if self.game.gameFSM.getCurrentState().getName() == 'play': self.game.acceptInputs() def enterVictory(self): self.notify.debug('enterVictory') outsideElevatorPos = self.game.sectionMgr.exitElevator.find('**/loc_elevator_front').getPos(render) insideElevatorPos = self.game.sectionMgr.exitElevator.find('**/loc_elevator_inside').getPos(render) runToElevator = Parallel(LerpPosInterval(self.toon, self.game.timeToRunToElevator, outsideElevatorPos), ActorInterval(self.toon, self.RunAnim, loop=1, duration=self.game.timeToRunToElevator)) danceIval = Parallel(LerpPosInterval(self.toon, 2, insideElevatorPos), ActorInterval(self.toon, self.Victory, loop=1, duration=ToonBlitzGlobals.GameDuration[self.game.getSafezoneId()])) waitToLand = 0.0 if self.toon.getZ(render) > 13: waitToLand = 1 self.victoryIval = Sequence(Wait(waitToLand), runToElevator, danceIval) self.victoryIval.start() def exitVictory(self): pass def enterCleanup(self): self.notify.debug('enterCleanup') self.toon.stopBlink() self.toon.startLookAround() self.toon.resetLOD() self.toon.dropShadow.show() def exitCleanup(self): pass def resume(self): self.fsm.request('normal') messenger.send('jumpLand') def blinkColor(self, color, duration): blink = Sequence(LerpColorScaleInterval(self.toon, 0.5, color, startColorScale=VBase4(1, 1, 1, 1)), LerpColorScaleInterval(self.toon, 0.5, VBase4(1, 1, 1, 1), startColorScale=color)) track = Sequence(Func(blink.loop), Wait(duration), Func(blink.finish)) return track def setAnimState(self, newState, playRate): if not self.unexpectedExit: self.toon.setAnimState(newState, playRate) def createHeadFrame(self, drawNum): toon = base.cr.doId2do.get(self.avId, None) self.headFrame = RaceHeadFrame.RaceHeadFrame(av=toon) eyes = self.headFrame.head.find('**/eyes*') eyes.setDepthTest(1) eyes.setDepthWrite(1) self.headFrame.configure(geom_scale=(0.5, 0.5, 0.5)) self.headFrame.setZ(self.game.assetMgr.faceStartPos[2]) self.headFrame.setDepthWrite(True) self.headFrame.setDepthTest(True) self.headFrame.reparentTo(self.game.assetMgr.aspect2dRoot) self.headFrame.setY(-drawNum) if self.isLocal: self.headFrame.setScale(0.2) else: self.headFrame.setScale(0.15) self.headFrame.setX(self.game.assetMgr.faceStartPos[0]) return def update(self): toonCurrX = self.toon.getX(render) progress = toonCurrX - self.game.gameStartX headFrameProgress = progress * self.conversionRatio headFrameX = self.game.assetMgr.faceStartPos[0] + headFrameProgress headFrameX = max(self.game.assetMgr.faceStartPos[0], headFrameX) headFrameX = min(self.game.assetMgr.faceEndPos[0], headFrameX) self.headFrame.setX(headFrameX) def showScoreText(self, number, scale = 1.25): if not number == 0: if self.scoreText: self.hideScoreText() self.ScoreTextGenerator.setFont(OTPGlobals.getSignFont()) if number < 0: self.ScoreTextGenerator.setText(str(number)) else: self.ScoreTextGenerator.setText('+' + str(number)) self.ScoreTextGenerator.clearShadow() self.ScoreTextGenerator.setAlign(TextNode.ACenter) if number < 0: r, g, b, a = (0.9, 0, 0, 1) else: r, g, b, a = (0.9, 0.9, 0, 1) self.scoreTextNode = self.ScoreTextGenerator.generate() self.scoreText = self.toon.attachNewNode(self.scoreTextNode) self.scoreText.setScale(scale) self.scoreText.setBillboardPointEye() self.scoreText.setBin('fixed', 100) self.scoreText.setPos(0, 0, self.toon.height / 2) self.scoreText.setTransparency(1) self.scoreText.setColor(r, g, b, a) self.scoreText.setDepthTest(0) self.scoreText.setDepthWrite(0) seq = Task.sequence(self.scoreText.lerpPos(Point3(0, 0, self.toon.height + 2), 0.5, blendType='easeOut'), self.scoreText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.25), Task(self.hideScoreTextTask)) taskMgr.add(seq, self.game.uniqueName('scoreText')) def hideScoreText(self): if self.scoreText: taskMgr.remove(self.game.uniqueName('scoreText')) self.scoreText.removeNode() self.scoreText = None return def hideScoreTextTask(self, task): self.hideScoreText() return Task.done