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

292 lines
12 KiB
Python

from panda3d.core 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
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.loadSfx('phase_3.5/audio/dial/AV_' + self.toon.style.getAnimal() + '_exclaim.ogg')
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 = Sequence(self.scoreText.posInterval(0.5, Point3(0, 0, self.toon.height + 2), blendType='easeOut'), self.scoreText.colorInterval(0.25, Vec4(r, g, b, 0)), Func(self.hideScoreText))
seq.start()
def hideScoreText(self):
if self.scoreText:
taskMgr.remove(self.game.uniqueName('scoreText'))
self.scoreText.removeNode()
self.scoreText = None
return