127 lines
4.9 KiB
Python
127 lines
4.9 KiB
Python
from direct.distributed.ClockDelta import *
|
|
from otp.level import DistributedEntityAI
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from direct.task import Task
|
|
from direct.fsm import ClassicFSM, State
|
|
from direct.fsm import State
|
|
import LiftConstants
|
|
|
|
class DistributedLiftAI(DistributedEntityAI.DistributedEntityAI):
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLiftAI')
|
|
|
|
def __init__(self, level, entId, initialState = LiftConstants.Down):
|
|
DistributedEntityAI.DistributedEntityAI.__init__(self, level, entId)
|
|
self.name = 'Lift%s:%s' % (self.levelDoId, self.entId)
|
|
self.startMoveTaskName = '%s-StartMove' % self.name
|
|
self.moveDoneTaskName = '%s-MoveDone' % self.name
|
|
self.state = initialState
|
|
self.fromState = initialState
|
|
self.stateTimestamp = globalClock.getFrameTime()
|
|
self.boardedAvs = []
|
|
|
|
def generate(self):
|
|
self.notify.debug('generate')
|
|
DistributedEntityAI.DistributedEntityAI.generate(self)
|
|
self.fsm = ClassicFSM.ClassicFSM('DistributedLiftAI', [State.State('off', self.enterOff, self.exitOff, ['waiting']), State.State('waiting', self.enterWaiting, self.exitWaiting, ['moving', 'waiting']), State.State('moving', self.enterMoving, self.exitMoving, ['waiting'])], 'off', 'off')
|
|
self.fsm.enterInitialState()
|
|
self.fsm.request('waiting')
|
|
|
|
def delete(self):
|
|
self.notify.debug('delete')
|
|
DistributedEntityAI.DistributedEntityAI.delete(self)
|
|
self.ignoreAll()
|
|
taskMgr.remove(self.startMoveTaskName)
|
|
taskMgr.remove(self.moveDoneTaskName)
|
|
del self.fsm
|
|
|
|
def b_setStateTransition(self, toState, fromState, arrivalTimestamp):
|
|
self.d_setStateTransition(toState, fromState, arrivalTimestamp)
|
|
self.setStateTransition(toState, fromState, arrivalTimestamp)
|
|
|
|
def d_setStateTransition(self, toState, fromState, arrivalTimestamp):
|
|
self.sendUpdate('setStateTransition', [toState, fromState, arrivalTimestamp])
|
|
|
|
def setStateTransition(self, toState, fromState, arrivalTimestamp):
|
|
self.state = toState
|
|
self.fromState = fromState
|
|
self.stateTimestamp = arrivalTimestamp
|
|
|
|
def getStateTransition(self):
|
|
return (self.state, self.fromState, self.stateTimestamp)
|
|
|
|
def setAvatarEnter(self):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
avatar = self.air.doId2do.get(avId)
|
|
if not avatar:
|
|
self.air.writeServerEvent('suspicious', avId, 'LiftAI.setAvatarEnter avId not valid')
|
|
return
|
|
self.notify.debug('setAvatarEnter: %s' % avId)
|
|
if avId in self.boardedAvs:
|
|
self.notify.warning('avatar %s already in list' % avId)
|
|
else:
|
|
self.boardedAvs.append(avId)
|
|
|
|
def handleExitedAvatar(self = self, avId = avId):
|
|
self.notify.debug('avatar %s exited' % avId)
|
|
self.avatarLeft(avId)
|
|
|
|
self.acceptOnce(self.air.getAvatarExitEvent(avId), handleExitedAvatar)
|
|
self.setMoveLater(self.moveDelay)
|
|
|
|
def setAvatarLeave(self):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
self.notify.debug('setAvatarLeave: %s' % avId)
|
|
self.avatarLeft(avId)
|
|
|
|
def avatarLeft(self, avId):
|
|
if avId in self.boardedAvs:
|
|
self.boardedAvs.remove(avId)
|
|
self.ignore(self.air.getAvatarExitEvent(avId))
|
|
if len(self.boardedAvs) == 0:
|
|
if self.fsm.getCurrentState().getName() == 'waiting':
|
|
self.fsm.request('waiting')
|
|
else:
|
|
self.notify.warning('avatar %s tried to leave, but is not in list' % avId)
|
|
|
|
def setMoveLater(self, delay):
|
|
|
|
def startMoving(task, self = self):
|
|
targetState = LiftConstants.oppositeState(self.state)
|
|
self.fsm.request('moving', [targetState])
|
|
return Task.done
|
|
|
|
self.cancelMoveLater()
|
|
taskMgr.doMethodLater(delay, startMoving, self.startMoveTaskName)
|
|
|
|
def cancelMoveLater(self):
|
|
taskMgr.remove(self.startMoveTaskName)
|
|
|
|
def enterOff(self):
|
|
self.notify.debug('enterOff')
|
|
|
|
def exitOff(self):
|
|
pass
|
|
|
|
def enterWaiting(self):
|
|
self.notify.debug('enterWaiting')
|
|
self.setMoveLater(self.autoMoveDelay)
|
|
|
|
def exitWaiting(self):
|
|
self.cancelMoveLater()
|
|
|
|
def enterMoving(self, targetState):
|
|
self.notify.debug('enterMoving, target=%s' % targetState)
|
|
if self.state == targetState:
|
|
self.notify.warning('already in state %s' % targetState)
|
|
return
|
|
arriveDelay = 1.0 + self.duration
|
|
self.b_setStateTransition(targetState, self.state, globalClockDelta.localToNetworkTime(globalClock.getFrameTime() + arriveDelay, bits=32))
|
|
|
|
def doneMoving(task, self = self):
|
|
self.fsm.request('waiting')
|
|
return Task.done
|
|
|
|
taskMgr.doMethodLater(arriveDelay, doneMoving, self.moveDoneTaskName)
|
|
|
|
def exitMoving(self):
|
|
pass
|