more cleanup

This commit is contained in:
Open Toontown 2023-04-28 21:51:00 -04:00
parent 1e4a7495d2
commit 25e353e290
4 changed files with 523 additions and 350 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,48 +1,66 @@
from toontown.toonbase.ToonBaseGlobal import *
from panda3d.core import *
from direct.interval.IntervalGlobal import *
from direct.distributed.ClockDelta import *
from toontown.toonbase import ToontownGlobals
from direct.directnotify import DirectNotifyGlobal
from direct.fsm import ClassicFSM, State
from direct.distributed import DistributedObject
from toontown.hood import ZoneUtil
from toontown.suit import Suit
from toontown.distributed import DelayDelete
from . import FADoorCodes
from direct.task.Task import Task
from . import DoorTypes
from toontown.toontowngui import TTDialog
from toontown.toonbase import TTLocalizer
from toontown.toontowngui import TeaserPanel
from toontown.distributed.DelayDeletable import DelayDeletable
if (__debug__):
import pdb
from panda3d.core import NodePath, Point3, VBase3, Vec3
from panda3d.otp import Nametag, NametagGroup
class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.distributed.ClockDelta import globalClockDelta
from direct.distributed.DistributedObject import DistributedObject
from direct.fsm.ClassicFSM import ClassicFSM
from direct.fsm.State import State
from direct.interval.IntervalGlobal import (
ActorInterval,
Func,
HprInterval,
LerpHprInterval,
LerpPosHprInterval,
LerpPosInterval,
Parallel,
PosHprInterval,
Sequence,
SoundInterval,
Wait
)
from direct.showbase.MessengerGlobal import messenger
from direct.task.TaskManagerGlobal import taskMgr
from toontown.building import DoorTypes
from toontown.building import FADoorCodes
from toontown.distributed.DelayDeletable import DelayDeletable
from toontown.distributed.DelayDelete import DelayDelete, cleanupDelayDeletes
from toontown.hood import ZoneUtil
from toontown.suit.Suit import Suit
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
from toontown.toontowngui import TTDialog
from toontown.toontowngui.TeaserPanel import TeaserPanel
class DistributedDoor(DistributedObject, DelayDeletable):
notify = directNotify.newCategory('DistributedDoor')
def __init__(self, cr):
DistributedObject.DistributedObject.__init__(self, cr)
DistributedObject.__init__(self, cr)
self.openSfx = base.loader.loadSfx('phase_3.5/audio/sfx/Door_Open_1.ogg')
self.closeSfx = base.loader.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',
self.fsm = ClassicFSM('DistributedDoor_right', [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')
State('closing', self.enterClosing, self.exitClosing, ['closed', 'opening']),
State('closed', self.enterClosed, self.exitClosed, ['opening']),
State('opening', self.enterOpening, self.exitOpening, ['open']),
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',
self.exitDoorFSM = ClassicFSM('DistributedDoor_left', [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')
State('closing', self.exitDoorEnterClosing, self.exitDoorExitClosing, ['closed', 'opening']),
State('closed', self.exitDoorEnterClosed, self.exitDoorExitClosed, ['opening']),
State('opening', self.exitDoorEnterOpening, self.exitDoorExitOpening, ['open']),
State('open', self.exitDoorEnterOpen, self.exitDoorExitOpen, ['closing', 'open'])], 'off', 'off')
self.exitDoorFSM.enterInitialState()
self.specialDoorTypes = {DoorTypes.EXT_HQ: 0,
DoorTypes.EXT_COGHQ: 0,
@ -50,17 +68,15 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
DoorTypes.EXT_KS: 0,
DoorTypes.INT_KS: 0}
self.doorX = 1.5
return
def generate(self):
DistributedObject.DistributedObject.generate(self)
DistributedObject.generate(self)
self.avatarTracks = []
self.avatarExitTracks = []
self.avatarIDList = []
self.avatarExitIDList = []
self.doorTrack = None
self.doorExitTrack = None
return
def disable(self):
self.clearNametag()
@ -72,20 +88,22 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.exitDoorFSM.request('off')
if 'building' in self.__dict__:
del self.building
self.finishAllTracks()
self.avatarIDList = []
self.avatarExitIDList = []
if hasattr(self, 'tempDoorNodePath'):
self.tempDoorNodePath.removeNode()
del self.tempDoorNodePath
DistributedObject.DistributedObject.disable(self)
DistributedObject.disable(self)
def delete(self):
del self.fsm
del self.exitDoorFSM
del self.openSfx
del self.closeSfx
DistributedObject.DistributedObject.delete(self)
DistributedObject.delete(self)
def wantsNametag(self):
return not ZoneUtil.isInterior(self.zoneId)
@ -93,11 +111,13 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def setupNametag(self):
if not self.wantsNametag():
return
if self.nametag == None:
self.nametag = NametagGroup()
self.nametag.setFont(ToontownGlobals.getBuildingNametagFont())
if TTLocalizer.BuildingNametagShadow:
self.nametag.setShadow(*TTLocalizer.BuildingNametagShadow)
self.nametag.setContents(Nametag.CName)
self.nametag.setColorCode(NametagGroup.CCToonBuilding)
self.nametag.setActive(0)
@ -106,14 +126,12 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
name = self.cr.playGame.dnaStore.getTitleFromBlockNumber(self.block)
self.nametag.setName(name)
self.nametag.manage(base.marginManager)
return
def clearNametag(self):
if self.nametag != None:
self.nametag.unmanage(base.marginManager)
self.nametag.setAvatar(NodePath())
self.nametag = None
return
def getTriggerName(self):
if self.doorType == DoorTypes.INT_HQ or self.doorType in self.specialDoorTypes:
@ -137,26 +155,25 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.hideIfHasFlat(self.findDoorNode('leftDoor'))
self.findDoorNode('doorFrameHoleRight').hide()
self.findDoorNode('doorFrameHoleLeft').hide()
else:
return
def setTriggerName(self):
if self.doorType in self.specialDoorTypes:
building = self.getBuilding()
doorTrigger = building.find('**/door_' + str(self.doorIndex) + '/**/door_trigger*')
doorTrigger.node().setName(self.getTriggerName())
else:
return
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):
@ -185,7 +202,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.exitDoorFSM.request(state, [globalClockDelta.localElapsedTime(timestamp)])
def announceGenerate(self):
DistributedObject.DistributedObject.announceGenerate(self)
DistributedObject.announceGenerate(self)
self.doPostAnnounceGenerate()
def doPostAnnounceGenerate(self):
@ -193,6 +210,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.bHasFlat = True
else:
self.bHasFlat = not self.findDoorNode('door*flat', True).isEmpty()
self.hideDoorParts()
self.setTriggerName()
self.accept(self.getEnterTriggerEvent(), self.doorTrigger)
@ -202,13 +220,13 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def getBuilding(self):
if 'building' not in self.__dict__:
if self.doorType == DoorTypes.INT_STANDARD:
door = render.find('**/leftDoor;+s')
door = base.render.find('**/leftDoor;+s')
self.building = door.getParent()
elif self.doorType == DoorTypes.INT_HQ:
door = render.find('**/door_0')
door = base.render.find('**/door_0')
self.building = door.getParent()
elif self.doorType == DoorTypes.INT_KS:
self.building = render.find('**/KartShop_Interior*')
self.building = base.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():
@ -217,6 +235,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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):
@ -226,6 +245,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
else:
self.building = self.cr.playGame.hood.loader.geom
print('---------------- door is interior -------')
return self.building
def readyToExit(self):
@ -238,33 +258,38 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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'))
track.append(LerpPosHprInterval(nodePath=base.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')
track.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')
track.delayDelete = DelayDelete(avatar, 'avatarEnqueueTrack')
return track
def getAnimStateInterval(self, avatar, animName):
isSuit = isinstance(avatar, Suit.Suit)
isSuit = isinstance(avatar, Suit)
if isSuit:
return Func(avatar.loop, animName, 0)
else:
@ -284,7 +309,8 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
place = base.cr.playGame.getPlace()
if place:
place.fsm.request('stopped')
self.dialog = TeaserPanel.TeaserPanel(pageName='otherHoods', doneFunc=self.handleOkTeaser)
self.dialog = TeaserPanel(pageName='otherHoods', doneFunc=self.handleOkTeaser)
def handleOkTeaser(self):
self.accept(self.getEnterTriggerEvent(), self.doorTrigger)
@ -301,6 +327,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
allowed = base.ttAccess.canAccess(zoneId)
else:
allowed = base.ttAccess.canAccess()
return allowed
def checkIsDoorHitTaskName(self):
@ -311,8 +338,9 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
self.ignore(self.checkIsDoorHitTaskName())
self.ignore(self.getExitTriggerEvent())
self.enterDoor()
return Task.done
return Task.cont
return task.done
return task.cont
def cancelCheckIsDoorHitTask(self, args):
taskMgr.remove(self.checkIsDoorHitTaskName())
@ -333,7 +361,6 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
else:
self.accept(self.getExitTriggerEvent(), self.cancelCheckIsDoorHitTask)
taskMgr.add(self.checkIsDoorHitTask, self.checkIsDoorHitTaskName())
return
def avatarEnter(self, avatarID):
avatar = self.cr.doId2do.get(avatarID, None)
@ -343,7 +370,6 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
track.start()
self.avatarTracks.append(track)
self.avatarIDList.append(avatarID)
return
def rejectEnter(self, reason):
message = FADoorCodes.reasonDict[reason]
@ -360,7 +386,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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')
self.rejectDialog.delayDelete = DelayDelete(self, '__faRejectEnter')
event = 'clientCleanup'
self.acceptOnce(event, self.__handleClientCleanup)
base.cr.playGame.getPlace().setState('stopped')
@ -370,6 +396,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def __handleClientCleanup(self):
if hasattr(self, 'rejectDialog') and self.rejectDialog:
self.rejectDialog.doneStatus = 'ok'
self.__handleRejectAck()
def __handleFallAsleepDoor(self):
@ -383,6 +410,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
doneStatus = self.rejectDialog.doneStatus
if doneStatus != 'ok':
self.notify.error('Unrecognized doneStatus: ' + str(doneStatus))
self.__basicRejectEnter()
self.rejectDialog.delayDelete.destroy()
self.rejectDialog.cleanup()
@ -390,7 +418,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def getDoorNodePath(self):
if self.doorType == DoorTypes.INT_STANDARD:
otherNP = render.find('**/door_origin')
otherNP = base.render.find('**/door_origin')
elif self.doorType == DoorTypes.EXT_STANDARD:
if hasattr(self, 'tempDoorNodePath'):
return self.tempDoorNodePath
@ -404,14 +432,16 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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))
otherNP = base.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)
@ -419,18 +449,22 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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))
track.append(PosHprInterval(base.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))
finalPos = base.render.getRelativePoint(otherNP, Point3(-self.doorX, -6, ToontownGlobals.FloorOffset))
else:
finalPos = render.getRelativePoint(otherNP, Point3(-self.doorX, -3, ToontownGlobals.FloorOffset))
finalPos = base.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')
track.delayDelete = DelayDelete(avatar, 'DistributedDoor.avatarExitTrack')
return track
def exitCompleted(self):
@ -438,6 +472,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
place = self.cr.playGame.getPlace()
if place:
place.setState('walk')
base.localAvatar.d_setParent(ToontownGlobals.SPRender)
def avatarExit(self, avatarID):
@ -451,26 +486,26 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def finishDoorTrack(self):
if self.doorTrack:
self.doorTrack.finish()
self.doorTrack = None
return
def finishDoorExitTrack(self):
if self.doorExitTrack:
self.doorExitTrack.finish()
self.doorExitTrack = None
return
def finishAllTracks(self):
self.finishDoorTrack()
self.finishDoorExitTrack()
for t in self.avatarTracks:
t.finish()
DelayDelete.cleanupDelayDeletes(t)
cleanupDelayDeletes(t)
self.avatarTracks = []
for t in self.avatarExitTracks:
t.finish()
DelayDelete.cleanupDelayDeletes(t)
cleanupDelayDeletes(t)
self.avatarExitTracks = []
@ -498,16 +533,19 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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)
@ -529,16 +567,19 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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)
@ -553,6 +594,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
track = self.avatarEnterDoorTrack(avatar, 1.0)
track.start(ts)
self.avatarTracks.append(track)
if avatarID == base.localAvatar.doId:
self.done = 1
@ -561,7 +603,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def exitOpen(self):
for track in self.avatarTracks:
track.finish()
DelayDelete.cleanupDelayDeletes(track)
cleanupDelayDeletes(track)
self.avatarTracks = []
@ -576,10 +618,12 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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()
@ -602,11 +646,13 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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
@ -632,7 +678,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
def exitDoorExitOpen(self):
for track in self.avatarExitTracks:
track.finish()
DelayDelete.cleanupDelayDeletes(track)
cleanupDelayDeletes(track)
self.avatarExitTracks = []
@ -645,8 +691,10 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable):
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):

