ToonTownRewritten/toontown/building/DistributedClubElevator.py
2014-05-09 14:53:36 -06:00

531 lines
21 KiB
Python

from pandac.PandaModules import *
from direct.distributed.ClockDelta import *
from direct.interval.IntervalGlobal import *
from toontown.building import ElevatorConstants
from toontown.building import ElevatorUtils
from toontown.building import DistributedElevatorFSM
from toontown.toonbase import ToontownGlobals
from direct.directnotify import DirectNotifyGlobal
from direct.fsm import ClassicFSM
from direct.fsm import State
from toontown.hood import ZoneUtil
from toontown.toonbase import TTLocalizer
from direct.fsm.FSM import FSM
from direct.task import Task
from toontown.distributed import DelayDelete
from direct.showbase import PythonUtil
class DistributedClubElevator(DistributedElevatorFSM.DistributedElevatorFSM):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedClubElevator')
JumpOutOffsets = ((3, 5, 0),
(1.5, 4, 0),
(-1.5, 4, 0),
(-3, 4, 0))
defaultTransitions = {'Off': ['Opening', 'Closed'],
'Opening': ['WaitEmpty',
'WaitCountdown',
'Opening',
'Closing'],
'WaitEmpty': ['WaitCountdown', 'Closing', 'Off'],
'WaitCountdown': ['WaitEmpty',
'AllAboard',
'Closing',
'WaitCountdown'],
'AllAboard': ['WaitEmpty', 'Closing'],
'Closing': ['Closed',
'WaitEmpty',
'Closing',
'Opening'],
'Closed': ['Opening']}
id = 0
def __init__(self, cr):
DistributedElevatorFSM.DistributedElevatorFSM.__init__(self, cr)
FSM.__init__(self, 'ElevatorClub_%s_FSM' % self.id)
self.type = ElevatorConstants.ELEVATOR_COUNTRY_CLUB
self.countdownTime = ElevatorConstants.ElevatorData[self.type]['countdown']
self.nametag = None
self.currentFloor = -1
self.isLocked = 0
self.isEntering = 0
self.doorOpeningFlag = 0
self.doorsNeedToClose = 0
self.wantState = 0
self.latch = None
self.lastState = self.state
self.kartModelPath = 'phase_12/models/bossbotHQ/Coggolf_cart3'
self.leftDoor = None
self.rightDoor = None
self.__toonTracks = {}
return
def setupElevator(self):
self.elevatorModel = loader.loadModel('phase_11/models/lawbotHQ/LB_ElevatorScaled')
if not self.elevatorModel:
self.notify.error('No Elevator Model in DistributedElevatorFloor.setupElevator. Please inform JML. Fool!')
self.leftDoor = self.elevatorModel.find('**/left-door')
if self.leftDoor.isEmpty():
self.leftDoor = self.elevatorModel.find('**/left_door')
self.rightDoor = self.elevatorModel.find('**/right-door')
if self.rightDoor.isEmpty():
self.rightDoor = self.elevatorModel.find('**/right_door')
DistributedElevatorFSM.DistributedElevatorFSM.setupElevator(self)
def generate(self):
DistributedElevatorFSM.DistributedElevatorFSM.generate(self)
self.loader = self.cr.playGame.hood.loader
self.golfKart = render.attachNewNode('golfKartNode')
self.kart = loader.loadModel(self.kartModelPath)
self.kart.setPos(0, 0, 0)
self.kart.setScale(1)
self.kart.reparentTo(self.golfKart)
self.wheels = self.kart.findAllMatches('**/wheelNode*')
self.numWheels = self.wheels.getNumPaths()
self.setPosHpr(0, 0, 0, 0, 0, 0)
def announceGenerate(self):
DistributedElevatorFSM.DistributedElevatorFSM.announceGenerate(self)
if self.latch:
self.notify.info('Setting latch in announce generate')
self.setLatch(self.latch)
angle = self.startingHpr[0]
angle -= 90
radAngle = deg2Rad(angle)
unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0)
unitVec *= 45.0
self.endPos = self.startingPos + unitVec
self.endPos.setZ(0.5)
dist = Vec3(self.endPos - self.enteringPos).length()
wheelAngle = dist / (4.8 * 1.4 * math.pi) * 360
self.kartEnterAnimateInterval = Parallel(LerpHprInterval(self.wheels[0], 5.0, Vec3(self.wheels[0].getH(), wheelAngle, self.wheels[0].getR())), LerpHprInterval(self.wheels[1], 5.0, Vec3(self.wheels[1].getH(), wheelAngle, self.wheels[1].getR())), LerpHprInterval(self.wheels[2], 5.0, Vec3(self.wheels[2].getH(), wheelAngle, self.wheels[2].getR())), LerpHprInterval(self.wheels[3], 5.0, Vec3(self.wheels[3].getH(), wheelAngle, self.wheels[3].getR())), name='CogKartAnimate')
trolleyExitTrack1 = Parallel(LerpPosInterval(self.golfKart, 5.0, self.endPos), self.kartEnterAnimateInterval, name='CogKartExitTrack')
self.trolleyExitTrack = Sequence(trolleyExitTrack1)
self.trolleyEnterTrack = Sequence(LerpPosInterval(self.golfKart, 5.0, self.startingPos, startPos=self.enteringPos))
self.closeDoors = Sequence(self.trolleyExitTrack, Func(self.onDoorCloseFinish))
self.openDoors = Sequence(self.trolleyEnterTrack)
self.setPos(0, 0, 0)
def __placeElevator(self):
self.notify.debug('PLACING ELEVATOR FOOL!!')
if self.isEntering:
elevatorNode = render.find('**/elevator_origin')
if not elevatorNode.isEmpty():
self.elevatorModel.setPos(0, 0, 0)
self.elevatorModel.reparentTo(elevatorNode)
else:
self.notify.debug('NO NODE elevator_origin!!')
else:
elevatorNode = render.find('**/SlidingDoor')
if not elevatorNode.isEmpty():
self.elevatorModel.setPos(0, 10, -15)
self.elevatorModel.setH(180)
self.elevatorModel.reparentTo(elevatorNode)
else:
self.notify.debug('NO NODE SlidingDoor!!')
def setLatch(self, markerId):
self.notify.info('Setting latch')
marker = self.cr.doId2do.get(markerId)
self.latchRequest = self.cr.relatedObjectMgr.requestObjects([markerId], allCallback=self.set2Latch, timeout=5)
self.latch = markerId
def set2Latch(self, taskMgrFooler = None):
self.latchRequest = None
if hasattr(self, 'cr'):
marker = self.cr.doId2do.get(self.latch)
if marker:
self.getElevatorModel().reparentTo(marker)
return
taskMgr.doMethodLater(10.0, self._repart2Marker, 'elevatorfloor-markerReparent')
self.notify.warning('Using backup, do method later version of latch')
return
def _repart2Marker(self, taskFoolio = 0):
if hasattr(self, 'cr') and self.cr:
marker = self.cr.doId2do.get(self.latch)
if marker:
self.getElevatorModel().reparentTo(marker)
else:
self.notify.error('could not find latch even in defered try')
def setPos(self, x, y, z):
self.getElevatorModel().setPos(x, y, z)
def setH(self, H):
self.getElevatorModel().setH(H)
def delete(self):
self.request('Off')
DistributedElevatorFSM.DistributedElevatorFSM.delete(self)
self.getElevatorModel().removeNode()
del self.golfKart
self.ignore('LawOffice_Spec_Loaded')
self.ignoreAll()
def disable(self):
self.request('Off')
self.clearToonTracks()
DistributedElevatorFSM.DistributedElevatorFSM.disable(self)
def setEntranceId(self, entranceId):
self.entranceId = entranceId
if self.entranceId == 0:
self.elevatorModel.setPosHpr(62.74, -85.31, 0.0, 2.0, 0.0, 0.0)
elif self.entranceId == 1:
self.elevatorModel.setPosHpr(-162.25, 26.43, 0.0, 269.0, 0.0, 0.0)
else:
self.notify.error('Invalid entranceId: %s' % entranceId)
def gotBldg(self, buildingList):
pass
def setFloor(self, floorNumber):
if self.currentFloor >= 0:
if self.bldg.floorIndicator[self.currentFloor]:
self.bldg.floorIndicator[self.currentFloor].setColor(LIGHT_OFF_COLOR)
if floorNumber >= 0:
if self.bldg.floorIndicator[floorNumber]:
self.bldg.floorIndicator[floorNumber].setColor(LIGHT_ON_COLOR)
self.currentFloor = floorNumber
def handleEnterSphere(self, collEntry):
self.cr.playGame.getPlace().detectedElevatorCollision(self)
def handleEnterElevator(self):
if base.localAvatar.hp > 0:
toon = base.localAvatar
self.sendUpdate('requestBoard', [])
else:
self.notify.warning('Tried to board elevator with hp: %d' % base.localAvatar.hp)
def enterWaitEmpty(self, ts):
self.lastState = self.state
self.elevatorSphereNodePath.unstash()
self.forceDoorsOpen()
self.accept(self.uniqueName('enterelevatorSphere'), self.handleEnterSphere)
self.accept(self.uniqueName('enterElevatorOK'), self.handleEnterElevator)
DistributedElevatorFSM.DistributedElevatorFSM.enterWaitEmpty(self, ts)
def exitWaitEmpty(self):
self.lastState = self.state
self.elevatorSphereNodePath.stash()
self.ignore(self.uniqueName('enterelevatorSphere'))
self.ignore(self.uniqueName('enterElevatorOK'))
DistributedElevatorFSM.DistributedElevatorFSM.exitWaitEmpty(self)
def enterWaitCountdown(self, ts):
self.lastState = self.state
DistributedElevatorFSM.DistributedElevatorFSM.enterWaitCountdown(self, ts)
self.forceDoorsOpen()
self.accept(self.uniqueName('enterElevatorOK'), self.handleEnterElevator)
self.startCountdownClock(self.countdownTime, ts)
def exitWaitCountdown(self):
self.lastState = self.state
self.ignore(self.uniqueName('enterElevatorOK'))
DistributedElevatorFSM.DistributedElevatorFSM.exitWaitCountdown(self)
def enterClosing(self, ts):
self.lastState = self.state
taskMgr.doMethodLater(1.0, self._delayIris, 'delayedIris')
DistributedElevatorFSM.DistributedElevatorFSM.enterClosing(self, ts)
def _delayIris(self, tskfooler = 0):
base.transitions.irisOut(1.0)
base.localAvatar.pauseGlitchKiller()
return Task.done
def kickToonsOut(self):
if not self.localToonOnBoard:
zoneId = self.cr.playGame.hood.hoodId
self.cr.playGame.getPlace().fsm.request('teleportOut', [{'loader': ZoneUtil.getLoaderName(zoneId),
'where': ZoneUtil.getToonWhereName(zoneId),
'how': 'teleportIn',
'hoodId': zoneId,
'zoneId': zoneId,
'shardId': None,
'avId': -1}])
return
def exitClosing(self):
self.lastState = self.state
DistributedElevatorFSM.DistributedElevatorFSM.exitClosing(self)
def enterClosed(self, ts):
self.lastState = self.state
self.forceDoorsClosed()
self.__doorsClosed(self.getZoneId())
def exitClosed(self):
self.lastState = self.state
DistributedElevatorFSM.DistributedElevatorFSM.exitClosed(self)
def enterOff(self):
self.lastState = self.state
if self.wantState == 'closed':
self.demand('Closing')
elif self.wantState == 'waitEmpty':
self.demand('WaitEmpty')
DistributedElevatorFSM.DistributedElevatorFSM.enterOff(self)
def exitOff(self):
self.lastState = self.state
DistributedElevatorFSM.DistributedElevatorFSM.exitOff(self)
def enterOpening(self, ts):
self.lastState = self.state
DistributedElevatorFSM.DistributedElevatorFSM.enterOpening(self, ts)
def exitOpening(self):
DistributedElevatorFSM.DistributedElevatorFSM.exitOpening(self)
self.kickEveryoneOut()
def getZoneId(self):
return 0
def setBldgDoId(self, bldgDoId):
self.bldg = None
self.setupElevatorKart()
return
def setupElevatorKart(self):
collisionRadius = ElevatorConstants.ElevatorData[self.type]['collRadius']
self.elevatorSphere = CollisionSphere(0, 0, 0, collisionRadius)
self.elevatorSphere.setTangible(1)
self.elevatorSphereNode = CollisionNode(self.uniqueName('elevatorSphere'))
self.elevatorSphereNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
self.elevatorSphereNode.addSolid(self.elevatorSphere)
self.elevatorSphereNodePath = self.getElevatorModel().attachNewNode(self.elevatorSphereNode)
self.elevatorSphereNodePath.hide()
self.elevatorSphereNodePath.reparentTo(self.getElevatorModel())
self.elevatorSphereNodePath.stash()
self.boardedAvIds = {}
self.finishSetup()
def getElevatorModel(self):
return self.elevatorModel
def kickEveryoneOut(self):
bailFlag = 0
for avId, slot in self.boardedAvIds.items():
self.emptySlot(slot, avId, bailFlag, globalClockDelta.getRealNetworkTime())
if avId == base.localAvatar.doId:
pass
def __doorsClosed(self, zoneId):
pass
def onDoorCloseFinish(self):
pass
def setLocked(self, locked):
self.isLocked = locked
if locked:
if self.state == 'WaitEmpty':
self.request('Closing')
if self.countFullSeats() == 0:
self.wantState = 'closed'
else:
self.wantState = 'opening'
else:
self.wantState = 'waitEmpty'
if self.state == 'Closed':
self.request('Opening')
def getLocked(self):
return self.isLocked
def setEntering(self, entering):
self.isEntering = entering
def getEntering(self):
return self.isEntering
def forceDoorsOpen(self):
pass
def forceDoorsClosed(self):
pass
def enterOff(self):
self.lastState = self.state
def exitOff(self):
pass
def setLawOfficeInteriorZone(self, zoneId):
if self.localToonOnBoard:
hoodId = self.cr.playGame.hood.hoodId
doneStatus = {'loader': 'cogHQLoader',
'where': 'factoryInterior',
'how': 'teleportIn',
'zoneId': zoneId,
'hoodId': hoodId}
self.cr.playGame.getPlace().elevator.signalDone(doneStatus)
def getElevatorModel(self):
return self.golfKart
def setPosHpr(self, x, y, z, h, p, r):
self.startingPos = Vec3(x, y, z)
self.enteringPos = Vec3(x, y, z - 10)
self.startingHpr = Vec3(h, 0, 0)
self.golfKart.setPosHpr(x, y, z, h, 0, 0)
def fillSlot(self, index, avId):
self.notify.debug('%s.fillSlot(%s, %s, ...)' % (self.doId, index, avId))
request = self.toonRequests.get(index)
if request:
self.cr.relatedObjectMgr.abortRequest(request)
del self.toonRequests[index]
if avId == 0:
pass
elif not self.cr.doId2do.has_key(avId):
func = PythonUtil.Functor(self.gotToon, index, avId)
self.toonRequests[index] = self.cr.relatedObjectMgr.requestObjects([avId], allCallback=func)
elif not self.isSetup:
self.deferredSlots.append((index, avId))
else:
if avId == base.localAvatar.getDoId():
self.localToonOnBoard = 1
elevator = self.getPlaceElevator()
elevator.fsm.request('boarding', [self.getElevatorModel()])
elevator.fsm.request('boarded')
toon = self.cr.doId2do[avId]
toon.stopSmooth()
toon.wrtReparentTo(self.golfKart)
sitStartDuration = toon.getDuration('sit-start')
jumpTrack = self.generateToonJumpTrack(toon, index)
track = Sequence(jumpTrack, Func(toon.setAnimState, 'Sit', 1.0), Func(self.clearToonTrack, avId), name=toon.uniqueName('fillElevator'), autoPause=1)
track.delayDelete = DelayDelete.DelayDelete(toon, 'fillSlot')
self.storeToonTrack(avId, track)
track.start()
self.boardedAvIds[avId] = None
return
def generateToonJumpTrack(self, av, seatIndex):
av.pose('sit', 47)
hipOffset = av.getHipsParts()[2].getPos(av)
def getToonJumpTrack(av, seatIndex):
def getJumpDest(av = av, node = self.golfKart):
dest = Point3(0, 0, 0)
if hasattr(self, 'golfKart') and self.golfKart:
dest = Vec3(self.golfKart.getPos(av.getParent()))
seatNode = self.golfKart.find('**/seat' + str(seatIndex + 1))
dest += seatNode.getPos(self.golfKart)
dna = av.getStyle()
dest -= hipOffset
if seatIndex < 2:
dest.setY(dest.getY() + 2 * hipOffset.getY())
dest.setZ(dest.getZ() + 0.1)
else:
self.notify.warning('getJumpDestinvalid golfKart, returning (0,0,0)')
return dest
def getJumpHpr(av = av, node = self.golfKart):
hpr = Point3(0, 0, 0)
if hasattr(self, 'golfKart') and self.golfKart:
hpr = self.golfKart.getHpr(av.getParent())
if seatIndex < 2:
hpr.setX(hpr.getX() + 180)
else:
hpr.setX(hpr.getX())
angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX())
hpr.setX(angle)
else:
self.notify.warning('getJumpHpr invalid golfKart, returning (0,0,0)')
return hpr
toonJumpTrack = Parallel(ActorInterval(av, 'jump'), Sequence(Wait(0.43), Parallel(LerpHprInterval(av, hpr=getJumpHpr, duration=0.9), ProjectileInterval(av, endPos=getJumpDest, duration=0.9))))
return toonJumpTrack
def getToonSitTrack(av):
toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit'))
return toonSitTrack
toonJumpTrack = getToonJumpTrack(av, seatIndex)
toonSitTrack = getToonSitTrack(av)
jumpTrack = Sequence(Parallel(toonJumpTrack, Sequence(Wait(1), toonSitTrack)), Func(av.wrtReparentTo, self.golfKart))
return jumpTrack
def emptySlot(self, index, avId, bailFlag, timestamp):
if avId == 0:
pass
elif not self.isSetup:
newSlots = []
for slot in self.deferredSlots:
if slot[0] != index:
newSlots.append(slot)
self.deferredSlots = newSlots
elif self.cr.doId2do.has_key(avId):
if bailFlag == 1 and hasattr(self, 'clockNode'):
if timestamp < self.countdownTime and timestamp >= 0:
self.countdown(self.countdownTime - timestamp)
else:
self.countdown(self.countdownTime)
toon = self.cr.doId2do[avId]
toon.stopSmooth()
sitStartDuration = toon.getDuration('sit-start')
jumpOutTrack = self.generateToonReverseJumpTrack(toon, index)
track = Sequence(jumpOutTrack, Func(self.clearToonTrack, avId), Func(self.notifyToonOffElevator, toon), name=toon.uniqueName('emptyElevator'), autoPause=1)
track.delayDelete = DelayDelete.DelayDelete(toon, 'ClubElevator.emptySlot')
self.storeToonTrack(avId, track)
track.start()
if avId == base.localAvatar.getDoId():
messenger.send('exitElevator')
if avId in self.boardedAvIds:
del self.boardedAvIds[avId]
else:
self.notify.warning('toon: ' + str(avId) + " doesn't exist, and" + ' cannot exit the elevator!')
def generateToonReverseJumpTrack(self, av, seatIndex):
self.notify.debug('av.getH() = %s' % av.getH())
def getToonJumpTrack(av, destNode):
def getJumpDest(av = av, node = destNode):
dest = node.getPos(av.getParent())
dest += Vec3(*self.JumpOutOffsets[seatIndex])
return dest
def getJumpHpr(av = av, node = destNode):
hpr = node.getHpr(av.getParent())
hpr.setX(hpr.getX() + 180)
angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX())
hpr.setX(angle)
return hpr
toonJumpTrack = Parallel(ActorInterval(av, 'jump'), Sequence(Wait(0.1), Parallel(ProjectileInterval(av, endPos=getJumpDest, duration=0.9))))
return toonJumpTrack
toonJumpTrack = getToonJumpTrack(av, self.golfKart)
jumpTrack = Sequence(toonJumpTrack, Func(av.loop, 'neutral'), Func(av.wrtReparentTo, render))
return jumpTrack
def startCountdownClock(self, countdownTime, ts):
DistributedElevatorFSM.DistributedElevatorFSM.startCountdownClock(self, countdownTime, ts)
self.clock.setH(self.clock.getH() + 180)
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()
if self.__toonTracks.get(avId):
DelayDelete.cleanupDelayDeletes(self.__toonTracks[avId])
del self.__toonTracks[avId]
def clearToonTracks(self):
keyList = []
for key in self.__toonTracks:
keyList.append(key)
for key in keyList:
if self.__toonTracks.has_key(key):
self.clearToonTrack(key)