toontown-just-works/toontown/safezone/OZSafeZoneLoader.py
2024-07-07 18:08:39 -05:00

373 lines
18 KiB
Python

import copy
from direct.actor import Actor
from direct.distributed.ClockDelta import *
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from direct.interval.IntervalGlobal import *
from panda3d.core import *
import random
from otp.avatar import Avatar
from otp.otpbase import OTPGlobals
from toontown.distributed import DelayDelete
from toontown.effects import Bubbles
from toontown.hood import ZoneUtil
from toontown.safezone.OZPlayground import OZPlayground
from toontown.safezone.SafeZoneLoader import SafeZoneLoader
from toontown.toon import Toon, ToonDNA
class OZSafeZoneLoader(SafeZoneLoader):
def __init__(self, hood, parentFSM, doneEvent):
SafeZoneLoader.__init__(self, hood, parentFSM, doneEvent)
self.musicFile = 'phase_6/audio/bgm/OZ_SZ.ogg'
self.activityMusicFile = 'phase_6/audio/bgm/GS_KartShop.ogg'
self.dnaFile = 'phase_6/dna/outdoor_zone_sz.pdna'
self.safeZoneStorageDNAFile = 'phase_6/dna/storage_OZ_sz.pdna'
self.__toonTracks = {}
del self.fsm
self.fsm = ClassicFSM.ClassicFSM('SafeZoneLoader', [State.State('start', self.enterStart, self.exitStart, ['quietZone', 'playground', 'toonInterior']),
State.State('playground', self.enterPlayground, self.exitPlayground, ['quietZone', 'golfcourse']),
State.State('toonInterior', self.enterToonInterior, self.exitToonInterior, ['quietZone']),
State.State('quietZone', self.enterQuietZone, self.exitQuietZone, ['playground', 'toonInterior', 'golfcourse']),
State.State('golfcourse', self.enterGolfCourse, self.exitGolfCourse, ['quietZone', 'playground']),
State.State('final', self.enterFinal, self.exitFinal, ['start'])], 'start', 'final')
def load(self):
self.done = 0
self.geyserTrack = None
SafeZoneLoader.load(self)
self.birdSound = map(base.loadSfx, ['phase_4/audio/sfx/SZ_TC_bird1.ogg', 'phase_4/audio/sfx/SZ_TC_bird2.ogg', 'phase_4/audio/sfx/SZ_TC_bird3.ogg'])
self.underwaterSound = base.loadSfx('phase_4/audio/sfx/AV_ambient_water.ogg')
self.swimSound = base.loadSfx('phase_4/audio/sfx/AV_swim_single_stroke.ogg')
self.submergeSound = base.loadSfx('phase_5.5/audio/sfx/AV_jump_in_water.ogg')
geyserPlacer = self.geom.find('**/geyser*')
waterfallPlacer = self.geom.find('**/waterfall*')
binMgr = CullBinManager.getGlobalPtr()
binMgr.addBin('water', CullBinManager.BTFixed, 29)
pool = self.geom.find('**/pPlane5*')
pool.setTransparency(1)
pool.setColorScale(1.0, 1.0, 1.0, 1.0)
pool.setBin('water', 50, 1)
self.geyserModel = loader.loadModel('phase_6/models/golf/golf_geyser_model')
self.geyserSound = loader.loadSfx('phase_6/audio/sfx/OZ_Geyser.ogg')
self.geyserSoundInterval = SoundInterval(self.geyserSound, node=geyserPlacer, listenerNode=base.camera, seamlessLoop=False, volume=1.0, cutOff=120)
self.geyserSoundNoToon = loader.loadSfx('phase_6/audio/sfx/OZ_Geyser_No_Toon.ogg')
self.geyserSoundNoToonInterval = SoundInterval(self.geyserSoundNoToon, node=geyserPlacer, listenerNode=base.camera, seamlessLoop=False, volume=1.0, cutOff=120)
if self.geyserModel:
self.geyserActor = Actor.Actor(self.geyserModel)
self.geyserActor.loadAnims({'idle': 'phase_6/models/golf/golf_geyser'})
self.geyserActor.reparentTo(render)
self.geyserActor.setPlayRate(8.6, 'idle')
self.geyserActor.loop('idle')
self.geyserActor.setDepthWrite(0)
self.geyserActor.setTwoSided(True, 11)
self.geyserActor.setColorScale(1.0, 1.0, 1.0, 1.0)
self.geyserActor.setBin('fixed', 0)
mesh = self.geyserActor.find('**/mesh_tide1')
joint = self.geyserActor.find('**/uvj_WakeWhiteTide1')
mesh.setTexProjector(mesh.findTextureStage('default'), joint, self.geyserActor)
self.geyserActor.setPos(geyserPlacer.getPos())
self.geyserActor.setZ(geyserPlacer.getZ() - 100.0)
self.geyserPos = geyserPlacer.getPos()
self.geyserPlacer = geyserPlacer
self.startGeyser()
base.sfxPlayer.setCutoffDistance(160)
self.geyserPoolSfx = loader.loadSfx('phase_6/audio/sfx/OZ_Geyser_BuildUp_Loop.ogg')
self.geyserPoolSoundInterval = SoundInterval(self.geyserPoolSfx, node=self.geyserPlacer, listenerNode=base.camera, seamlessLoop=True, volume=1.0, cutOff=120)
self.geyserPoolSoundInterval.loop()
self.bubbles = Bubbles.Bubbles(self.geyserPlacer, render)
self.bubbles.renderParent.setDepthWrite(0)
self.bubbles.start()
self.collBase = render.attachNewNode('collisionBase')
self.geyserCollSphere = CollisionSphere(0, 0, 0, 7.5)
self.geyserCollSphere.setTangible(1)
self.geyserCollNode = CollisionNode('barrelSphere')
self.geyserCollNode.setIntoCollideMask(OTPGlobals.WallBitmask)
self.geyserCollNode.addSolid(self.geyserCollSphere)
self.geyserNodePath = self.collBase.attachNewNode(self.geyserCollNode)
self.geyserNodePath.setPos(self.geyserPos[0], self.geyserPos[1], self.geyserPos[2] - 100.0)
self.waterfallModel = loader.loadModel('phase_6/models/golf/golf_waterfall_model')
if self.waterfallModel:
self.waterfallActor = Actor.Actor(self.waterfallModel)
self.waterfallActor.loadAnims({'idle': 'phase_6/models/golf/golf_waterfall'})
self.waterfallActor.reparentTo(render)
self.waterfallActor.setPlayRate(3.5, 'idle')
self.waterfallActor.loop('idle')
mesh = self.waterfallActor.find('**/mesh_tide1')
joint = self.waterfallActor.find('**/uvj_WakeWhiteTide1')
mesh.setTexProjector(mesh.findTextureStage('default'), joint, self.waterfallActor)
self.waterfallActor.setPos(waterfallPlacer.getPos())
self.accept('clientLogout', self._handleLogout)
def exit(self):
self.clearToonTracks()
SafeZoneLoader.exit(self)
self.ignore('clientLogout')
def startGeyser(self, task = None):
if hasattr(base.cr, 'DTimer') and base.cr.DTimer:
self.geyserCycleTime = 20.0
useTime = base.cr.DTimer.getTime()
timeToNextGeyser = 20.0 - useTime % 20.0
taskMgr.doMethodLater(timeToNextGeyser, self.doGeyser, 'geyser Task')
else:
taskMgr.doMethodLater(5.0, self.startGeyser, 'start geyser Task')
def doGeyser(self, task = None):
if not self.done:
self.setGeyserAnim()
useTime = base.cr.DTimer.getTime()
timeToNextGeyser = 20.0 - useTime % 20.0
taskMgr.doMethodLater(timeToNextGeyser, self.doGeyser, 'geyser Task')
return task.done
def restoreLocal(self, task = None):
place = base.cr.playGame.getPlace()
if place:
place.fsm.request('walk')
base.localAvatar.setTeleportAvailable(1)
base.localAvatar.collisionsOn()
base.localAvatar.dropShadow.show()
def restoreRemote(self, remoteAv, task = None):
if remoteAv in Avatar.Avatar.ActiveAvatars:
remoteAv.startSmooth()
remoteAv.dropShadow.show()
def setGeyserAnim(self, task = None):
if self.done:
return
maxSize = 0.4 * random.random() + 0.75
time = 1.0
self.geyserTrack = Sequence()
upPos = Vec3(self.geyserPos[0], self.geyserPos[1], self.geyserPos[2])
downPos = Vec3(self.geyserPos[0], self.geyserPos[1], self.geyserPos[2] - 8.0)
avList = copy.copy(Avatar.Avatar.ActiveAvatars)
avList.append(base.localAvatar)
playSound = 0
for av in avList:
distance = self.geyserPlacer.getDistance(av)
if distance < 7.0:
place = base.cr.playGame.getPlace()
local = 0
avPos = av.getPos()
upToon = Vec3(avPos[0], avPos[1], maxSize * self.geyserPos[2] + 40.0)
midToon = Vec3(avPos[0], avPos[1], maxSize * self.geyserPos[2] + 30.0)
downToon = Vec3(avPos[0], avPos[1], self.geyserPos[2])
returnPoints = [(7, 7),
(8, 0),
(-8, 3),
(-7, 7),
(3, -7),
(0, 8),
(-10, 0),
(8, -3),
(5, 8),
(-8, 5),
(-1, 7)]
pick = int((float(av.doId) - 11.0) / 13.0 % len(returnPoints))
returnChoice = returnPoints[pick]
toonReturn = Vec3(self.geyserPos[0] + returnChoice[0], self.geyserPos[1] + returnChoice[1], self.geyserPos[2] - 1.5)
topTrack = Sequence()
av.dropShadow.hide()
playSound = 1
if av == base.localAvatar:
base.cr.playGame.getPlace().setState('fishing')
base.localAvatar.setTeleportAvailable(0)
base.localAvatar.collisionsOff()
local = 1
else:
topTrack.delayDeletes = [DelayDelete.DelayDelete(av, 'OZSafeZoneLoader.setGeyserAnim')]
av.stopSmooth()
animTrack = Parallel()
toonTrack = Sequence()
toonTrack.append(Wait(0.5))
animTrack.append(ActorInterval(av, 'jump-idle', loop=1, endTime=11.5 * time))
animTrack.append(ActorInterval(av, 'neutral', loop=0, endTime=0.25 * time))
holder = render.attachNewNode('toon hold')
base.holder = holder
toonPos = av.getPos(render)
toonHpr = av.getHpr(render)
print 'av Pos %s' % av.getPos()
base.toonPos = toonPos
holder.setPos(toonPos)
av.reparentTo(holder)
av.setPos(0, 0, 0)
lookAt = 180
toonH = (lookAt + toonHpr[0]) % 360
newHpr = Vec3(toonH, toonHpr[1], toonHpr[2])
if toonH < 180:
lookIn = Vec3(0 + lookAt, -30, 0)
else:
lookIn = Vec3(360 + lookAt, -30, 0)
print 'Camera Hprs toon %s; lookIn %s; final %s' % (newHpr, lookIn, lookIn - newHpr)
if local == 1:
camPosOriginal = camera.getPos()
camHprOriginal = camera.getHpr()
camParentOriginal = camera.getParent()
cameraPivot = holder.attachNewNode('camera pivot')
chooseHeading = random.choice([-10.0, 15.0, 40.0])
cameraPivot.setHpr(chooseHeading, -20.0, 0.0)
cameraArm = cameraPivot.attachNewNode('camera arm')
cameraArm.setPos(0.0, -23.0, 3.0)
camPosStart = Point3(0.0, 0.0, 0.0)
camHprStart = Vec3(0.0, 0.0, 0.0)
self.changeCamera(cameraArm, camPosStart, camHprStart)
cameraTrack = Sequence()
cameraTrack.append(Wait(11.0 * time))
cameraTrack.append(Func(self.changeCamera, camParentOriginal, camPosOriginal, camHprOriginal))
cameraTrack.start()
moveTrack = Sequence()
moveTrack.append(Wait(0.5))
moveTrack.append(LerpPosInterval(holder, 3.0 * time, pos=upToon, startPos=downToon, blendType='easeOut'))
moveTrack.append(LerpPosInterval(holder, 2.0 * time, pos=midToon, startPos=upToon, blendType='easeInOut'))
moveTrack.append(LerpPosInterval(holder, 1.0 * time, pos=upToon, startPos=midToon, blendType='easeInOut'))
moveTrack.append(LerpPosInterval(holder, 2.0 * time, pos=midToon, startPos=upToon, blendType='easeInOut'))
moveTrack.append(LerpPosInterval(holder, 1.0 * time, pos=upToon, startPos=midToon, blendType='easeInOut'))
moveTrack.append(LerpPosInterval(holder, 2.5 * time, pos=toonReturn, startPos=upToon, blendType='easeIn'))
animTrack.append(moveTrack)
animTrack.append(toonTrack)
topTrack.append(animTrack)
topTrack.append(Func(av.setPos, toonReturn))
topTrack.append(Func(av.reparentTo, render))
topTrack.append(Func(holder.remove))
if local == 1:
topTrack.append(Func(self.restoreLocal))
else:
topTrack.append(Func(self.restoreRemote, av))
topTrack.append(Func(self.clearToonTrack, av.doId))
self.storeToonTrack(av.doId, topTrack)
topTrack.start()
self.geyserTrack.append(Func(self.doPrint, 'geyser start'))
self.geyserTrack.append(Func(self.geyserNodePath.setPos, self.geyserPos[0], self.geyserPos[1], self.geyserPos[2]))
self.geyserTrack.append(Parallel(LerpScaleInterval(self.geyserActor, 2.0 * time, 0.75, 0.01), LerpPosInterval(self.geyserActor, 2.0 * time, pos=downPos, startPos=downPos)))
self.geyserTrack.append(Parallel(LerpScaleInterval(self.geyserActor, time, maxSize, 0.75), LerpPosInterval(self.geyserActor, time, pos=upPos, startPos=downPos)))
self.geyserTrack.append(Parallel(LerpScaleInterval(self.geyserActor, 2.0 * time, 0.75, maxSize), LerpPosInterval(self.geyserActor, 2.0 * time, pos=downPos, startPos=upPos)))
self.geyserTrack.append(Parallel(LerpScaleInterval(self.geyserActor, time, maxSize, 0.75), LerpPosInterval(self.geyserActor, time, pos=upPos, startPos=downPos)))
self.geyserTrack.append(Parallel(LerpScaleInterval(self.geyserActor, 2.0 * time, 0.75, maxSize), LerpPosInterval(self.geyserActor, 2.0 * time, pos=downPos, startPos=upPos)))
self.geyserTrack.append(Parallel(LerpScaleInterval(self.geyserActor, time, maxSize, 0.75), LerpPosInterval(self.geyserActor, time, pos=upPos, startPos=downPos)))
self.geyserTrack.append(Parallel(LerpScaleInterval(self.geyserActor, 4.0 * time, 0.01, maxSize), LerpPosInterval(self.geyserActor, 4.0 * time, pos=downPos, startPos=upPos)))
self.geyserTrack.append(Func(self.geyserNodePath.setPos, self.geyserPos[0], self.geyserPos[1], self.geyserPos[2] - 100.0))
self.geyserTrack.append(Func(self.doPrint, 'geyser end'))
self.geyserTrack.start()
if playSound:
self.geyserSoundInterval.start()
else:
self.geyserSoundNoToonInterval.start()
def changeCamera(self, newParent, newPos, newHpr):
camera.reparentTo(newParent)
camera.setPosHpr(newPos, newHpr)
def doPrint(self, thing):
return 0
print thing
def unload(self):
del self.birdSound
SafeZoneLoader.unload(self)
self.done = 1
self.collBase.removeNode()
if self.geyserTrack:
self.geyserTrack.finish()
self.geyserTrack = None
self.geyserActor.cleanup()
self.geyserModel.removeNode()
self.waterfallActor.cleanup()
self.waterfallModel.removeNode()
self.bubbles.destroy()
del self.bubbles
self.geyserPoolSoundInterval.finish()
self.geyserPoolSfx.stop()
self.geyserPoolSfx = None
self.geyserPoolSoundInterval = None
self.geyserSoundInterval.finish()
self.geyserSound.stop()
self.geyserSoundInterval = None
self.geyserSound = None
self.geyserSoundNoToonInterval.finish()
self.geyserSoundNoToon.stop()
self.geyserSoundNoToonInterval = None
self.geyserSoundNoToon = None
def enterPlayground(self, requestStatus):
self.playgroundClass = OZPlayground
SafeZoneLoader.enterPlayground(self, requestStatus)
def exitPlayground(self):
taskMgr.remove('titleText')
self.hood.hideTitleText()
SafeZoneLoader.exitPlayground(self)
self.playgroundClass = None
return
def handlePlaygroundDone(self):
status = self.place.doneStatus
self.doneStatus = status
messenger.send(self.doneEvent)
def enteringARace(self, status):
if not status['where'] == 'golfcourse':
return 0
if ZoneUtil.isDynamicZone(status['zoneId']):
return status['hoodId'] == self.hood.hoodId
else:
return ZoneUtil.getHoodId(status['zoneId']) == self.hood.hoodId
def enteringAGolfCourse(self, status):
if not status['where'] == 'golfcourse':
return 0
if ZoneUtil.isDynamicZone(status['zoneId']):
return status['hoodId'] == self.hood.hoodId
else:
return ZoneUtil.getHoodId(status['zoneId']) == self.hood.hoodId
def enterGolfCourse(self, requestStatus):
if 'curseId' in requestStatus:
self.golfCourseId = requestStatus['courseId']
else:
self.golfCourseId = 0
self.accept('raceOver', self.handleRaceOver)
self.accept('leavingGolf', self.handleLeftGolf)
base.transitions.irisOut(t=0.2)
def exitGolfCourse(self):
del self.golfCourseId
def handleRaceOver(self):
print 'you done!!'
def handleLeftGolf(self):
req = {'loader': 'safeZoneLoader',
'where': 'playground',
'how': 'teleportIn',
'zoneId': 6000,
'hoodId': 6000,
'shardId': None}
self.fsm.request('quietZone', [req])
return
def _handleLogout(self):
self.clearToonTracks()
def storeToonTrack(self, avId, track):
self.clearToonTrack(avId)
self.__toonTracks[avId] = track
def clearToonTrack(self, avId):
oldTrack = self.__toonTracks.get(avId)
if oldTrack:
oldTrack.pause()
DelayDelete.cleanupDelayDeletes(oldTrack)
del self.__toonTracks[avId]
def clearToonTracks(self):
keyList = []
for key in self.__toonTracks:
keyList.append(key)
for key in keyList:
if key in self.__toonTracks:
self.clearToonTrack(key)