View file

@ -1,30 +1,36 @@
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.directnotify import DirectNotifyGlobal
from direct.fsm import StateData
from direct.showbase.PythonUtil import PriorityCallbacks
from toontown.safezone import PublicWalk
from toontown.launcher import DownloadForceAcknowledge
from . import TrialerForceAcknowledge
from . import ZoneUtil
from toontown.friends import FriendsListManager
from toontown.toonbase import ToontownGlobals
from toontown.toon.Toon import teleportDebug
from toontown.estate import HouseGlobals
from toontown.toonbase import TTLocalizer
from otp.otpbase import OTPLocalizer
from otp.avatar import Emote
from otp.avatar.Avatar import teleportNotify
from direct.task import Task
from . import QuietZoneState
from toontown.distributed import ToontownDistrictStats
from panda3d.core import NodePath
from panda3d.otp import NametagGlobals
class Place(StateData.StateData, FriendsListManager.FriendsListManager):
notify = DirectNotifyGlobal.directNotify.newCategory('Place')
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.StateData import StateData
from direct.showbase.MessengerGlobal import messenger
from direct.showbase.PythonUtil import Functor, PriorityCallbacks, SubframeCall, uniqueName
from direct.task.TaskManagerGlobal import taskMgr
from otp.avatar.Avatar import teleportNotify
from otp.avatar.Emote import globalEmote
from otp.otpbase import OTPLocalizer
from toontown.distributed import ToontownDistrictStats
from toontown.estate import HouseGlobals
from toontown.friends.FriendsListManager import FriendsListManager
from toontown.hood import ZoneUtil
from toontown.hood.QuietZoneState import QuietZoneState
from toontown.hood.TrialerForceAcknowledge import TrialerForceAcknowledge
from toontown.launcher.DownloadForceAcknowledge import DownloadForceAcknowledge
from toontown.safezone.PublicWalk import PublicWalk
from toontown.toon.Toon import teleportDebug
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
class Place(StateData, FriendsListManager):
notify = directNotify.newCategory('Place')
def __init__(self, loader, doneEvent):
StateData.StateData.__init__(self, doneEvent)
FriendsListManager.FriendsListManager.__init__(self)
StateData.__init__(self, doneEvent)
FriendsListManager.__init__(self)
self.loader = loader
self.dfaDoneEvent = 'dfaDoneEvent'
self.trialerFADoneEvent = 'trialerFADoneEvent'
@ -35,26 +41,27 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self._leftQuietZoneSubframeCall = None
self._setZoneCompleteLocalCallbacks = PriorityCallbacks()
self._setZoneCompleteSubframeCall = None
return
def load(self):
StateData.StateData.load(self)
FriendsListManager.FriendsListManager.load(self)
StateData.load(self)
FriendsListManager.load(self)
self.walkDoneEvent = 'walkDone'
self.walkStateData = PublicWalk.PublicWalk(self.fsm, self.walkDoneEvent)
self.walkStateData = PublicWalk(self.fsm, self.walkDoneEvent)
self.walkStateData.load()
self._tempFSM = self.fsm
def unload(self):
StateData.StateData.unload(self)
FriendsListManager.FriendsListManager.unload(self)
StateData.unload(self)
FriendsListManager.unload(self)
self.notify.info('Unloading Place (%s). Fsm in %s' % (self.zoneId, self._tempFSM.getCurrentState().getName()))
if self._leftQuietZoneSubframeCall:
self._leftQuietZoneSubframeCall.cleanup()
self._leftQuietZoneSubframeCall = None
if self._setZoneCompleteSubframeCall:
self._setZoneCompleteSubframeCall.cleanup()
self._setZoneCompleteSubframeCall = None
self._leftQuietZoneLocalCallbacks = None
self._setZoneCompleteLocalCallbacks = None
del self._tempFSM
@ -66,12 +73,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
if self.trialerFA:
self.trialerFA.exit()
del self.trialerFA
return
def _getQZState(self):
if hasattr(base, 'cr') and hasattr(base.cr, 'playGame'):
if hasattr(base.cr.playGame, 'quietZoneStateData') and base.cr.playGame.quietZoneStateData:
return base.cr.playGame.quietZoneStateData
return None
def addLeftQuietZoneCallback(self, callback, priority = None):
@ -82,22 +89,22 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
token = self._leftQuietZoneLocalCallbacks.add(callback, priority=priority)
if not self._leftQuietZoneSubframeCall:
self._leftQuietZoneSubframeCall = SubframeCall(self._doLeftQuietZoneCallbacks, taskMgr.getCurrentTask().getPriority() - 1)
return token
def removeLeftQuietZoneCallback(self, token):
if token is not None:
if token in self._leftQuietZoneLocalCallbacks:
self._leftQuietZoneLocalCallbacks.remove(token)
qzsd = self._getQZState()
if qzsd:
qzsd.removeLeftQuietZoneCallback(token)
return
def _doLeftQuietZoneCallbacks(self):
self._leftQuietZoneLocalCallbacks()
self._leftQuietZoneLocalCallbacks.clear()
self._leftQuietZoneSubframeCall = None
return
def addSetZoneCompleteCallback(self, callback, priority = None):
qzsd = self._getQZState()
@ -107,29 +114,30 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
token = self._setZoneCompleteLocalCallbacks.add(callback, priority=priority)
if not self._setZoneCompleteSubframeCall:
self._setZoneCompleteSubframeCall = SubframeCall(self._doSetZoneCompleteLocalCallbacks, taskMgr.getCurrentTask().getPriority() - 1)
return token
def removeSetZoneCompleteCallback(self, token):
if token is not None:
if any(token == x[1] for x in self._setZoneCompleteLocalCallbacks._callbacks):
self._setZoneCompleteLocalCallbacks.remove(token)
qzsd = self._getQZState()
if qzsd:
qzsd.removeSetZoneCompleteCallback(token)
return
def _doSetZoneCompleteLocalCallbacks(self):
self._setZoneCompleteSubframeCall = None
localCallbacks = self._setZoneCompleteLocalCallbacks
self._setZoneCompleteLocalCallbacks()
localCallbacks.clear()
return
def setState(self, state):
if hasattr(self, 'fsm'):
curState = self.fsm.getName()
if state == 'pet' or curState == 'pet':
self.preserveFriendsList()
self.fsm.request(state)
def getState(self):
@ -148,10 +156,10 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def handleTeleportQuery(self, fromAvatar, toAvatar):
if base.config.GetBool('want-tptrack', False):
if toAvatar == localAvatar:
if toAvatar == base.localAvatar:
toAvatar.doTeleportResponse(fromAvatar, toAvatar, toAvatar.doId, 1, toAvatar.defaultShard, base.cr.playGame.getPlaceId(), self.getZoneId(), fromAvatar.doId)
else:
self.notify.warning('handleTeleportQuery toAvatar.doId != localAvatar.doId' % (toAvatar.doId, localAvatar.doId))
self.notify.warning('handleTeleportQuery toAvatar.doId != localAvatar.doId' % (toAvatar.doId, base.localAvatar.doId))
else:
fromAvatar.d_teleportResponse(toAvatar.doId, 1, toAvatar.defaultShard, base.cr.playGame.getPlaceId(), self.getZoneId())
@ -159,6 +167,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
if self.isPeriodTimerEffective():
if base.cr.periodTimerExpired:
taskMgr.doMethodLater(5, self.redoPeriodTimer, 'redoPeriodTimer')
self.accept('periodTimerExpired', self.periodTimerExpired)
def disablePeriodTimer(self):
@ -167,7 +176,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def redoPeriodTimer(self, task):
messenger.send('periodTimerExpired')
return Task.done
return task.done
def periodTimerExpired(self):
self.fsm.request('final')
@ -209,10 +218,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.walkStateData.enter()
if teleportIn == 0:
self.walkStateData.fsm.request('walking')
self.acceptOnce(self.walkDoneEvent, self.handleWalkDone)
if base.cr.productName in ['DisneyOnline-US', 'ES'] and not base.cr.isPaid() and base.localAvatar.tutorialAck:
base.localAvatar.chatMgr.obscure(0, 0)
base.localAvatar.chatMgr.normalButton.show()
self.accept('teleportQuery', self.handleTeleportQuery)
base.localAvatar.setTeleportAvailable(1)
base.localAvatar.questPage.acceptOnscreenHooks()
@ -225,6 +236,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.exitFLM()
if base.cr.productName in ['DisneyOnline-US', 'ES'] and not base.cr.isPaid() and base.localAvatar.tutorialAck and not base.cr.whiteListChatEnabled:
base.localAvatar.chatMgr.obscure(1, 0)
self.disablePeriodTimer()
messenger.send('wakeup')
self.walkStateData.exit()
@ -233,13 +245,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.ignore('teleportQuery')
if base.cr.playGame.hood != None:
base.cr.playGame.hood.hideTitleText()
base.localAvatar.questPage.hideQuestsOnscreen()
base.localAvatar.questPage.ignoreOnscreenHooks()
base.localAvatar.invPage.ignoreOnscreenHooks()
base.localAvatar.invPage.hideInventoryOnscreen()
base.localAvatar.questMap.hide()
base.localAvatar.questMap.ignoreOnscreenHooks()
return
def handleWalkDone(self, doneStatus):
mode = doneStatus['mode']
@ -308,10 +320,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
target = base.cr.doFind('DistributedTarget')
if target:
target.hideGui()
self.accept('teleportQuery', self.handleTeleportQuery)
base.localAvatar.setTeleportAvailable(1)
if page:
base.localAvatar.book.setPage(page)
base.localAvatar.b_setAnimState('OpenBook', 1, self.enterStickerBookGUI)
base.localAvatar.obscureMoveFurnitureButton(1)
@ -328,11 +342,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def __handleFallingAsleep(self, task):
base.localAvatar.book.exit()
base.localAvatar.b_setAnimState('CloseBook', 1, callback=self.__handleFallingAsleepBookClose)
return Task.done
return task.done
def __handleFallingAsleepBookClose(self):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
base.localAvatar.forceGotoSleep()
def exitStickerBook(self):
@ -377,10 +392,11 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
base.localAvatar.b_setAnimState('CloseBook', 1, callback=self.startPartyNow, extraArgs=[firstStart, hostId])
def handleBookCloseTeleport(self, hoodId, zoneId):
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
return
self.requestLeave({'loader': ZoneUtil.getBranchLoaderName(zoneId),
'where': ZoneUtil.getToonWhereName(zoneId),
'how': 'teleportIn',
@ -388,7 +404,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
'zoneId': zoneId,
'shardId': None,
'avId': -1})
return
def __handleBookCloseExit(self):
base.localAvatar.b_setAnimState('TeleportOut', 1, self.__handleBookExitTeleport, [0])
@ -396,14 +411,16 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def __handleBookExitTeleport(self, requestStatus):
if base.cr.timeManager:
base.cr.timeManager.setDisconnectReason(ToontownGlobals.DisconnectBookExit)
base.transitions.fadeScreen(1.0)
base.cr.gameFSM.request(self.exitTo)
def goHomeNow(self, curZoneId):
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
return
hoodId = ToontownGlobals.MyEstate
self.requestLeave({'loader': 'safeZoneLoader',
'where': 'estate',
@ -412,13 +429,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
'zoneId': -1,
'shardId': None,
'avId': -1})
return
def startPartyNow(self, firstStart, hostId):
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
return
base.localAvatar.creatingNewPartyWithMagicWord = False
base.localAvatar.aboutToPlanParty = False
hoodId = ToontownGlobals.PartyHood
@ -436,6 +453,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
if shardId == base.localAvatar.defaultShard:
shardId = None
base.cr.playGame.getPlace().requestLeave({'loader': 'safeZoneLoader',
'where': 'party',
'how': 'teleportIn',
@ -446,13 +464,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
else:
if hostId is None:
hostId = base.localAvatar.doId
base.cr.partyManager.sendAvatarToParty(hostId)
return
return
def handleBookClose(self):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
if hasattr(self, 'toonSubmerged') and self.toonSubmerged == 1:
if hasattr(self, 'walkStateData'):
self.walkStateData.fsm.request('swimming', [self.loader.swimSound])
@ -469,26 +487,27 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterDFA(self, requestStatus):
teleportDebug(requestStatus, 'enterDFA(%s)' % (requestStatus,))
self.acceptOnce(self.dfaDoneEvent, self.enterDFACallback, [requestStatus])
self.dfa = DownloadForceAcknowledge.DownloadForceAcknowledge(self.dfaDoneEvent)
self.dfa = DownloadForceAcknowledge(self.dfaDoneEvent)
self.dfa.enter(base.cr.hoodMgr.getPhaseFromHood(requestStatus['hoodId']))
def exitDFA(self):
self.ignore(self.dfaDoneEvent)
def handleEnterTunnel(self, requestStatus, collEntry):
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
dummyNP = NodePath('dummyNP')
dummyNP.reparentTo(render)
dummyNP.reparentTo(base.render)
tunnelOrigin = requestStatus['tunnelOrigin']
dummyNP.setPos(localAvatar.getPos())
dummyNP.setPos(base.localAvatar.getPos())
dummyNP.setH(tunnelOrigin.getH())
dummyNP.setPos(dummyNP, 0, 4, 0)
localAvatar.setPos(dummyNP.getPos())
base.localAvatar.setPos(dummyNP.getPos())
dummyNP.removeNode()
del dummyNP
return
self.requestLeave(requestStatus)
def enterDFACallback(self, requestStatus, doneStatus):
@ -504,6 +523,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
out = {'teleportIn': 'teleportOut',
'tunnelIn': 'tunnelOut',
'doorIn': 'doorOut'}
teleportDebug(requestStatus, 'requesting %s, requestStatus=%s' % (out[requestStatus['how']], requestStatus))
self.fsm.request(out[requestStatus['how']], [requestStatus])
elif doneStatus['mode'] == 'incomplete':
@ -520,7 +540,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterTrialerFA(self, requestStatus):
teleportDebug(requestStatus, 'enterTrialerFA(%s)' % requestStatus)
self.acceptOnce(self.trialerFADoneEvent, self.trialerFACallback, [requestStatus])
self.trialerFA = TrialerForceAcknowledge.TrialerForceAcknowledge(self.trialerFADoneEvent)
self.trialerFA = TrialerForceAcknowledge(self.trialerFADoneEvent)
self.trialerFA.enter(requestStatus['hoodId'])
def exitTrialerFA(self):
@ -589,6 +609,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
tunnelName = requestStatus.get('tunnelName')
if tunnelName == None:
tunnelName = base.cr.hoodMgr.makeLinkTunnelName(self.loader.hood.id, fromZoneId)
self.doneStatus = {'loader': ZoneUtil.getLoaderName(zoneId),
'where': ZoneUtil.getToonWhereName(zoneId),
'how': how,
@ -599,7 +620,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.accept('tunnelOutMovieDone', self.__tunnelOutMovieDone)
base.localAvatar.tunnelOut(tunnelOrigin)
base.localAvatar.stopQuestMap()
return
def __tunnelOutMovieDone(self):
self.ignore('tunnelOutMovieDone')
@ -621,11 +641,11 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterDied(self, requestStatus, callback = None):
if callback == None:
callback = self.__diedDone
base.localAvatar.laffMeter.start()
camera.wrtReparentTo(render)
base.camera.wrtReparentTo(base.render)
base.localAvatar.b_setAnimState('Died', 1, callback, [requestStatus])
base.localAvatar.obscureMoveFurnitureButton(1)
return
def __diedDone(self, requestStatus):
self.doneStatus = requestStatus
@ -643,6 +663,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
base.cr.estateMgr.getLocalEstateZone(avId)
else:
base.cr.estateMgr.getLocalEstateZone(base.localAvatar.getDoId())
if HouseGlobals.WANT_TELEPORT_TIMEOUT:
taskMgr.doMethodLater(HouseGlobals.TELEPORT_TIMEOUT, self.goHomeFailed, 'goHomeFailed')
@ -653,6 +674,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.doneStatus['failed'] = 1
self.goHomeFailed(None)
return
if ownerId == 0 and zoneId == 0:
if self.doneStatus['shardId'] is None or self.doneStatus['shardId'] is base.localAvatar.defaultShard:
self.doneStatus['failed'] = 1
@ -666,14 +688,15 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.doneStatus['how'] = 'teleportIn'
messenger.send(self.doneEvent)
return
if self.doneStatus['zoneId'] == -1:
self.doneStatus['zoneId'] = zoneId
elif self.doneStatus['zoneId'] != zoneId:
self.doneStatus['where'] = 'house'
self.doneStatus['ownerId'] = ownerId
messenger.send(self.doneEvent)
messenger.send('localToonLeft')
return
def goHomeFailed(self, task):
self.notify.debug('goHomeFailed')
@ -682,7 +705,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.doneStatus['hood'] = base.localAvatar.lastHood
self.doneStatus['zone'] = base.localAvatar.lastHood
self.fsm.request('teleportIn', [self.doneStatus])
return Task.done
return task.done
def notifyUserGoHomeFailed(self):
self.notify.debug('notifyUserGoHomeFailed')
@ -692,12 +715,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
avatar = base.cr.identifyAvatar(failedToVisitAvId)
if avatar:
avName = avatar.getName()
if avName:
message = TTLocalizer.EstateTeleportFailedNotFriends % avName
else:
message = TTLocalizer.EstateTeleportFailed
base.localAvatar.setSystemMessage(0, message)
return
def enterTeleportIn(self, requestStatus):
self._tiToken = self.addSetZoneCompleteCallback(Functor(self._placeTeleportInPostZoneComplete, requestStatus), 100)
@ -723,16 +747,16 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
teleportDebug(requestStatus, 'friend not here, giving up')
base.localAvatar.setSystemMessage(avId, OTPLocalizer.WhisperTargetLeftVisit % (friend.getName(),))
friend.d_teleportGiveup(base.localAvatar.doId)
base.transitions.irisIn()
self.nextState = requestStatus.get('nextState', 'walk')
base.localAvatar.attachCamera()
base.localAvatar.startUpdateSmartCamera()
base.localAvatar.startPosHprBroadcast()
globalClock.tick()
base.clock.tick()
base.localAvatar.b_setAnimState('TeleportIn', 1, callback=self.teleportInDone)
base.localAvatar.d_broadcastPositionNow()
base.localAvatar.b_setParent(ToontownGlobals.SPRender)
return
def teleportInDone(self):
if hasattr(self, 'fsm'):
@ -748,7 +772,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
base.localAvatar.stopUpdateSmartCamera()
base.localAvatar.detachCamera()
base.localAvatar.stopPosHprBroadcast()
return
def requestTeleport(self, hoodId, zoneId, shardId, avId):
if avId > 0:
@ -756,20 +779,25 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
zoneId,
shardId,
avId),))
if localAvatar.hasActiveBoardingGroup():
if base.localAvatar.hasActiveBoardingGroup():
if avId > 0:
teleportNotify.debug('requestTeleport: has active boarding group')
rejectText = TTLocalizer.BoardingCannotLeaveZone
localAvatar.elevatorNotifier.showMe(rejectText)
base.localAvatar.elevatorNotifier.showMe(rejectText)
return
loaderId = ZoneUtil.getBranchLoaderName(zoneId)
whereId = ZoneUtil.getToonWhereName(zoneId)
if hoodId == ToontownGlobals.MyEstate:
loaderId = 'safeZoneLoader'
whereId = 'estate'
if hoodId == ToontownGlobals.PartyHood:
loaderId = 'safeZoneLoader'
whereId = 'party'
self.requestLeave({'loader': loaderId,
'where': whereId,
'how': 'teleportIn',
@ -828,6 +856,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
if hasattr(self, 'fsm'):
messenger.send('bankAsleep')
self.fsm.request('walk')
base.localAvatar.forceGotoSleep()
def exitBanking(self):
@ -850,6 +879,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def __handleFallingAsleepPhone(self, arg):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
messenger.send('phoneAsleep')
base.localAvatar.forceGotoSleep()
@ -863,12 +893,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterStopped(self):
base.localAvatar.b_setAnimState('neutral', 1)
Emote.globalEmote.disableBody(base.localAvatar, 'enterStopped')
globalEmote.disableBody(base.localAvatar, 'enterStopped')
self.accept('teleportQuery', self.handleTeleportQuery)
if base.localAvatar.isDisguised:
base.localAvatar.setTeleportAvailable(0)
else:
base.localAvatar.setTeleportAvailable(1)
base.localAvatar.laffMeter.start()
base.localAvatar.obscureMoveFurnitureButton(1)
base.localAvatar.startSleepWatch(self.__handleFallingAsleepStopped)
@ -877,11 +908,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def __handleFallingAsleepStopped(self, arg):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
base.localAvatar.forceGotoSleep()
messenger.send('stoppedAsleep')
def exitStopped(self):
Emote.globalEmote.releaseBody(base.localAvatar, 'exitStopped')
globalEmote.releaseBody(base.localAvatar, 'exitStopped')
base.localAvatar.setTeleportAvailable(0)
self.ignore('teleportQuery')
base.localAvatar.laffMeter.stop()
@ -892,7 +924,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterPet(self):
base.localAvatar.b_setAnimState('neutral', 1)
Emote.globalEmote.disableBody(base.localAvatar, 'enterPet')
globalEmote.disableBody(base.localAvatar, 'enterPet')
self.accept('teleportQuery', self.handleTeleportQuery)
base.localAvatar.setTeleportAvailable(1)
base.localAvatar.setTeleportAllowed(0)
@ -902,7 +934,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def exitPet(self):
base.localAvatar.setTeleportAvailable(0)
base.localAvatar.setTeleportAllowed(1)
Emote.globalEmote.releaseBody(base.localAvatar, 'exitPet')
globalEmote.releaseBody(base.localAvatar, 'exitPet')
self.ignore('teleportQuery')
base.localAvatar.laffMeter.stop()
self.exitFLM()
@ -910,7 +942,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
def enterQuietZone(self, requestStatus):
self.quietZoneDoneEvent = uniqueName('quietZoneDone')
self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone)
self.quietZoneStateData = QuietZoneState.QuietZoneState(self.quietZoneDoneEvent)
self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent)
self.quietZoneStateData.load()
self.quietZoneStateData.enter(requestStatus)
@ -920,7 +952,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager):
self.quietZoneStateData.exit()
self.quietZoneStateData.unload()
self.quietZoneStateData = None
return
def handleQuietZoneDone(self):
how = base.cr.handlerArgs['how']

