mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-11-01 01:07:54 +00:00
696 lines
28 KiB
Python
696 lines
28 KiB
Python
|
import DoorTypes
|
||
|
import FADoorCodes
|
||
|
from direct.directnotify import DirectNotifyGlobal
|
||
|
from direct.distributed import DistributedObject
|
||
|
from direct.distributed.ClockDelta import *
|
||
|
from direct.fsm import ClassicFSM, State
|
||
|
from direct.interval.IntervalGlobal import *
|
||
|
from direct.task.Task import Task
|
||
|
from pandac.PandaModules import *
|
||
|
from toontown.distributed import DelayDelete
|
||
|
from toontown.distributed.DelayDeletable import DelayDeletable
|
||
|
from toontown.hood import ZoneUtil
|
||
|
from toontown.suit import Suit
|
||
|
from toontown.toonbase.ToonBaseGlobal import *
|
||
|
from toontown.toontowngui import TTDialog
|
||
|
from toontown.toontowngui import TeaserPanel
|
||
|
from toontown.nametag.NametagGroup import NametagGroup
|
||
|
from toontown.nametag.Nametag import Nametag
|
||
|
|
||
|
|
||
|
class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
|
||
|
def __init__(self, cr):
|
||
|
DistributedObject.DistributedObject.__init__(self, cr)
|
||
|
self.openSfx = base.loadSfx('phase_3.5/audio/sfx/Door_Open_1.ogg')
|
||
|
self.closeSfx = base.loadSfx('phase_3.5/audio/sfx/Door_Close_1.ogg')
|
||
|
self.nametag = None
|
||
|
self.fsm = ClassicFSM.ClassicFSM(
|
||
|
'DistributedDoor_right',
|
||
|
[
|
||
|
State.State('off', self.enterOff, self.exitOff,
|
||
|
['closing', 'closed', 'opening', 'open']),
|
||
|
State.State('closing', self.enterClosing, self.exitClosing,
|
||
|
['closed', 'opening']),
|
||
|
State.State('closed', self.enterClosed, self.exitClosed,
|
||
|
['opening']),
|
||
|
State.State('opening', self.enterOpening, self.exitOpening,
|
||
|
['open']),
|
||
|
State.State('open', self.enterOpen, self.exitOpen,
|
||
|
['closing', 'open'])
|
||
|
], 'off', 'off')
|
||
|
self.fsm.enterInitialState()
|
||
|
self.exitDoorFSM = ClassicFSM.ClassicFSM(
|
||
|
'DistributedDoor_left',
|
||
|
[
|
||
|
State.State('off', self.exitDoorEnterOff, self.exitDoorExitOff,
|
||
|
['closing', 'closed', 'opening', 'open']),
|
||
|
State.State('closing', self.exitDoorEnterClosing, self.exitDoorExitClosing,
|
||
|
['closed', 'opening']),
|
||
|
State.State('closed', self.exitDoorEnterClosed, self.exitDoorExitClosed,
|
||
|
['opening']),
|
||
|
State.State('opening', self.exitDoorEnterOpening, self.exitDoorExitOpening,
|
||
|
['open']),
|
||
|
State.State('open', self.exitDoorEnterOpen, self.exitDoorExitOpen,
|
||
|
['closing', 'open'])
|
||
|
], 'off', 'off')
|
||
|
self.exitDoorFSM.enterInitialState()
|
||
|
self.specialDoorTypes = {
|
||
|
DoorTypes.EXT_HQ: 0,
|
||
|
DoorTypes.EXT_COGHQ: 0,
|
||
|
DoorTypes.INT_COGHQ: 0,
|
||
|
DoorTypes.EXT_KS: 0,
|
||
|
DoorTypes.INT_KS: 0 }
|
||
|
self.doorX = 1.5
|
||
|
|
||
|
def generate(self):
|
||
|
DistributedObject.DistributedObject.generate(self)
|
||
|
self.avatarTracks = []
|
||
|
self.avatarExitTracks = []
|
||
|
self.avatarIDList = []
|
||
|
self.avatarExitIDList = []
|
||
|
self.doorTrack = None
|
||
|
self.doorExitTrack = None
|
||
|
|
||
|
def disable(self):
|
||
|
self.clearNametag()
|
||
|
taskMgr.remove(self.checkIsDoorHitTaskName())
|
||
|
self.ignore(self.getEnterTriggerEvent())
|
||
|
self.ignore(self.getExitTriggerEvent())
|
||
|
self.ignore('clearOutToonInterior')
|
||
|
self.fsm.request('off')
|
||
|
self.exitDoorFSM.request('off')
|
||
|
if hasattr(self, 'building'):
|
||
|
del self.building
|
||
|
self.finishAllTracks()
|
||
|
self.avatarIDList = []
|
||
|
self.avatarExitIDList = []
|
||
|
if hasattr(self, 'tempDoorNodePath'):
|
||
|
self.tempDoorNodePath.removeNode()
|
||
|
del self.tempDoorNodePath
|
||
|
DistributedObject.DistributedObject.disable(self)
|
||
|
|
||
|
def delete(self):
|
||
|
del self.fsm
|
||
|
del self.exitDoorFSM
|
||
|
del self.openSfx
|
||
|
del self.closeSfx
|
||
|
DistributedObject.DistributedObject.delete(self)
|
||
|
|
||
|
def wantsNametag(self):
|
||
|
return not ZoneUtil.isInterior(self.zoneId)
|
||
|
|
||
|
def setupNametag(self):
|
||
|
if not self.wantsNametag():
|
||
|
return
|
||
|
if self.doorIndex != 0:
|
||
|
return
|
||
|
if self.nametag == None:
|
||
|
self.nametag = NametagGroup()
|
||
|
self.nametag.setNametag3d(None)
|
||
|
self.nametag.setFont(ToontownGlobals.getBuildingNametagFont())
|
||
|
if TTLocalizer.BuildingNametagShadow:
|
||
|
self.nametag.setShadow(*TTLocalizer.BuildingNametagShadow)
|
||
|
self.nametag.hideChat()
|
||
|
self.nametag.hideThought()
|
||
|
nametagColor = NametagGlobals.NametagColors[NametagGlobals.CCToonBuilding]
|
||
|
self.nametag.setNametagColor(nametagColor)
|
||
|
self.nametag.setActive(False)
|
||
|
self.nametag.setAvatar(self.getDoorNodePath())
|
||
|
name = self.cr.playGame.dnaStore.getTitleFromBlockNumber(self.block)
|
||
|
self.nametag.setText(name)
|
||
|
self.nametag.manage(base.marginManager)
|
||
|
self.nametag.updateAll()
|
||
|
|
||
|
def clearNametag(self):
|
||
|
if self.nametag is not None:
|
||
|
self.nametag.unmanage(base.marginManager)
|
||
|
self.nametag.setAvatar(NodePath())
|
||
|
self.nametag = None
|
||
|
|
||
|
def getTriggerName(self):
|
||
|
if (self.doorType == DoorTypes.INT_HQ) or (self.doorType in self.specialDoorTypes):
|
||
|
return 'door_trigger_' + str(self.block) + '_' + str(self.doorIndex)
|
||
|
else:
|
||
|
return 'door_trigger_' + str(self.block)
|
||
|
|
||
|
def getTriggerName_wip(self):
|
||
|
name = 'door_trigger_%d' % (self.doId,)
|
||
|
return name
|
||
|
|
||
|
def getEnterTriggerEvent(self):
|
||
|
return 'enter' + self.getTriggerName()
|
||
|
|
||
|
def getExitTriggerEvent(self):
|
||
|
return 'exit' + self.getTriggerName()
|
||
|
|
||
|
def hideDoorParts(self):
|
||
|
if self.doorType in self.specialDoorTypes:
|
||
|
self.hideIfHasFlat(self.findDoorNode('rightDoor'))
|
||
|
self.hideIfHasFlat(self.findDoorNode('leftDoor'))
|
||
|
try:
|
||
|
self.findDoorNode('doorFrameHoleRight').hide()
|
||
|
self.findDoorNode('doorFrameHoleLeft').hide()
|
||
|
except:
|
||
|
pass
|
||
|
|
||
|
def setTriggerName(self):
|
||
|
if self.doorType in self.specialDoorTypes:
|
||
|
building = self.getBuilding()
|
||
|
doorTrigger = building.find('**/door_' + str(self.doorIndex) + '/**/door_trigger*')
|
||
|
try:
|
||
|
doorTrigger.node().setName(self.getTriggerName())
|
||
|
except:
|
||
|
pass
|
||
|
|
||
|
def setTriggerName_wip(self):
|
||
|
building = self.getBuilding()
|
||
|
doorTrigger = building.find('**/door_%d/**/door_trigger_%d' % (self.doorIndex, self.block))
|
||
|
if doorTrigger.isEmpty():
|
||
|
doorTrigger = building.find('**/door_trigger_%d' % (self.block,))
|
||
|
if doorTrigger.isEmpty():
|
||
|
doorTrigger = building.find('**/door_%d/**/door_trigger_*' % (self.doorIndex,))
|
||
|
if doorTrigger.isEmpty():
|
||
|
doorTrigger = building.find('**/door_trigger_*')
|
||
|
doorTrigger.node().setName(self.getTriggerName())
|
||
|
|
||
|
def setZoneIdAndBlock(self, zoneId, block):
|
||
|
self.zoneId = zoneId
|
||
|
self.block = block
|
||
|
|
||
|
def setDoorType(self, doorType):
|
||
|
self.notify.debug('Door type = ' + str(doorType) + ' on door #' + str(self.doId))
|
||
|
self.doorType = doorType
|
||
|
|
||
|
def setDoorIndex(self, doorIndex):
|
||
|
self.doorIndex = doorIndex
|
||
|
|
||
|
def setSwing(self, flags):
|
||
|
self.leftSwing = flags & 1 != 0
|
||
|
self.rightSwing = flags & 2 != 0
|
||
|
|
||
|
def setOtherZoneIdAndDoId(self, zoneId, distributedObjectID):
|
||
|
self.otherZoneId = zoneId
|
||
|
self.otherDoId = distributedObjectID
|
||
|
|
||
|
def setState(self, state, timestamp):
|
||
|
self.fsm.request(state, [globalClockDelta.localElapsedTime(timestamp)])
|
||
|
|
||
|
def setExitDoorState(self, state, timestamp):
|
||
|
self.exitDoorFSM.request(state, [globalClockDelta.localElapsedTime(timestamp)])
|
||
|
|
||
|
def announceGenerate(self):
|
||
|
DistributedObject.DistributedObject.announceGenerate(self)
|
||
|
self.doPostAnnounceGenerate()
|
||
|
|
||
|
def doPostAnnounceGenerate(self):
|
||
|
flatDoorTypes = [DoorTypes.INT_STANDARD, DoorTypes.INT_HQ]
|
||
|
if self.doorType in flatDoorTypes:
|
||
|
self.bHasFlat = True
|
||
|
else:
|
||
|
self.bHasFlat = not self.findDoorNode('door*flat', True).isEmpty()
|
||
|
self.hideDoorParts()
|
||
|
self.setTriggerName()
|
||
|
|
||
|
# Check if we are dealing with a DDL HQ door...
|
||
|
if self.doorType == DoorTypes.EXT_HQ and \
|
||
|
ZoneUtil.getHoodId(self.zoneId) == ToontownGlobals.DonaldsDreamland:
|
||
|
|
||
|
# Get the doorTrigger...
|
||
|
building = self.getBuilding()
|
||
|
doorTrigger = building.find('**/%s' % self.getTriggerName())
|
||
|
|
||
|
# Check if the doorTrigger hasn't been 'fixed' already...
|
||
|
if not doorTrigger.getTag('fixed'):
|
||
|
|
||
|
# Reposition the doorTrigger based on its index...
|
||
|
if self.doorIndex == 0:
|
||
|
doorTrigger.setY(doorTrigger, 0.25)
|
||
|
else:
|
||
|
doorTrigger.setY(doorTrigger, -0.25)
|
||
|
|
||
|
# We are done :) Tag the door as fixed.
|
||
|
doorTrigger.setTag('fixed', 'true')
|
||
|
|
||
|
self.accept(self.getEnterTriggerEvent(), self.doorTrigger)
|
||
|
self.acceptOnce('clearOutToonInterior', self.doorTrigger)
|
||
|
self.setupNametag()
|
||
|
|
||
|
def getBuilding(self):
|
||
|
if not hasattr(self, 'building'):
|
||
|
if self.doorType == DoorTypes.INT_STANDARD:
|
||
|
door = render.find('**/leftDoor;+s')
|
||
|
self.building = door.getParent()
|
||
|
elif self.doorType == DoorTypes.INT_HQ:
|
||
|
door = render.find('**/door_0')
|
||
|
self.building = door.getParent()
|
||
|
elif self.doorType == DoorTypes.INT_KS:
|
||
|
self.building = render.find('**/KartShop_Interior*')
|
||
|
elif self.doorType == DoorTypes.EXT_STANDARD or self.doorType == DoorTypes.EXT_HQ or self.doorType == DoorTypes.EXT_KS:
|
||
|
self.building = self.cr.playGame.hood.loader.geom.find('**/??' + str(self.block) + ':*_landmark_*_DNARoot;+s')
|
||
|
if self.building.isEmpty():
|
||
|
self.building = self.cr.playGame.hood.loader.geom.find('**/??' + str(self.block) + ':animated_building_*_DNARoot;+s')
|
||
|
elif self.doorType == DoorTypes.EXT_COGHQ or self.doorType == DoorTypes.INT_COGHQ:
|
||
|
self.building = self.cr.playGame.hood.loader.geom
|
||
|
else:
|
||
|
self.notify.error('No such door type as ' + str(self.doorType))
|
||
|
return self.building
|
||
|
|
||
|
def getBuilding_wip(self):
|
||
|
if not hasattr(self, 'building'):
|
||
|
if hasattr(self, 'block'):
|
||
|
self.building = self.cr.playGame.hood.loader.geom.find('**/??' + str(self.block) + ':*_landmark_*_DNARoot;+s')
|
||
|
else:
|
||
|
self.building = self.cr.playGame.hood.loader.geom
|
||
|
return self.building
|
||
|
|
||
|
def readyToExit(self):
|
||
|
base.transitions.fadeScreen(1.0)
|
||
|
self.sendUpdate('requestExit')
|
||
|
|
||
|
def avatarEnterDoorTrack(self, avatar, duration):
|
||
|
trackName = 'avatarEnterDoor-%d-%d' % (self.doId, avatar.doId)
|
||
|
track = Parallel(name = trackName)
|
||
|
otherNP = self.getDoorNodePath()
|
||
|
if hasattr(avatar, 'stopSmooth'):
|
||
|
avatar.stopSmooth()
|
||
|
if avatar.doId == base.localAvatar.doId:
|
||
|
track.append(LerpPosHprInterval(nodePath = camera, other = avatar, duration = duration, pos = Point3(0, -8, avatar.getHeight()), hpr = VBase3(0, 0, 0), blendType = 'easeInOut'))
|
||
|
finalPos = avatar.getParent().getRelativePoint(otherNP, Point3(self.doorX, 2, ToontownGlobals.FloorOffset))
|
||
|
moveHere = Sequence(self.getAnimStateInterval(avatar, 'walk'), LerpPosInterval(nodePath = avatar, duration = duration, pos = finalPos, blendType = 'easeIn'))
|
||
|
track.append(moveHere)
|
||
|
if avatar.doId == base.localAvatar.doId:
|
||
|
track.append(Sequence(Wait(duration * 0.5), Func(base.transitions.irisOut, duration * 0.5), Wait(duration * 0.5), Func(avatar.b_setParent, ToontownGlobals.SPHidden)))
|
||
|
track.delayDelete = DelayDelete.DelayDelete(avatar, 'avatarEnterDoorTrack')
|
||
|
return track
|
||
|
|
||
|
def avatarEnqueueTrack(self, avatar, duration):
|
||
|
if hasattr(avatar, 'stopSmooth'):
|
||
|
avatar.stopSmooth()
|
||
|
back = -5.0 - 2.0 * len(self.avatarIDList)
|
||
|
if back < -9.0:
|
||
|
back = -9.0
|
||
|
offset = Point3(self.doorX, back, ToontownGlobals.FloorOffset)
|
||
|
otherNP = self.getDoorNodePath()
|
||
|
walkLike = ActorInterval(avatar, 'walk', startTime = 1, duration = duration, endTime = 0.0001)
|
||
|
standHere = Sequence(LerpPosHprInterval(nodePath = avatar, other = otherNP, duration = duration, pos = offset, hpr = VBase3(0, 0, 0), blendType = 'easeInOut'), self.getAnimStateInterval(avatar, 'neutral'))
|
||
|
trackName = 'avatarEnqueueDoor-%d-%d' % (self.doId, avatar.doId)
|
||
|
track = Parallel(walkLike, standHere, name = trackName)
|
||
|
track.delayDelete = DelayDelete.DelayDelete(avatar, 'avatarEnqueueTrack')
|
||
|
return track
|
||
|
|
||
|
def getAnimStateInterval(self, avatar, animName):
|
||
|
isSuit = isinstance(avatar, Suit.Suit)
|
||
|
if isSuit:
|
||
|
return Func(avatar.loop, animName, 0)
|
||
|
else:
|
||
|
return Func(avatar.setAnimState, animName)
|
||
|
|
||
|
def isDoorHit(self):
|
||
|
vec = base.localAvatar.getRelativeVector(self.currentDoorNp, self.currentDoorVec)
|
||
|
netScale = self.currentDoorNp.getNetTransform().getScale()
|
||
|
yToTest = vec.getY() / netScale[1]
|
||
|
return yToTest
|
||
|
|
||
|
def enterDoor(self):
|
||
|
if self.allowedToEnter():
|
||
|
messenger.send('DistributedDoor_doorTrigger')
|
||
|
self.sendUpdate('requestEnter')
|
||
|
else:
|
||
|
place = base.cr.playGame.getPlace()
|
||
|
if place:
|
||
|
place.fsm.request('stopped')
|
||
|
self.dialog = TeaserPanel.TeaserPanel(pageName = 'otherHoods', doneFunc = self.handleOkTeaser)
|
||
|
|
||
|
def handleOkTeaser(self):
|
||
|
self.accept(self.getEnterTriggerEvent(), self.doorTrigger)
|
||
|
self.dialog.destroy()
|
||
|
del self.dialog
|
||
|
place = base.cr.playGame.getPlace()
|
||
|
if place:
|
||
|
place.fsm.request('walk')
|
||
|
|
||
|
def allowedToEnter(self):
|
||
|
if base.cr.isPaid():
|
||
|
return True
|
||
|
place = base.cr.playGame.getPlace()
|
||
|
myHoodId = ZoneUtil.getCanonicalHoodId(place.zoneId)
|
||
|
if hasattr(place, 'id'):
|
||
|
myHoodId = place.id
|
||
|
if myHoodId in (ToontownGlobals.ToontownCentral, ToontownGlobals.MyEstate, ToontownGlobals.GoofySpeedway, ToontownGlobals.Tutorial):
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
def checkIsDoorHitTaskName(self):
|
||
|
return 'checkIsDoorHit' + self.getTriggerName()
|
||
|
|
||
|
def checkIsDoorHitTask(self, task):
|
||
|
if self.isDoorHit():
|
||
|
self.ignore(self.checkIsDoorHitTaskName())
|
||
|
self.ignore(self.getExitTriggerEvent())
|
||
|
self.enterDoor()
|
||
|
return Task.done
|
||
|
return Task.cont
|
||
|
|
||
|
def cancelCheckIsDoorHitTask(self, args):
|
||
|
taskMgr.remove(self.checkIsDoorHitTaskName())
|
||
|
del self.currentDoorNp
|
||
|
del self.currentDoorVec
|
||
|
self.ignore(self.getExitTriggerEvent())
|
||
|
self.accept(self.getEnterTriggerEvent(), self.doorTrigger)
|
||
|
|
||
|
def doorTrigger(self, args=None):
|
||
|
self.ignore(self.getEnterTriggerEvent())
|
||
|
if args == None:
|
||
|
self.enterDoor()
|
||
|
else:
|
||
|
self.currentDoorNp = NodePath(args.getIntoNodePath())
|
||
|
self.currentDoorVec = Vec3(args.getSurfaceNormal(self.currentDoorNp))
|
||
|
if self.isDoorHit():
|
||
|
self.enterDoor()
|
||
|
else:
|
||
|
self.accept(self.getExitTriggerEvent(), self.cancelCheckIsDoorHitTask)
|
||
|
taskMgr.add(self.checkIsDoorHitTask, self.checkIsDoorHitTaskName())
|
||
|
|
||
|
def avatarEnter(self, avatarID):
|
||
|
avatar = self.cr.doId2do.get(avatarID, None)
|
||
|
if avatar:
|
||
|
avatar.setAnimState('neutral')
|
||
|
track = self.avatarEnqueueTrack(avatar, 0.5)
|
||
|
track.start()
|
||
|
self.avatarTracks.append(track)
|
||
|
self.avatarIDList.append(avatarID)
|
||
|
|
||
|
def rejectEnter(self, reason):
|
||
|
message = FADoorCodes.reasonDict[reason]
|
||
|
if message:
|
||
|
self.__faRejectEnter(message)
|
||
|
else:
|
||
|
self.__basicRejectEnter()
|
||
|
|
||
|
def __basicRejectEnter(self):
|
||
|
self.accept(self.getEnterTriggerEvent(), self.doorTrigger)
|
||
|
if self.cr.playGame.getPlace():
|
||
|
self.cr.playGame.getPlace().setState('walk')
|
||
|
|
||
|
def __faRejectEnter(self, message):
|
||
|
self.rejectDialog = TTDialog.TTGlobalDialog(message = message, doneEvent = 'doorRejectAck', style = TTDialog.Acknowledge)
|
||
|
self.rejectDialog.show()
|
||
|
self.rejectDialog.delayDelete = DelayDelete.DelayDelete(self, '__faRejectEnter')
|
||
|
event = 'clientCleanup'
|
||
|
self.acceptOnce(event, self.__handleClientCleanup)
|
||
|
base.cr.playGame.getPlace().setState('stopped')
|
||
|
self.acceptOnce('doorRejectAck', self.__handleRejectAck)
|
||
|
self.acceptOnce('stoppedAsleep', self.__handleFallAsleepDoor)
|
||
|
|
||
|
def __handleClientCleanup(self):
|
||
|
if hasattr(self, 'rejectDialog') and self.rejectDialog:
|
||
|
self.rejectDialog.doneStatus = 'ok'
|
||
|
self.__handleRejectAck()
|
||
|
|
||
|
def __handleFallAsleepDoor(self):
|
||
|
self.rejectDialog.doneStatus = 'ok'
|
||
|
self.__handleRejectAck()
|
||
|
|
||
|
def __handleRejectAck(self):
|
||
|
self.ignore('doorRejectAck')
|
||
|
self.ignore('stoppedAsleep')
|
||
|
self.ignore('clientCleanup')
|
||
|
doneStatus = self.rejectDialog.doneStatus
|
||
|
if doneStatus != 'ok':
|
||
|
self.notify.error('Unrecognized doneStatus: ' + str(doneStatus))
|
||
|
self.__basicRejectEnter()
|
||
|
self.rejectDialog.delayDelete.destroy()
|
||
|
self.rejectDialog.cleanup()
|
||
|
del self.rejectDialog
|
||
|
|
||
|
def getDoorNodePath(self):
|
||
|
if self.doorType == DoorTypes.INT_STANDARD:
|
||
|
otherNP = render.find('**/door_origin')
|
||
|
elif self.doorType == DoorTypes.EXT_STANDARD:
|
||
|
otherNP = self.getBuilding().find('**/*door_origin')
|
||
|
elif self.doorType in self.specialDoorTypes:
|
||
|
building = self.getBuilding()
|
||
|
otherNP = building.find('**/door_origin_' + str(self.doorIndex))
|
||
|
elif self.doorType == DoorTypes.INT_HQ:
|
||
|
otherNP = render.find('**/door_origin_' + str(self.doorIndex))
|
||
|
else:
|
||
|
self.notify.error('No such door type as ' + str(self.doorType))
|
||
|
return otherNP
|
||
|
|
||
|
def avatarExitTrack(self, avatar, duration):
|
||
|
if hasattr(avatar, 'stopSmooth'):
|
||
|
avatar.stopSmooth()
|
||
|
otherNP = self.getDoorNodePath()
|
||
|
trackName = 'avatarExitDoor-%d-%d' % (self.doId, avatar.doId)
|
||
|
track = Sequence(name=trackName)
|
||
|
track.append(self.getAnimStateInterval(avatar, 'walk'))
|
||
|
track.append(
|
||
|
PosHprInterval(
|
||
|
avatar, Point3(-self.doorX, 0, ToontownGlobals.FloorOffset),
|
||
|
VBase3(179, 0, 0), other=otherNP
|
||
|
)
|
||
|
)
|
||
|
track.append(Func(avatar.setParent, ToontownGlobals.SPRender))
|
||
|
if avatar.doId == base.localAvatar.doId:
|
||
|
track.append(
|
||
|
PosHprInterval(
|
||
|
camera, VBase3(-self.doorX, 5, avatar.getHeight()),
|
||
|
VBase3(180, 0, 0), other=otherNP
|
||
|
)
|
||
|
)
|
||
|
if avatar.doId == base.localAvatar.doId:
|
||
|
finalPos = render.getRelativePoint(
|
||
|
otherNP, Point3(-self.doorX, -6, ToontownGlobals.FloorOffset)
|
||
|
)
|
||
|
else:
|
||
|
finalPos = render.getRelativePoint(
|
||
|
otherNP, Point3(-self.doorX, -3, ToontownGlobals.FloorOffset)
|
||
|
)
|
||
|
track.append(
|
||
|
LerpPosInterval(
|
||
|
nodePath=avatar, duration=duration, pos=finalPos,
|
||
|
blendType='easeInOut'
|
||
|
)
|
||
|
)
|
||
|
if avatar.doId == base.localAvatar.doId:
|
||
|
track.append(Func(self.exitCompleted))
|
||
|
track.append(Func(base.transitions.irisIn))
|
||
|
if hasattr(avatar, 'startSmooth'):
|
||
|
track.append(Func(avatar.startSmooth))
|
||
|
track.delayDelete = DelayDelete.DelayDelete(avatar, 'DistributedDoor.avatarExitTrack')
|
||
|
return track
|
||
|
|
||
|
def exitCompleted(self):
|
||
|
base.localAvatar.setAnimState('neutral')
|
||
|
place = self.cr.playGame.getPlace()
|
||
|
if place:
|
||
|
place.setState('walk')
|
||
|
base.localAvatar.d_setParent(ToontownGlobals.SPRender)
|
||
|
|
||
|
def avatarExit(self, avatarID):
|
||
|
if avatarID in self.avatarIDList:
|
||
|
self.avatarIDList.remove(avatarID)
|
||
|
if avatarID == base.localAvatar.doId:
|
||
|
self.exitCompleted()
|
||
|
else:
|
||
|
self.avatarExitIDList.append(avatarID)
|
||
|
|
||
|
def finishDoorTrack(self):
|
||
|
if self.doorTrack:
|
||
|
self.doorTrack.finish()
|
||
|
self.doorTrack = None
|
||
|
|
||
|
def finishDoorExitTrack(self):
|
||
|
if self.doorExitTrack:
|
||
|
self.doorExitTrack.finish()
|
||
|
self.doorExitTrack = None
|
||
|
|
||
|
def finishAllTracks(self):
|
||
|
self.finishDoorTrack()
|
||
|
self.finishDoorExitTrack()
|
||
|
for t in self.avatarTracks:
|
||
|
t.finish()
|
||
|
DelayDelete.cleanupDelayDeletes(t)
|
||
|
self.avatarTracks = []
|
||
|
for t in self.avatarExitTracks:
|
||
|
t.finish()
|
||
|
DelayDelete.cleanupDelayDeletes(t)
|
||
|
self.avatarExitTracks = []
|
||
|
|
||
|
def enterOff(self):
|
||
|
pass
|
||
|
|
||
|
def exitOff(self):
|
||
|
pass
|
||
|
|
||
|
def getRequestStatus(self):
|
||
|
zoneId = self.otherZoneId
|
||
|
request = {
|
||
|
'loader': ZoneUtil.getBranchLoaderName(zoneId),
|
||
|
'where': ZoneUtil.getToonWhereName(zoneId),
|
||
|
'how': 'doorIn',
|
||
|
'hoodId': ZoneUtil.getHoodId(zoneId),
|
||
|
'zoneId': zoneId,
|
||
|
'shardId': None,
|
||
|
'avId': -1,
|
||
|
'allowRedirect': 0,
|
||
|
'doorDoId': self.otherDoId
|
||
|
}
|
||
|
return request
|
||
|
|
||
|
def enterClosing(self, ts):
|
||
|
doorFrameHoleRight = self.findDoorNode('doorFrameHoleRight')
|
||
|
if doorFrameHoleRight.isEmpty():
|
||
|
self.notify.warning('enterClosing(): did not find doorFrameHoleRight')
|
||
|
return
|
||
|
rightDoor = self.findDoorNode('rightDoor')
|
||
|
if rightDoor.isEmpty():
|
||
|
self.notify.warning('enterClosing(): did not find rightDoor')
|
||
|
return
|
||
|
otherNP = self.getDoorNodePath()
|
||
|
trackName = 'doorClose-%d' % self.doId
|
||
|
if self.rightSwing:
|
||
|
h = 100
|
||
|
else:
|
||
|
h = -100
|
||
|
self.finishDoorTrack()
|
||
|
self.doorTrack = Sequence(LerpHprInterval(nodePath = rightDoor, duration = 1.0, hpr = VBase3(0, 0, 0), startHpr = VBase3(h, 0, 0), other = otherNP, blendType = 'easeInOut'), Func(doorFrameHoleRight.hide), Func(self.hideIfHasFlat, rightDoor), SoundInterval(self.closeSfx, node = rightDoor), name = trackName)
|
||
|
self.doorTrack.start(ts)
|
||
|
if hasattr(self, 'done'):
|
||
|
request = self.getRequestStatus()
|
||
|
messenger.send('doorDoneEvent', [request])
|
||
|
|
||
|
def exitClosing(self):
|
||
|
pass
|
||
|
|
||
|
def enterClosed(self, ts):
|
||
|
pass
|
||
|
|
||
|
def exitClosed(self):
|
||
|
pass
|
||
|
|
||
|
def enterOpening(self, ts):
|
||
|
doorFrameHoleRight = self.findDoorNode('doorFrameHoleRight')
|
||
|
if doorFrameHoleRight.isEmpty():
|
||
|
self.notify.warning('enterOpening(): did not find doorFrameHoleRight')
|
||
|
return
|
||
|
rightDoor = self.findDoorNode('rightDoor')
|
||
|
if rightDoor.isEmpty():
|
||
|
self.notify.warning('enterOpening(): did not find rightDoor')
|
||
|
return
|
||
|
otherNP = self.getDoorNodePath()
|
||
|
trackName = 'doorOpen-%d' % self.doId
|
||
|
if self.rightSwing:
|
||
|
h = 100
|
||
|
else:
|
||
|
h = -100
|
||
|
self.finishDoorTrack()
|
||
|
self.doorTrack = Parallel(SoundInterval(self.openSfx, node=rightDoor), Sequence(HprInterval(rightDoor, VBase3(0, 0, 0), other=otherNP), Wait(0.4), Func(rightDoor.show), Func(doorFrameHoleRight.show), LerpHprInterval(nodePath=rightDoor, duration=0.6, hpr=VBase3(h, 0, 0), startHpr=VBase3(0, 0, 0), other=otherNP, blendType='easeInOut')), name=trackName)
|
||
|
self.doorTrack.start(ts)
|
||
|
|
||
|
def exitOpening(self):
|
||
|
pass
|
||
|
|
||
|
def enterOpen(self, ts):
|
||
|
for avatarID in self.avatarIDList:
|
||
|
avatar = self.cr.doId2do.get(avatarID)
|
||
|
if avatar:
|
||
|
track = self.avatarEnterDoorTrack(avatar, 1.0)
|
||
|
track.start(ts)
|
||
|
self.avatarTracks.append(track)
|
||
|
if avatarID == base.localAvatar.doId:
|
||
|
self.done = 1
|
||
|
self.avatarIDList = []
|
||
|
|
||
|
def exitOpen(self):
|
||
|
for track in self.avatarTracks:
|
||
|
track.finish()
|
||
|
DelayDelete.cleanupDelayDeletes(track)
|
||
|
self.avatarTracks = []
|
||
|
|
||
|
def exitDoorEnterOff(self):
|
||
|
pass
|
||
|
|
||
|
def exitDoorExitOff(self):
|
||
|
pass
|
||
|
|
||
|
def exitDoorEnterClosing(self, ts):
|
||
|
doorFrameHoleLeft = self.findDoorNode('doorFrameHoleLeft')
|
||
|
if doorFrameHoleLeft.isEmpty():
|
||
|
self.notify.warning('enterOpening(): did not find flatDoors')
|
||
|
return
|
||
|
if self.leftSwing:
|
||
|
h = -100
|
||
|
else:
|
||
|
h = 100
|
||
|
leftDoor = self.findDoorNode('leftDoor')
|
||
|
if not leftDoor.isEmpty():
|
||
|
otherNP = self.getDoorNodePath()
|
||
|
trackName = 'doorExitTrack-%d' % self.doId
|
||
|
self.finishDoorExitTrack()
|
||
|
self.doorExitTrack = Sequence(LerpHprInterval(nodePath = leftDoor, duration = 1.0, hpr = VBase3(0, 0, 0), startHpr = VBase3(h, 0, 0), other = otherNP, blendType = 'easeInOut'), Func(doorFrameHoleLeft.hide), Func(self.hideIfHasFlat, leftDoor), SoundInterval(self.closeSfx, node = leftDoor), name = trackName)
|
||
|
self.doorExitTrack.start(ts)
|
||
|
|
||
|
def exitDoorExitClosing(self):
|
||
|
pass
|
||
|
|
||
|
def exitDoorEnterClosed(self, ts):
|
||
|
pass
|
||
|
|
||
|
def exitDoorExitClosed(self):
|
||
|
pass
|
||
|
|
||
|
def exitDoorEnterOpening(self, ts):
|
||
|
doorFrameHoleLeft = self.findDoorNode('doorFrameHoleLeft')
|
||
|
if doorFrameHoleLeft.isEmpty():
|
||
|
self.notify.warning('enterOpening(): did not find flatDoors')
|
||
|
return
|
||
|
leftDoor = self.findDoorNode('leftDoor')
|
||
|
if self.leftSwing:
|
||
|
h = -100
|
||
|
else:
|
||
|
h = 100
|
||
|
if not leftDoor.isEmpty():
|
||
|
otherNP = self.getDoorNodePath()
|
||
|
trackName = 'doorDoorExitTrack-%d' % self.doId
|
||
|
self.finishDoorExitTrack()
|
||
|
self.doorExitTrack = Parallel(SoundInterval(self.openSfx, node = leftDoor), Sequence(Func(leftDoor.show), Func(doorFrameHoleLeft.show), LerpHprInterval(nodePath = leftDoor, duration = 0.59999999999999998, hpr = VBase3(h, 0, 0), startHpr = VBase3(0, 0, 0), other = otherNP, blendType = 'easeInOut')), name = trackName)
|
||
|
self.doorExitTrack.start(ts)
|
||
|
else:
|
||
|
self.notify.warning('exitDoorEnterOpening(): did not find leftDoor')
|
||
|
|
||
|
def exitDoorExitOpening(self):
|
||
|
pass
|
||
|
|
||
|
def exitDoorEnterOpen(self, ts):
|
||
|
for avatarID in self.avatarExitIDList:
|
||
|
avatar = self.cr.doId2do.get(avatarID)
|
||
|
if avatar:
|
||
|
track = self.avatarExitTrack(avatar, 0.2)
|
||
|
track.start()
|
||
|
self.avatarExitTracks.append(track)
|
||
|
self.avatarExitIDList = []
|
||
|
|
||
|
def exitDoorExitOpen(self):
|
||
|
for track in self.avatarExitTracks:
|
||
|
track.finish()
|
||
|
DelayDelete.cleanupDelayDeletes(track)
|
||
|
self.avatarExitTracks = []
|
||
|
|
||
|
def findDoorNode(self, string, allowEmpty = False):
|
||
|
building = self.getBuilding()
|
||
|
if not building:
|
||
|
self.notify.warning('getBuilding() returned None, avoiding crash, remark 896029')
|
||
|
foundNode = None
|
||
|
else:
|
||
|
foundNode = building.find('**/door_' + str(self.doorIndex) + '/**/' + string + '*;+s+i')
|
||
|
if foundNode.isEmpty():
|
||
|
foundNode = building.find('**/' + string + '*;+s+i')
|
||
|
if allowEmpty:
|
||
|
return foundNode
|
||
|
return foundNode
|
||
|
|
||
|
def hideIfHasFlat(self, node):
|
||
|
if self.bHasFlat:
|
||
|
node.hide()
|