toontown-just-works/toontown/coghq/DistributedLift.py
2024-07-07 18:08:39 -05:00

202 lines
7.6 KiB
Python

from panda3d.core import *
from direct.distributed.ClockDelta import *
from direct.interval.IntervalGlobal import *
from otp.level import BasicEntities
from direct.directnotify import DirectNotifyGlobal
from direct.fsm import ClassicFSM, State
from direct.fsm import State
import LiftConstants
import MovingPlatform
class DistributedLift(BasicEntities.DistributedNodePathEntity):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLift')
def __init__(self, cr):
BasicEntities.DistributedNodePathEntity.__init__(self, cr)
def generateInit(self):
self.notify.debug('generateInit')
BasicEntities.DistributedNodePathEntity.generateInit(self)
self.moveSnd = base.loadSfx('phase_9/audio/sfx/CHQ_FACT_elevator_up_down.ogg')
self.fsm = ClassicFSM.ClassicFSM('DistributedLift', [State.State('off', self.enterOff, self.exitOff, ['moving']), State.State('moving', self.enterMoving, self.exitMoving, ['waiting']), State.State('waiting', self.enterWaiting, self.exitWaiting, ['moving'])], 'off', 'off')
self.fsm.enterInitialState()
def generate(self):
self.notify.debug('generate')
BasicEntities.DistributedNodePathEntity.generate(self)
self.platform = self.attachNewNode('platParent')
def setStateTransition(self, toState, fromState, arrivalTimestamp):
self.notify.debug('setStateTransition: %s->%s' % (fromState, toState))
if not self.isGenerated():
self.initialState = toState
self.initialFromState = fromState
self.initialStateTimestamp = arrivalTimestamp
else:
self.fsm.request('moving', [toState, fromState, arrivalTimestamp])
def announceGenerate(self):
self.notify.debug('announceGenerate')
BasicEntities.DistributedNodePathEntity.announceGenerate(self)
self.initPlatform()
self.state = None
self.fsm.request('moving', [self.initialState, self.initialFromState, self.initialStateTimestamp])
del self.initialState
del self.initialStateTimestamp
return
def disable(self):
self.notify.debug('disable')
self.ignoreAll()
self.fsm.requestFinalState()
BasicEntities.DistributedNodePathEntity.disable(self)
def delete(self):
self.notify.debug('delete')
del self.moveSnd
del self.fsm
self.destroyPlatform()
self.platform.removeNode()
del self.platform
BasicEntities.DistributedNodePathEntity.delete(self)
def initPlatform(self):
model = loader.loadModel(self.modelPath)
if model is None:
return
model.setScale(self.modelScale)
if self.floorName is None:
return
self.platformModel = MovingPlatform.MovingPlatform()
self.platformModel.setupCopyModel(self.getParentToken(), model, self.floorName)
self.accept(self.platformModel.getEnterEvent(), self.localToonEntered)
self.accept(self.platformModel.getExitEvent(), self.localToonLeft)
self.startGuard = None
self.endGuard = None
zoneNp = self.getZoneNode()
if len(self.startGuardName):
self.startGuard = zoneNp.find('**/%s' % self.startGuardName)
if len(self.endGuardName):
self.endGuard = zoneNp.find('**/%s' % self.endGuardName)
side2srch = {'front': '**/wall_front',
'back': '**/wall_back',
'left': '**/wall_left',
'right': '**/wall_right'}
for side in side2srch.values():
np = self.platformModel.find(side)
if not np.isEmpty():
np.setScale(1.0, 1.0, 2.0)
np.setZ(-10)
np.flattenLight()
self.startBoardColl = NodePathCollection()
self.endBoardColl = NodePathCollection()
for side in self.startBoardSides:
np = self.platformModel.find(side2srch[side])
if np.isEmpty():
DistributedLift.warning("couldn't find %s board collision" % side)
else:
self.startBoardColl.addPath(np)
for side in self.endBoardSides:
np = self.platformModel.find(side2srch[side])
if np.isEmpty():
DistributedLift.warning("couldn't find %s board collision" % side)
else:
self.endBoardColl.addPath(np)
self.platformModel.reparentTo(self.platform)
return
def destroyPlatform(self):
if hasattr(self, 'platformModel'):
self.ignore(self.platformModel.getEnterEvent())
self.ignore(self.platformModel.getExitEvent())
self.platformModel.destroy()
del self.platformModel
if self.startGuard is not None:
self.startGuard.unstash()
if self.endGuard is not None:
self.endGuard.unstash()
del self.startGuard
del self.endGuard
del self.startBoardColl
del self.endBoardColl
return
def localToonEntered(self):
self.sendUpdate('setAvatarEnter')
def localToonLeft(self):
self.sendUpdate('setAvatarLeave')
def enterOff(self):
self.notify.debug('enterOff')
def exitOff(self):
pass
def getPosition(self, state):
if state is LiftConstants.Down:
return self.startPos
else:
return self.endPos
def getGuard(self, state):
if state is LiftConstants.Down:
return self.startGuard
else:
return self.endGuard
def getBoardColl(self, state):
if state is LiftConstants.Down:
return self.startBoardColl
else:
return self.endBoardColl
def enterMoving(self, toState, fromState, arrivalTimestamp):
self.notify.debug('enterMoving, %s->%s' % (fromState, toState))
if self.state == toState:
self.notify.warning('already in state %s' % toState)
startPos = self.getPosition(fromState)
endPos = self.getPosition(toState)
startGuard = self.getGuard(fromState)
endGuard = self.getGuard(toState)
startBoardColl = self.getBoardColl(fromState)
endBoardColl = self.getBoardColl(toState)
def startMoving(self = self, guard = startGuard, boardColl = startBoardColl):
if guard is not None and not guard.isEmpty():
guard.unstash()
boardColl.unstash()
self.soundIval = SoundInterval(self.moveSnd, node=self.platform)
self.soundIval.loop()
return
def doneMoving(self = self, guard = endGuard, boardColl = endBoardColl, newState = toState):
self.state = newState
if hasattr(self, 'soundIval'):
self.soundIval.pause()
del self.soundIval
if guard is not None and not guard.isEmpty():
guard.stash()
boardColl.stash()
self.fsm.request('waiting')
return
self.moveIval = Sequence(Func(startMoving), LerpPosInterval(self.platform, self.duration, endPos, startPos=startPos, blendType='easeInOut', name='lift-%s-move' % self.entId, fluid=1), Func(doneMoving))
ivalStartT = globalClockDelta.networkToLocalTime(arrivalTimestamp, bits=32) - self.moveIval.getDuration()
self.moveIval.start(globalClock.getFrameTime() - ivalStartT)
def exitMoving(self):
if hasattr(self, 'soundIval'):
self.soundIval.pause()
del self.soundIval
self.moveIval.pause()
del self.moveIval
def enterWaiting(self):
self.notify.debug('enterWaiting')
def exitWaiting(self):
pass