View file

@ -1,41 +1,45 @@
from direct.interval.IntervalGlobal import *
from panda3d.core import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.directnotify import DirectNotifyGlobal
from toontown.hood import Place
from direct.showbase import DirectObject
from direct.fsm import StateData
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from direct.task import Task
from toontown.toon import DeathForceAcknowledge
from toontown.toon import HealthForceAcknowledge
from toontown.tutorial import TutorialForceAcknowledge
from toontown.toon import NPCForceAcknowledge
from toontown.trolley import Trolley
from toontown.toontowngui import TTDialog
from toontown.toonbase import ToontownGlobals
from toontown.toon.Toon import teleportDebug
from toontown.toonbase import TTLocalizer
from direct.gui import DirectLabel
from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs
from toontown.quest import Quests
from panda3d.core import LineSegs, NodePath, TextNode, Vec4
from panda3d.otp import NametagGlobals
class Playground(Place.Place):
notify = DirectNotifyGlobal.directNotify.newCategory('Playground')
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.ClassicFSM import ClassicFSM
from direct.fsm.State import State
from direct.gui.DirectLabel import DirectLabel
from direct.interval.IntervalGlobal import Func, LerpColorScaleInterval, Sequence
from direct.showbase.MessengerGlobal import messenger
from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs
from toontown.classicchars import CCharPaths
from toontown.hood.Place import Place
from toontown.quest import Quests
from toontown.toon.DeathForceAcknowledge import DeathForceAcknowledge
from toontown.toon.HealthForceAcknowledge import HealthForceAcknowledge
from toontown.toon.NPCForceAcknowledge import NPCForceAcknowledge
from toontown.toon.Toon import teleportDebug
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
from toontown.toontowngui import TTDialog
from toontown.trolley.Trolley import Trolley
from toontown.tutorial.TutorialForceAcknowledge import TutorialForceAcknowledge
class Playground(Place):
notify = directNotify.newCategory('Playground')
def __init__(self, loader, parentFSM, doneEvent):
Place.Place.__init__(self, loader, doneEvent)
Place.__init__(self, loader, doneEvent)
self.tfaDoneEvent = 'tfaDoneEvent'
self.fsm = ClassicFSM.ClassicFSM('Playground', [
State.State('start',
self.fsm = ClassicFSM('Playground', [
State('start',
self.enterStart,
self.exitStart, [
'walk',
'deathAck',
'doorIn',
'tunnelIn']),
State.State('walk',
State('walk',
self.enterWalk,
self.exitWalk, [
'drive',
@ -52,7 +56,7 @@ class Playground(Place.Place):
'purchase',
'stopped',
'fishing']),
State.State('stickerBook',
State('stickerBook',
self.enterStickerBook,
self.exitStickerBook, [
'walk',
@ -66,124 +70,124 @@ class Playground(Place.Place):
'stopped',
'fishing',
'trialerFA']),
State.State('sit',
State('sit',
self.enterSit,
self.exitSit, [
'walk',
'DFA',
'trialerFA']),
State.State('drive',
State('drive',
self.enterDrive,
self.exitDrive, [
'walk',
'DFA',
'trialerFA']),
State.State('trolley',
State('trolley',
self.enterTrolley,
self.exitTrolley, [
'walk']),
State.State('doorIn',
State('doorIn',
self.enterDoorIn,
self.exitDoorIn, [
'walk']),
State.State('doorOut',
State('doorOut',
self.enterDoorOut,
self.exitDoorOut, [
'walk']),
State.State('TFA',
State('TFA',
self.enterTFA,
self.exitTFA, [
'TFAReject',
'DFA']),
State.State('TFAReject',
State('TFAReject',
self.enterTFAReject,
self.exitTFAReject, [
'walk']),
State.State('trialerFA',
State('trialerFA',
self.enterTrialerFA,
self.exitTrialerFA, [
'trialerFAReject',
'DFA']),
State.State('trialerFAReject',
State('trialerFAReject',
self.enterTrialerFAReject,
self.exitTrialerFAReject, [
'walk']),
State.State('DFA',
State('DFA',
self.enterDFA,
self.exitDFA, [
'DFAReject',
'NPCFA',
'HFA']),
State.State('DFAReject',
State('DFAReject',
self.enterDFAReject,
self.exitDFAReject, [
'walk']),
State.State('NPCFA',
State('NPCFA',
self.enterNPCFA,
self.exitNPCFA, [
'NPCFAReject',
'HFA']),
State.State('NPCFAReject',
State('NPCFAReject',
self.enterNPCFAReject,
self.exitNPCFAReject, [
'walk']),
State.State('HFA',
State('HFA',
self.enterHFA,
self.exitHFA, [
'HFAReject',
'teleportOut',
'tunnelOut']),
State.State('HFAReject',
State('HFAReject',
self.enterHFAReject,
self.exitHFAReject, [
'walk']),
State.State('deathAck',
State('deathAck',
self.enterDeathAck,
self.exitDeathAck, [
'teleportIn']),
State.State('teleportIn',
State('teleportIn',
self.enterTeleportIn,
self.exitTeleportIn, [
'walk',
'popup']),
State.State('popup',
State('popup',
self.enterPopup,
self.exitPopup, [
'walk']),
State.State('teleportOut',
State('teleportOut',
self.enterTeleportOut,
self.exitTeleportOut, [
'deathAck',
'teleportIn']),
State.State('died',
State('died',
self.enterDied,
self.exitDied, [
'final']),
State.State('tunnelIn',
State('tunnelIn',
self.enterTunnelIn,
self.exitTunnelIn, [
'walk']),
State.State('tunnelOut',
State('tunnelOut',
self.enterTunnelOut,
self.exitTunnelOut, [
'final']),
State.State('quest',
State('quest',
self.enterQuest,
self.exitQuest, [
'walk']),
State.State('purchase',
State('purchase',
self.enterPurchase,
self.exitPurchase, [
'walk']),
State.State('stopped',
State('stopped',
self.enterStopped,
self.exitStopped, [
'walk']),
State.State('fishing',
State('fishing',
self.enterFishing,
self.exitFishing, [
'walk']),
State.State('final',
State('final',
self.enterFinal,
self.exitFinal, [
'start'])],
@ -195,7 +199,6 @@ class Playground(Place.Place):
self.npcfaDoneEvent = 'npcfaDoneEvent'
self.dialog = None
self.deathAckBox = None
return
def enter(self, requestStatus):
self.fsm.enterInitialState()
@ -203,7 +206,7 @@ class Playground(Place.Place):
self.accept('doorDoneEvent', self.handleDoorDoneEvent)
self.accept('DistributedDoor_doorTrigger', self.handleDoorTrigger)
base.playMusic(self.loader.music, looping=1, volume=0.8)
self.loader.geom.reparentTo(render)
self.loader.geom.reparentTo(base.render)
for i in self.loader.nodeList:
self.loader.enterAnimatedProps(i)
@ -231,12 +234,14 @@ class Playground(Place.Place):
self.loader.hood.startSky()
lightsOn = LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 0.1, Vec4(1, 1, 1, 1))
lightsOn.start()
NametagGlobals.setMasterArrowsOn(1)
self.zoneId = requestStatus['zoneId']
self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.loader.nodeList, self.zoneId)
how = requestStatus['how']
if how == 'teleportIn':
how = 'deathAck'
self.fsm.request(how, [requestStatus])
def exit(self):
@ -248,13 +253,12 @@ class Playground(Place.Place):
node.removeNode()
del self.tunnelOriginList
self.loader.geom.reparentTo(hidden)
self.loader.geom.reparentTo(base.hidden)
def __lightDecorationOff__():
for light in self.loader.hood.halloweenLights:
light.reparentTo(hidden)
light.reparentTo(base.hidden)
newsManager = base.cr.newsManager
NametagGlobals.setMasterArrowsOn(0)
for i in self.loader.nodeList:
self.loader.exitAnimatedProps(i)
@ -263,7 +267,7 @@ class Playground(Place.Place):
self.loader.music.stop()
def load(self):
Place.Place.load(self)
Place.load(self)
self.parentFSM.getStateNamed('playground').addChild(self.fsm)
def unload(self):
@ -273,13 +277,14 @@ class Playground(Place.Place):
if self.dialog:
self.dialog.cleanup()
self.dialog = None
if self.deathAckBox:
self.deathAckBox.cleanup()
self.deathAckBox = None
TTDialog.cleanupDialog('globalDialog')
self.ignoreAll()
Place.Place.unload(self)
return
Place.unload(self)
def showTreasurePoints(self, points):
self.hideDebugPointText()
@ -303,7 +308,6 @@ class Playground(Place.Place):
self.hideDebugPointText()
lines = LineSegs()
lines.setColor(1, 0, 0, 1)
from toontown.classicchars import CCharPaths
for name, pointDef in list(paths.items()):
self.showDebugPointText(name, pointDef[0])
for connectTo in pointDef[1]:
@ -333,6 +337,7 @@ class Playground(Place.Place):
self.debugTextNode.setTextColor(1, 0, 0, 1)
self.debugTextNode.setAlign(TextNode.ACenter)
self.debugTextNode.setFont(ToontownGlobals.getSignFont())
self.debugTextNode.setText(text)
np = self.debugText.attachNewNode(self.debugTextNode.generate())
np.setPos(point[0], point[1], point[2])
@ -344,7 +349,7 @@ class Playground(Place.Place):
base.localAvatar.b_setAnimState('off', 1)
base.localAvatar.cantLeaveGame = 1
self.accept(self.trolleyDoneEvent, self.handleTrolleyDone)
self.trolley = Trolley.Trolley(self, self.fsm, self.trolleyDoneEvent)
self.trolley = Trolley(self, self.fsm, self.trolleyDoneEvent)
self.trolley.load()
self.trolley.enter()
@ -376,7 +381,6 @@ class Playground(Place.Place):
messenger.send(self.doneEvent)
else:
self.notify.error('Unknown mode: ' + mode + ' in handleTrolleyDone')
return
def debugStartMinigame(self, zoneId, minigameId):
self.doneStatus = {'loader': 'minigame',
@ -386,7 +390,6 @@ class Playground(Place.Place):
'shardId': None,
'minigameId': minigameId}
messenger.send(self.doneEvent)
return
def enterTFACallback(self, requestStatus, doneStatus):
self.tfa.exit()
@ -412,7 +415,7 @@ class Playground(Place.Place):
def enterHFA(self, requestStatus):
self.acceptOnce(self.hfaDoneEvent, self.enterHFACallback, [requestStatus])
self.hfa = HealthForceAcknowledge.HealthForceAcknowledge(self.hfaDoneEvent)
self.hfa = HealthForceAcknowledge(self.hfaDoneEvent)
self.hfa.enter(1)
def exitHFA(self):
@ -428,6 +431,7 @@ class Playground(Place.Place):
outHow = {'teleportIn': 'teleportOut',
'tunnelIn': 'tunnelOut',
'doorIn': 'doorOut'}
self.fsm.request(outHow[requestStatus['how']], [requestStatus])
elif doneStatus['mode'] == 'incomplete':
self.fsm.request('HFAReject')
@ -442,7 +446,7 @@ class Playground(Place.Place):
def enterNPCFA(self, requestStatus):
self.acceptOnce(self.npcfaDoneEvent, self.enterNPCFACallback, [requestStatus])
self.npcfa = NPCForceAcknowledge.NPCForceAcknowledge(self.npcfaDoneEvent)
self.npcfa = NPCForceAcknowledge(self.npcfaDoneEvent)
self.npcfa.enter()
def exitNPCFA(self):
@ -469,20 +473,18 @@ class Playground(Place.Place):
self.ignore('deathAck')
self.deathAckBox.cleanup()
self.deathAckBox = None
Place.Place.enterWalk(self, teleportIn)
return
Place.enterWalk(self, teleportIn)
def enterDeathAck(self, requestStatus):
self.deathAckBox = None
self.fsm.request('teleportIn', [requestStatus])
return
def exitDeathAck(self):
if self.deathAckBox:
self.ignore('deathAck')
self.deathAckBox.cleanup()
self.deathAckBox = None
return
def enterTeleportIn(self, requestStatus):
imgScale = 0.25
@ -492,10 +494,10 @@ class Playground(Place.Place):
requestStatus['nextState'] = 'popup'
x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(self.loader.hood.id)
self.accept('deathAck', self.__handleDeathAck, extraArgs=[requestStatus])
self.deathAckBox = DeathForceAcknowledge.DeathForceAcknowledge(doneEvent='deathAck')
self.deathAckBox = DeathForceAcknowledge(doneEvent='deathAck')
elif base.localAvatar.hp > 0 and (Quests.avatarHasTrolleyQuest(base.localAvatar) or Quests.avatarHasFirstCogQuest(base.localAvatar) or Quests.avatarHasFriendQuest(base.localAvatar) or Quests.avatarHasPhoneQuest(base.localAvatar) and Quests.avatarHasCompletedPhoneQuest(base.localAvatar)) and self.loader.hood.id == ToontownGlobals.ToontownCentral:
requestStatus['nextState'] = 'popup'
imageModel = loader.loadModel('phase_4/models/gui/tfa_images')
imageModel = base.loader.loadModel('phase_4/models/gui/tfa_images')
if base.localAvatar.quests[0][0] == Quests.TROLLEY_QUEST_ID:
if not Quests.avatarHasCompletedTrolleyQuest(base.localAvatar):
x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(base.cr.hoodMgr.ToontownCentralInitialDropPoints)
@ -526,7 +528,7 @@ class Playground(Place.Place):
if not Quests.avatarHasCompletedFriendQuest(base.localAvatar):
x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(base.cr.hoodMgr.ToontownCentralInitialDropPoints)
msg = TTLocalizer.NPCForceAcknowledgeMessage7
gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
gui = base.loader.loadModel('phase_3.5/models/gui/friendslist_gui')
imgNodePath = gui.find('**/FriendsBox_Closed')
imgPos = (0, 0, 0.04)
imgScale = 1.0
@ -544,38 +546,40 @@ class Playground(Place.Place):
imgNodePath = imageModel.find('**/hq-dialog-image')
imgPos = (0, 0, 0.05)
imgScale = 0.5
self.dialog = TTDialog.TTDialog(text=msg, command=self.__cleanupDialog, style=TTDialog.Acknowledge)
imgLabel = DirectLabel.DirectLabel(parent=self.dialog, relief=None, pos=imgPos, scale=TTLocalizer.PimgLabel, image=imgNodePath, image_scale=imgScale)
imgLabel = DirectLabel(parent=self.dialog, relief=None, pos=imgPos, scale=TTLocalizer.PimgLabel, image=imgNodePath, image_scale=imgScale)
imageModel.removeNode()
else:
requestStatus['nextState'] = 'walk'
x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(self.loader.hood.id)
base.localAvatar.detachNode()
base.localAvatar.setPosHpr(render, x, y, z, h, p, r)
Place.Place.enterTeleportIn(self, requestStatus)
return
base.localAvatar.setPosHpr(base.render, x, y, z, h, p, r)
Place.enterTeleportIn(self, requestStatus)
def __cleanupDialog(self, value):
if self.dialog:
self.dialog.cleanup()
self.dialog = None
if hasattr(self, 'fsm'):
self.fsm.request('walk', [1])
return
def __handleDeathAck(self, requestStatus):
if self.deathAckBox:
self.ignore('deathAck')
self.deathAckBox.cleanup()
self.deathAckBox = None
self.fsm.request('walk', [1])
return
def enterPopup(self, teleportIn = 0):
if base.localAvatar.hp < 1:
base.localAvatar.b_setAnimState('Sad', 1)
else:
base.localAvatar.b_setAnimState('neutral', 1.0)
self.accept('teleportQuery', self.handleTeleportQuery)
base.localAvatar.setTeleportAvailable(1)
base.localAvatar.startSleepWatch(self.__handleFallingAsleepPopup)
@ -589,18 +593,19 @@ class Playground(Place.Place):
if hasattr(self, 'fsm'):
self.fsm.request('walk')
base.localAvatar.forceGotoSleep()
return Task.done
return task.done
def enterTeleportOut(self, requestStatus):
Place.Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone)
Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone)
def __teleportOutDone(self, requestStatus):
teleportDebug(requestStatus, 'Playground.__teleportOutDone(%s)' % (requestStatus,))
if hasattr(self, 'activityFsm'):
self.activityFsm.requestFinalState()
hoodId = requestStatus['hoodId']
zoneId = requestStatus['zoneId']
avId = requestStatus['avId']
shardId = requestStatus['shardId']
if hoodId == self.loader.hood.hoodId and zoneId == self.loader.hood.hoodId and shardId == None:
teleportDebug(requestStatus, 'same playground')
@ -612,19 +617,19 @@ class Playground(Place.Place):
teleportDebug(requestStatus, 'different hood/zone')
self.doneStatus = requestStatus
messenger.send(self.doneEvent)
return
def exitTeleportOut(self):
Place.Place.exitTeleportOut(self)
Place.exitTeleportOut(self)
def createPlayground(self, dnaFile):
loader.loadDNAFile(self.loader.dnaStore, self.safeZoneStorageDNAFile)
node = loader.loadDNAFile(self.loader.dnaStore, dnaFile)
base.loader.loadDNAFile(self.loader.dnaStore, self.safeZoneStorageDNAFile)
node = base.loader.loadDNAFile(self.loader.dnaStore, dnaFile)
if node.getNumParents() == 1:
self.geom = NodePath(node.getParent(0))
self.geom.reparentTo(hidden)
self.geom.reparentTo(base.hidden)
else:
self.geom = hidden.attachNewNode(node)
self.geom = base.hidden.attachNewNode(node)
self.makeDictionaries(self.loader.dnaStore)
self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.nodeList, self.zoneId)
self.geom.flattenMedium()
@ -636,10 +641,10 @@ class Playground(Place.Place):
self.nodeList = []
for i in range(dnaStore.getNumDNAVisGroups()):
groupFullName = dnaStore.getDNAVisGroupName(i)
groupName = base.cr.hoodMgr.extractGroupName(groupFullName)
groupNode = self.geom.find('**/' + groupFullName)
if groupNode.isEmpty():
self.notify.error('Could not find visgroup')
self.nodeList.append(groupNode)
self.removeLandmarkBlockNodes()
@ -655,7 +660,7 @@ class Playground(Place.Place):
def enterTFA(self, requestStatus):
self.acceptOnce(self.tfaDoneEvent, self.enterTFACallback, [requestStatus])
self.tfa = TutorialForceAcknowledge.TutorialForceAcknowledge(self.tfaDoneEvent)
self.tfa = TutorialForceAcknowledge(self.tfaDoneEvent)
self.tfa.enter()
def exitTFA(self):