oldschool-toontown/toontown/safezone/OZSafeZoneLoader.py
2019-12-30 01:07:56 -05:00

383 lines
18 KiB
Python

from direct.directnotify import DirectNotifyGlobal
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from pandac.PandaModules import *
from otp.avatar import Avatar
from toontown.hood import ZoneUtil
from toontown.launcher import DownloadForceAcknowledge
from toontown.safezone.SafeZoneLoader import SafeZoneLoader
from toontown.safezone.OZPlayground import OZPlayground
from direct.actor import Actor
from direct.interval.IntervalGlobal import *
import random
from toontown.distributed import DelayDelete
from direct.distributed.ClockDelta import *
from otp.otpbase import OTPGlobals
import copy
from toontown.effects import Bubbles
import random
if (__debug__):
import pdb
class OZSafeZoneLoader(SafeZoneLoader):
def __init__(self, hood, parentFSM, doneEvent):
SafeZoneLoader.__init__(self, hood, parentFSM, doneEvent)
self.musicFile = 'phase_6/audio/bgm/OZ_SZ.mid'
self.activityMusicFile = 'phase_6/audio/bgm/GS_KartShop.mid'
self.dnaFile = 'phase_6/dna/outdoor_zone_sz.dna'
self.safeZoneStorageDNAFile = 'phase_6/dna/storage_OZ_sz.dna'
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 = list(map(base.loader.loadSfx, ['phase_4/audio/sfx/SZ_TC_bird1.mp3', 'phase_4/audio/sfx/SZ_TC_bird2.mp3', 'phase_4/audio/sfx/SZ_TC_bird3.mp3']))
self.underwaterSound = base.loader.loadSfx('phase_4/audio/sfx/AV_ambient_water.mp3')
self.swimSound = base.loader.loadSfx('phase_4/audio/sfx/AV_swim_single_stroke.mp3')
self.submergeSound = base.loader.loadSfx('phase_5.5/audio/sfx/AV_jump_in_water.mp3')
geyserPlacer = self.geom.find('**/geyser*')
waterfallPlacer = self.geom.find('**/waterfall*')
binMgr = CullBinManager.getGlobalPtr()
binMgr.addBin('water', CullBinManager.BTFixed, 29)
binMgr = CullBinManager.getGlobalPtr()
self.water = self.geom.find('**/water1*')
self.water.setTransparency(1)
self.water.setColorScale(1.0, 1.0, 1.0, 1.0)
self.water.setBin('water', 51, 1)
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.mp3')
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.mp3')
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.wav')
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)
return
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
return
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)