class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): deferFor = 1 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 return def generate(self): DistributedObject.DistributedObject.generate(self) self.avatarTracks = [] self.avatarExitTracks = [] self.avatarIDList = [] self.avatarExitIDList = [] self.doorTrack = None self.doorExitTrack = None return 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 self.__dict__.has_key('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: # Avoid duplicated nametags (eg hq doors) 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) self.nametag.setAvatar(self.getDoorNodePath()) self.nametag.setObjectCode(self.block) name = self.cr.playGame.dnaStore.getTitleFromBlockNumber(self.block) self.nametag.setName(name) self.nametag.manage(base.marginManager) 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.specialDoorTypes.has_key(self.doorType): return 'door_trigger_' + str(self.block) + '_' + str(self.doorIndex) else: return 'door_trigger_' + str(self.block) def getEnterTriggerEvent(self): return 'enter' + self.getTriggerName() def getExitTriggerEvent(self): return 'exit' + self.getTriggerName() def hideDoorParts(self): if self.specialDoorTypes.has_key(self.doorType): self.hideIfHasFlat(self.findDoorNode('rightDoor')) self.hideIfHasFlat(self.findDoorNode('leftDoor')) self.findDoorNode('doorFrameHoleRight').hide() self.findDoorNode('doorFrameHoleLeft').hide() def setTriggerName(self): if self.specialDoorTypes.has_key(self.doorType) or self.doorType == DoorTypes.EXT_STANDARD: building = self.getBuilding() pattern = '**/door_' + str(self.doorIndex) + '/**/door_trigger*' if self.doorType == DoorTypes.EXT_STANDARD: pattern = '**/door_trigger*' doorTrigger = building.find(pattern) if doorTrigger: doorTrigger.setY(doorTrigger, -3 if self.doorType != DoorTypes.EXT_STANDARD else 0) doorTrigger.node().setName(self.getTriggerName()) if __debug__: doorTrigger.show() # hacky: hard coded fixes if 'hq' in repr(building.getName()): y = 3 doorTrigger.setY(doorTrigger, y) if self.zoneId == 8000: # goofy speedway doorTrigger.setY(doorTrigger, 3) if self.doorType == DoorTypes.INT_KS: doorTrigger.setY(doorTrigger, 3) 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): if self.doorType == DoorTypes.INT_STANDARD: self.bHasFlat = True else: self.bHasFlat = not self.findDoorNode('door*flat', True).isEmpty() self.hideDoorParts() self.setTriggerName() 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 in (DoorTypes.EXT_STANDARD, DoorTypes.EXT_HQ, 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 in (DoorTypes.EXT_COGHQ, 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 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 < -0.5 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, zoneId = None): allowed = True return allowed 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()) return 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) return 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: if hasattr(self, 'tempDoorNodePath'): return self.tempDoorNodePath else: posHpr = self.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(self.block) otherNP = NodePath('doorOrigin') otherNP.setPos(posHpr.getPos()) otherNP.setHpr(posHpr.getHpr()) self.tempDoorNodePath = otherNP elif self.specialDoorTypes.has_key(self.doorType): 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 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) 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.6, 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') foundNode = NodePath() 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()
class DistributedElevatorExt(DistributedElevator.DistributedElevator): def __init__(self, cr): DistributedElevator.DistributedElevator.__init__(self, cr) self.nametag = None self.currentFloor = -1 self.__setFloorNumber = None return def setupElevator(self): if self.isSetup: self.elevatorSphereNodePath.removeNode() self.leftDoor = self.bldg.leftDoor self.rightDoor = self.bldg.rightDoor DistributedElevator.DistributedElevator.setupElevator(self) self.setupNametag() def disable(self): self.clearNametag() DistributedElevator.DistributedElevator.disable(self) def setupNametag(self): 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.CCSuitBuilding) self.nametag.setActive(0) self.nametag.setAvatar(self.getElevatorModel()) name = self.cr.playGame.dnaStore.getTitleFromBlockNumber(self.bldg.block) if self.bldg.mode == 'cogdo' and not name: name = TTLocalizer.Cogdominiums elif self.bldg.mode == 'cogdo': name += TTLocalizer.CogdominiumsExt elif not name: name = TTLocalizer.CogsInc else: name += TTLocalizer.CogsIncExt 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.destroy() self.nametag = None return def getBldgDoorOrigin(self): return self.bldg.getSuitDoorOrigin() def gotBldg(self, buildingList): self.bldgRequest = None self.bldg = buildingList[0] if not self.bldg: self.notify.error('setBldgDoId: elevator %d cannot find bldg %d!' % (self.doId, self.bldgDoId)) return else: if self.getBldgDoorOrigin(): self.bossLevel = self.bldg.getBossLevel() self.setupElevator() else: self.notify.warning('setBldgDoId: elevator %d cannot find suitDoorOrigin for bldg %d!' % (self.doId, self.bldgDoId)) if self.__setFloorNumber is not None: self.setFloor(self.__setFloorNumber) return def setFloor(self, floorNumber): if not hasattr(self, 'bldg'): self.__setFloorNumber = floorNumber return if self.currentFloor >= 0: if self.bldg.floorIndicator[self.currentFloor]: self.bldg.floorIndicator[self.currentFloor].setColor(LIGHT_OFF_COLOR) if floorNumber >= 0: if self.bldg.floorIndicator[floorNumber]: self.bldg.floorIndicator[floorNumber].setColor(LIGHT_ON_COLOR) self.currentFloor = floorNumber def handleEnterSphere(self, collEntry): self.notify.debug('Entering Elevator Sphere....') if hasattr(localAvatar, 'boardingParty') and localAvatar.boardingParty and localAvatar.boardingParty.getGroupLeader(localAvatar.doId) and localAvatar.boardingParty.getGroupLeader(localAvatar.doId) != localAvatar.doId: base.localAvatar.elevatorNotifier.showMe(TTLocalizer.ElevatorGroupMember) elif self.allowedToEnter(self.zoneId): self.cr.playGame.getPlace().detectedElevatorCollision(self) else: place = base.cr.playGame.getPlace() if place: place.fsm.request('stopped') self.dialog = TeaserPanel.TeaserPanel(pageName='cogHQ', doneFunc=self.handleOkTeaser) def handleEnterElevator(self): if hasattr(localAvatar, 'boardingParty') and localAvatar.boardingParty and localAvatar.boardingParty.getGroupLeader(localAvatar.doId): if localAvatar.boardingParty.getGroupLeader(localAvatar.doId) == localAvatar.doId: localAvatar.boardingParty.handleEnterElevator(self) elif self.elevatorTripId and localAvatar.lastElevatorLeft == self.elevatorTripId: self.rejectBoard(base.localAvatar.doId, REJECT_SHUFFLE) elif base.localAvatar.hp > 0: toon = base.localAvatar self.sendUpdate('requestBoard', []) else: self.notify.warning('Tried to board elevator with hp: %d' % base.localAvatar.hp) def enterWaitEmpty(self, ts): self.elevatorSphereNodePath.unstash() self.forceDoorsOpen() self.accept(self.uniqueName('enterelevatorSphere'), self.handleEnterSphere) self.accept(self.uniqueName('enterElevatorOK'), self.handleEnterElevator) DistributedElevator.DistributedElevator.enterWaitEmpty(self, ts) def exitWaitEmpty(self): self.elevatorSphereNodePath.stash() self.ignore(self.uniqueName('enterelevatorSphere')) self.ignore(self.uniqueName('enterElevatorOK')) DistributedElevator.DistributedElevator.exitWaitEmpty(self) def enterWaitCountdown(self, ts): DistributedElevator.DistributedElevator.enterWaitCountdown(self, ts) self.forceDoorsOpen() self.accept(self.uniqueName('enterElevatorOK'), self.handleEnterElevator) self.startCountdownClock(self.countdownTime, ts) def exitWaitCountdown(self): self.ignore(self.uniqueName('enterElevatorOK')) DistributedElevator.DistributedElevator.exitWaitCountdown(self) def getZoneId(self): return self.bldg.interiorZoneId def getElevatorModel(self): np = self.bldg.getSuitElevatorNodePath() if np.isEmpty(): self.notify.error("np not ok") return self.bldg.getSuitElevatorNodePath()
class Avatar(Actor, ShadowCaster): notify = directNotify.newCategory('Avatar') ActiveAvatars = [] ManagesNametagAmbientLightChanged = False def __init__(self, other = None): self.name = '' try: self.Avatar_initialized return except: self.Avatar_initialized = 1 Actor.__init__(self, None, None, other, flattenable=0, setFinal=0) ShadowCaster.__init__(self) self.__font = OTPGlobals.getInterfaceFont() self.__speechFont = OTPGlobals.getInterfaceFont() self.soundChatBubble = None self.avatarType = '' self.nametagNodePath = None self.__nameVisible = 1 self.nametag = NametagGroup() self.nametag.setAvatar(self) self.nametag.setFont(OTPGlobals.getInterfaceFont()) self.nametag.setSpeechFont(OTPGlobals.getInterfaceFont()) self.nametag2dContents = Nametag.CName | Nametag.CSpeech self.nametag2dDist = Nametag.CName | Nametag.CSpeech self.nametag2dNormalContents = Nametag.CName | Nametag.CSpeech self.nametag3d = self.attachNewNode('nametag3d') self.nametag3d.setTag('cam', 'nametag') self.nametag3d.setLightOff() if self.ManagesNametagAmbientLightChanged: self.acceptNametagAmbientLightChange() OTPRender.renderReflection(False, self.nametag3d, 'otp_avatar_nametag', None) self.getGeomNode().showThrough(OTPRender.ShadowCameraBitmask) self.nametag3d.hide(OTPRender.ShadowCameraBitmask) self.collTube = None self.battleTube = None self.scale = 1.0 self.nametagScale = 1.0 self.height = 0.0 self.battleTubeHeight = 0.0 self.battleTubeRadius = 0.0 self.style = None self.commonChatFlags = 0 self.understandable = 1 self.setPlayerType(NametagGroup.CCNormal) self.ghostMode = 0 self.__chatParagraph = None self.__chatMessage = None self.__chatFlags = 0 self.__chatPageNumber = None self.__chatAddressee = None self.__chatDialogueList = [] self.__chatSet = 0 self.__chatLocal = 0 self.__currentDialogue = None self.whitelistChatFlags = 0 self.wantAdminTag = True return def delete(self): try: self.Avatar_deleted except: self.deleteNametag3d() Actor.cleanup(self) if self.ManagesNametagAmbientLightChanged: self.ignoreNametagAmbientLightChange() self.Avatar_deleted = 1 del self.__font del self.__speechFont del self.style del self.soundChatBubble self.nametag.destroy() del self.nametag self.nametag3d.removeNode() ShadowCaster.delete(self) Actor.delete(self) def acceptNametagAmbientLightChange(self): self.accept('nametagAmbientLightChanged', self.nametagAmbientLightChanged) def ignoreNametagAmbientLightChange(self): self.ignore('nametagAmbientLightChanged') def isLocal(self): return 0 def isPet(self): return False def isProxy(self): return False def setPlayerType(self, playerType): self.playerType = playerType if not hasattr(self, 'nametag'): self.notify.warning('no nametag attributed, but would have been used.') return if self.isUnderstandable(): self.nametag.setColorCode(self.playerType) else: self.nametag.setColorCode(NametagGroup.CCNoChat) self.setNametagName() def setCommonChatFlags(self, commonChatFlags): self.commonChatFlags = commonChatFlags self.considerUnderstandable() if self == base.localAvatar: reconsiderAllUnderstandable() def setWhitelistChatFlags(self, whitelistChatFlags): self.whitelistChatFlags = whitelistChatFlags self.considerUnderstandable() if self == base.localAvatar: reconsiderAllUnderstandable() def considerUnderstandable(self): speed = 0 if self.playerType in (NametagGroup.CCNormal, NametagGroup.CCFreeChat, NametagGroup.CCSpeedChat): self.setPlayerType(NametagGroup.CCSpeedChat) speed = 1 if hasattr(base, 'localAvatar') and self == base.localAvatar: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif self.playerType == NametagGroup.CCSuit: self.understandable = 1 self.setPlayerType(NametagGroup.CCSuit) elif self.playerType not in (NametagGroup.CCNormal, NametagGroup.CCFreeChat, NametagGroup.CCSpeedChat): self.understandable = 1 self.setPlayerType(NametagGroup.CCNoChat) elif hasattr(base, 'localAvatar') and self.commonChatFlags & base.localAvatar.commonChatFlags & OTPGlobals.CommonChat: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif self.commonChatFlags & OTPGlobals.SuperChat: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif hasattr(base, 'localAvatar') and base.localAvatar.commonChatFlags & OTPGlobals.SuperChat: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif base.cr.getFriendFlags(self.doId) & OTPGlobals.FriendChat: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif base.cr.playerFriendsManager.findPlayerIdFromAvId(self.doId) is not None: playerInfo = base.cr.playerFriendsManager.findPlayerInfoFromAvId(self.doId) if playerInfo.openChatFriendshipYesNo: self.understandable = 1 self.nametag.setColorCode(NametagGroup.CCFreeChat) elif playerInfo.isUnderstandable(): self.understandable = 1 else: self.understandable = 0 if hasattr(self, 'adminAccess') and self != base.localAvatar: self.understandable = 2 elif hasattr(base, 'localAvatar') and self.whitelistChatFlags & base.localAvatar.whitelistChatFlags: self.understandable = 1 else: self.understandable = 0 if not hasattr(self, 'nametag'): self.notify.warning('no nametag attributed, but would have been used') else: self.nametag.setColorCode(self.playerType) return def isUnderstandable(self): return self.understandable def setDNAString(self, dnaString): pass def setDNA(self, dna): pass def getAvatarScale(self): return self.scale def setAvatarScale(self, scale): if self.scale != scale: self.scale = scale self.getGeomNode().setScale(scale) self.setHeight(self.height) def getNametagScale(self): return self.nametagScale def setNametagScale(self, scale): self.nametagScale = scale self.nametag3d.setScale(scale) def adjustNametag3d(self, parentScale = 1.0): self.nametag3d.setPos(0, 0, self.height + 0.5) def getHeight(self): return self.height def setHeight(self, height): self.height = height self.adjustNametag3d() if self.collTube: self.collTube.setPointB(0, 0, height - self.getRadius()) if self.collNodePath: self.collNodePath.forceRecomputeBounds() if self.battleTube: self.battleTube.setPointB(0, 0, height - self.getRadius()) def getRadius(self): return OTPGlobals.AvatarDefaultRadius def getName(self): return self.name def getType(self): return self.avatarType def setWantAdminTag(self, bool): self.wantAdminTag = bool def getWantAdminTag(self): return self.wantAdminTag def setName(self, name): if hasattr(self, 'isDisguised') and self.isDisguised: return self.name = name if hasattr(self, 'nametag'): self.setNametagName() def setDisplayName(self, str): if hasattr(self, 'isDisguised'): if self.isDisguised: return self.setNametagName(str) def setNametagName(self, name=None): if not name: name = self.name self.nametag.setName(name) if hasattr(self, 'adminAccess') and self.getWantAdminTag(): access = self.getAdminAccess() if access in OTPLocalizer.AccessToString: name += '\n\x01shadow\x01%s\x02' % OTPLocalizer.AccessToString[access] self.nametag.setDisplayName(name) def getFont(self): return self.__font def setFont(self, font): self.__font = font self.nametag.setFont(font) def getSpeechFont(self): return self.__speechFont def setSpeechFont(self, font): self.__speechFont = font self.nametag.setSpeechFont(font) def getStyle(self): return self.style def setStyle(self, style): self.style = style def getDialogueArray(self): return None def playCurrentDialogue(self, dialogue, chatFlags, interrupt = 1): if interrupt and self.__currentDialogue is not None: self.__currentDialogue.stop() self.__currentDialogue = dialogue if dialogue: base.playSfx(dialogue, node=self) elif chatFlags & CFSpeech != 0 and self.nametag.getNumChatPages() > 0: self.playDialogueForString(self.nametag.getChat()) if self.soundChatBubble != None: base.playSfx(self.soundChatBubble, node=self) return def playDialogueForString(self, chatString): searchString = chatString.lower() if searchString.find(OTPLocalizer.DialogSpecial) >= 0: type = 'special' elif searchString.find(OTPLocalizer.DialogExclamation) >= 0: type = 'exclamation' elif searchString.find(OTPLocalizer.DialogQuestion) >= 0: type = 'question' elif random.randint(0, 1): type = 'statementA' else: type = 'statementB' stringLength = len(chatString) if stringLength <= OTPLocalizer.DialogLength1: length = 1 elif stringLength <= OTPLocalizer.DialogLength2: length = 2 elif stringLength <= OTPLocalizer.DialogLength3: length = 3 else: length = 4 self.playDialogue(type, length) def playDialogue(self, type, length): dialogueArray = self.getDialogueArray() if dialogueArray == None: return sfxIndex = None if type == 'statementA' or type == 'statementB': if length == 1: sfxIndex = 0 elif length == 2: sfxIndex = 1 elif length >= 3: sfxIndex = 2 elif type == 'question': sfxIndex = 3 elif type == 'exclamation': sfxIndex = 4 elif type == 'special': sfxIndex = 5 else: notify.error('unrecognized dialogue type: ', type) # The standard cog phrase gets too repetitive when there are so many cogs running around. # Let's just choose a random one. if config.GetBool('want-doomsday', False) and self.playerType == NametagGroup.CCSuit: sfxIndex = random.choice([1, 2, 2, 2, 2, 3, 3, 3]) #Duplicates are Intentional if sfxIndex != None and sfxIndex < len(dialogueArray) and dialogueArray[sfxIndex] != None: base.playSfx(dialogueArray[sfxIndex], node=self) return def getDialogueSfx(self, type, length): retval = None dialogueArray = self.getDialogueArray() if dialogueArray == None: return sfxIndex = None if type == 'statementA' or type == 'statementB': if length == 1: sfxIndex = 0 elif length == 2: sfxIndex = 1 elif length >= 3: sfxIndex = 2 elif type == 'question': sfxIndex = 3 elif type == 'exclamation': sfxIndex = 4 elif type == 'special': sfxIndex = 5 else: notify.error('unrecognized dialogue type: ', type) if sfxIndex != None and sfxIndex < len(dialogueArray) and dialogueArray[sfxIndex] != None: retval = dialogueArray[sfxIndex] return retval def setChatAbsolute(self, chatString, chatFlags, dialogue = None, interrupt = 1): self.clearChat() self.nametag.setChat(chatString, chatFlags) self.playCurrentDialogue(dialogue, chatFlags, interrupt) def setChatMuted(self, chatString, chatFlags, dialogue = None, interrupt = 1, quiet = 0): pass def displayTalk(self, chatString): if not base.cr.avatarFriendsManager.checkIgnored(self.doId): if base.talkAssistant.isThought(chatString): self.nametag.setChat(base.talkAssistant.removeThoughtPrefix(chatString), CFThought) else: self.nametag.setChat(chatString, CFSpeech | CFTimeout) def clearChat(self): self.nametag.clearChat() def isInView(self): pos = self.getPos(camera) eyePos = Point3(pos[0], pos[1], pos[2] + self.getHeight()) return base.camNode.isInView(eyePos) def getNameVisible(self): return self.__nameVisible def setNameVisible(self, bool): self.__nameVisible = bool if bool: self.showName() if not bool: self.hideName() def hideName(self): self.nametag.getNametag3d().setContents(Nametag.CSpeech | Nametag.CThought) def showName(self): if self.__nameVisible and not self.ghostMode: self.nametag.getNametag3d().setContents(Nametag.CName | Nametag.CSpeech | Nametag.CThought) def hideNametag2d(self): self.nametag2dContents = 0 self.nametag.getNametag2d().setContents(self.nametag2dContents & self.nametag2dDist) def showNametag2d(self): self.nametag2dContents = self.nametag2dNormalContents if self.ghostMode: self.nametag2dContents = Nametag.CSpeech self.nametag.getNametag2d().setContents(self.nametag2dContents & self.nametag2dDist) def hideNametag3d(self): self.nametag.getNametag3d().setContents(0) def showNametag3d(self): if self.__nameVisible and not self.ghostMode: self.nametag.getNametag3d().setContents(Nametag.CName | Nametag.CSpeech | Nametag.CThought) else: self.nametag.getNametag3d().setContents(0) def setPickable(self, flag): self.nametag.setActive(flag) def clickedNametag(self): MagicWordManager.lastClickedNametag = self if self.nametag.hasButton(): self.advancePageNumber() elif self.nametag.isActive(): messenger.send('clickedNametag', [self]) def setPageChat(self, addressee, paragraph, message, quitButton, extraChatFlags = None, dialogueList = [], pageButton = True): self.__chatAddressee = addressee self.__chatPageNumber = None self.__chatParagraph = paragraph self.__chatMessage = message if extraChatFlags is None: self.__chatFlags = CFSpeech else: self.__chatFlags = CFSpeech | extraChatFlags self.__chatDialogueList = dialogueList self.__chatSet = 0 self.__chatLocal = 0 self.__updatePageChat() if addressee == base.localAvatar.doId: if pageButton: self.__chatFlags |= CFPageButton if quitButton == None: self.__chatFlags |= CFNoQuitButton elif quitButton: self.__chatFlags |= CFQuitButton self.b_setPageNumber(self.__chatParagraph, 0) return def setLocalPageChat(self, message, quitButton, extraChatFlags = None, dialogueList = []): self.__chatAddressee = base.localAvatar.doId self.__chatPageNumber = None self.__chatParagraph = None self.__chatMessage = message if extraChatFlags is None: self.__chatFlags = CFSpeech else: self.__chatFlags = CFSpeech | extraChatFlags self.__chatDialogueList = dialogueList self.__chatSet = 1 self.__chatLocal = 1 self.__chatFlags |= CFPageButton if quitButton == None: self.__chatFlags |= CFNoQuitButton elif quitButton: self.__chatFlags |= CFQuitButton if len(dialogueList) > 0: dialogue = dialogueList[0] else: dialogue = None self.clearChat() self.setChatAbsolute(message, self.__chatFlags, dialogue) self.setPageNumber(None, 0) return def setPageNumber(self, paragraph, pageNumber, timestamp = None): if timestamp == None: elapsed = 0.0 else: elapsed = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.__chatPageNumber = [paragraph, pageNumber] self.__updatePageChat() if hasattr(self, 'uniqueName'): if pageNumber >= 0: messenger.send(self.uniqueName('nextChatPage'), [pageNumber, elapsed]) else: messenger.send(self.uniqueName('doneChatPage'), [elapsed]) elif pageNumber >= 0: messenger.send('nextChatPage', [pageNumber, elapsed]) else: messenger.send('doneChatPage', [elapsed]) return def advancePageNumber(self): if self.__chatAddressee == base.localAvatar.doId and self.__chatPageNumber != None and self.__chatPageNumber[0] == self.__chatParagraph: pageNumber = self.__chatPageNumber[1] if pageNumber >= 0: pageNumber += 1 if pageNumber >= self.nametag.getNumChatPages(): pageNumber = -1 if self.__chatLocal: self.setPageNumber(self.__chatParagraph, pageNumber) else: self.b_setPageNumber(self.__chatParagraph, pageNumber) return def __updatePageChat(self): if self.__chatPageNumber != None and self.__chatPageNumber[0] == self.__chatParagraph: pageNumber = self.__chatPageNumber[1] if pageNumber >= 0: if not self.__chatSet: if len(self.__chatDialogueList) > 0: dialogue = self.__chatDialogueList[0] else: dialogue = None self.setChatAbsolute(self.__chatMessage, self.__chatFlags, dialogue) self.__chatSet = 1 if pageNumber < self.nametag.getNumChatPages(): self.nametag.setPageNumber(pageNumber) if pageNumber > 0: if len(self.__chatDialogueList) > pageNumber: dialogue = self.__chatDialogueList[pageNumber] else: dialogue = None self.playCurrentDialogue(dialogue, self.__chatFlags) else: self.clearChat() else: self.clearChat() return def getAirborneHeight(self): height = self.getPos(self.shadowPlacer.shadowNodePath) return height.getZ() + 0.025 def initializeNametag3d(self): self.deleteNametag3d() nametagNode = self.nametag.getNametag3d() self.nametagNodePath = self.nametag3d.attachNewNode(nametagNode) iconNodePath = self.nametag.getNameIcon() for cJoint in self.getNametagJoints(): cJoint.clearNetTransforms() cJoint.addNetTransform(nametagNode) def nametagAmbientLightChanged(self, newlight): self.nametag3d.setLightOff() if newlight: self.nametag3d.setLight(newlight) def deleteNametag3d(self): if self.nametagNodePath: self.nametagNodePath.removeNode() self.nametagNodePath = None return def initializeBodyCollisions(self, collIdStr): self.collTube = CollisionTube(0, 0, 0.5, 0, 0, self.height - self.getRadius(), self.getRadius()) self.collNode = CollisionNode(collIdStr) self.collNode.addSolid(self.collTube) self.collNodePath = self.attachNewNode(self.collNode) if self.ghostMode: self.collNode.setCollideMask(OTPGlobals.GhostBitmask) else: self.collNode.setCollideMask(OTPGlobals.WallBitmask) def stashBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.stash() def unstashBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.unstash() def disableBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.removeNode() del self.collNodePath self.collTube = None return def addActive(self): if base.wantNametags: try: Avatar.ActiveAvatars.remove(self) except ValueError: pass Avatar.ActiveAvatars.append(self) self.nametag.manage(base.marginManager) self.accept(self.nametag.getUniqueId(), self.clickedNametag) def removeActive(self): if base.wantNametags: try: Avatar.ActiveAvatars.remove(self) except ValueError: pass self.nametag.unmanage(base.marginManager) self.ignore(self.nametag.getUniqueId()) def loop(self, animName, restart = 1, partName = None, fromFrame = None, toFrame = None): return Actor.loop(self, animName, restart, partName, fromFrame, toFrame)
class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): def __init__(self, cr): DistributedObject.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', '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 return def generate(self): DistributedObject.DistributedObject.generate(self) self.avatarTracks = [] self.avatarExitTracks = [] self.avatarIDList = [] self.avatarExitIDList = [] self.doorTrack = None self.doorExitTrack = None return 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.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) self.nametag.setAvatar(self.getDoorNodePath()) self.nametag.setObjectCode(self.block) 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.destroy() self.nametag = None return def getTriggerName(self): if self.doorType == DoorTypes.INT_HQ or self.doorType in self.specialDoorTypes: return 'door_trigger_' + str(self.block) + '_' + str(self.doorIndex) 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): try: self.findDoorNode('doorFrameHoleRight').hide() self.findDoorNode('doorFrameHoleLeft').hide() except: pass if self.doorType in self.specialDoorTypes: self.hideIfHasFlat(self.findDoorNode('rightDoor')) self.hideIfHasFlat(self.findDoorNode('leftDoor')) def setTriggerName(self): if self.doorType in self.specialDoorTypes or self.doorType == DoorTypes.INT_HQ: building = self.getBuilding() doorTrigger = building.find('**/door_' + str(self.doorIndex) + '/**/door_trigger*') try: doorTrigger.setName(self.getTriggerName()) except: pass def hqTrigger(self): if self.doorType in [DoorTypes.EXT_STANDARD, DoorTypes.EXT_COGHQ]: building = self.getBuilding() doorTrigger = building.find('**/' + self.getTriggerName()) if not doorTrigger.isEmpty(): TRIGGER_SHIFT_Y = 0.25 TRIGGER_SHIFT_Z = 1.0 if '_gag_shop_' in building.getName(): doorTrigger.setY(doorTrigger.getY() + TRIGGER_SHIFT_Y) else: doorTrigger.setY(doorTrigger.getY() - TRIGGER_SHIFT_Y) doorTrigger.setZ(doorTrigger.getZ() + TRIGGER_SHIFT_Z) 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() self.hqTrigger() if self.doorType == DoorTypes.EXT_HQ and ZoneUtil.getHoodId(self.zoneId) == ToontownGlobals.DonaldsDreamland: building = self.getBuilding() doorTrigger = building.find('**/%s' % self.getTriggerName()) if not doorTrigger.getTag('fixed'): doorTrigger.setY(doorTrigger, 0.25 if not self.doorIndex else -0.25) 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') or not self.building: if self.doorType == DoorTypes.INT_STANDARD: door = render.find('**/*leftDoor*') 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 print '---------------- door is interior -------' 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 not otherNP: otherNP = render.find('**/door_origin_2') 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) 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 < -0.5 def enterDoor(self): if base.config.GetBool('want-doomsday', False): base.localAvatar.disableAvatarControls() self.confirm = TTDialog.TTGlobalDialog(doneEvent='confirmDone', message=SafezoneInvasionGlobals.LeaveToontownCentralAlert, style=TTDialog.Acknowledge) self.confirm.show() self.accept('confirmDone', self.handleConfirm) return if base.localAvatar.cameraFollow == 68: base.localAvatar.disableAvatarControls() self.confirm = TTDialog.TTGlobalDialog(doneEvent='confirmDone', message="You can't run away from this robot!", style=TTDialog.Acknowledge) self.confirm.show() self.accept('confirmDone', self.handleConfirm) return if base.cr.currentEpisode == 'gyro_tale': if ZoneUtil.getHoodId(self.zoneId) == ToontownGlobals.OldDaisyGardens and 'toon_landmark_DG_E1' not in self.getBuilding().getName(): return 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 handleConfirm(self): status = self.confirm.doneStatus self.ignore('confirmDone') self.confirm.cleanup() del self.confirm if status == 'ok': base.localAvatar.enableAvatarControls() self.accept(self.getExitTriggerEvent(), self.cancelCheckIsDoorHitTask) 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, zoneId=None): allowed = False if hasattr(base, 'ttAccess') and base.ttAccess: if zoneId: allowed = base.ttAccess.canAccess(zoneId) else: allowed = base.ttAccess.canAccess() return allowed 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): if base.localAvatar.doorIgnore: return 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()) return 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) return 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') else: if self.doorType == DoorTypes.EXT_STANDARD: otherNP = self.getBuilding().find('**/*door_origin') else: if self.specialDoorTypes.has_key(self.doorType): building = self.getBuilding() otherNP = building.find('**/door_origin_' + str(self.doorIndex)) else: if 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() if not otherNP: otherNP = render.find('**/door_origin_2') 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 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) 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: if self.zoneId == 21834: h = 180 else: h = 100 else: if self.zoneId == 21834: h = -180 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: if self.zoneId == 21834: h = 180 else: h = 100 else: if self.zoneId == 21834: h = -180 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.6, 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()
class Avatar(Actor, ShadowCaster): notify = directNotify.newCategory('Avatar') ActiveAvatars = [] ManagesNametagAmbientLightChanged = False def __init__(self, other=None): self.name = '' try: self.Avatar_initialized return except: self.Avatar_initialized = 1 Actor.__init__(self, None, None, other, flattenable=0, setFinal=0) ShadowCaster.__init__(self) self.__font = OTPGlobals.getInterfaceFont() self.__speechFont = OTPGlobals.getInterfaceFont() self.soundChatBubble = None self.avatarType = '' self.nametagNodePath = None self.__nameVisible = 1 self.nametag = NametagGroup() self.nametag.setAvatar(self) self.nametag.setFont(OTPGlobals.getInterfaceFont()) self.nametag.setSpeechFont(OTPGlobals.getInterfaceFont()) self.nametag2dContents = Nametag.CName | Nametag.CSpeech self.nametag2dDist = Nametag.CName | Nametag.CSpeech self.nametag2dNormalContents = Nametag.CName | Nametag.CSpeech self.nametag3d = self.attachNewNode('nametag3d') self.nametag3d.setTag('cam', 'nametag') self.nametag3d.setLightOff() if self.ManagesNametagAmbientLightChanged: self.acceptNametagAmbientLightChange() OTPRender.renderReflection(False, self.nametag3d, 'otp_avatar_nametag', None) self.getGeomNode().showThrough(OTPRender.ShadowCameraBitmask) self.nametag3d.hide(OTPRender.ShadowCameraBitmask) self.collTube = None self.battleTube = None self.scale = 1.0 self.nametagScale = 1.0 self.height = 0.0 self.battleTubeHeight = 0.0 self.battleTubeRadius = 0.0 self.style = None self.commonChatFlags = 0 self.understandable = 1 self.setPlayerType(NametagGroup.CCNormal) self.ghostMode = 0 self.__chatParagraph = None self.__chatMessage = None self.__chatFlags = 0 self.__chatPageNumber = None self.__chatAddressee = None self.__chatDialogueList = [] self.__chatSet = 0 self.__chatLocal = 0 self.__currentDialogue = None self.whitelistChatFlags = 0 return def delete(self): try: self.Avatar_deleted except: self.deleteNametag3d() Actor.cleanup(self) if self.ManagesNametagAmbientLightChanged: self.ignoreNametagAmbientLightChange() self.Avatar_deleted = 1 del self.__font del self.__speechFont del self.style del self.soundChatBubble self.nametag.destroy() del self.nametag self.nametag3d.removeNode() ShadowCaster.delete(self) Actor.delete(self) def acceptNametagAmbientLightChange(self): self.accept('nametagAmbientLightChanged', self.nametagAmbientLightChanged) def ignoreNametagAmbientLightChange(self): self.ignore('nametagAmbientLightChanged') def isLocal(self): return 0 def isPet(self): return False def isProxy(self): return False def setPlayerType(self, playerType): self.playerType = playerType if not hasattr(self, 'nametag'): self.notify.warning( 'no nametag attributed, but would have been used.') return if self.isUnderstandable(): self.nametag.setColorCode(self.playerType) else: self.nametag.setColorCode(NametagGroup.CCNoChat) def setCommonChatFlags(self, commonChatFlags): self.commonChatFlags = commonChatFlags self.considerUnderstandable() if self == base.localAvatar: reconsiderAllUnderstandable() def setWhitelistChatFlags(self, whitelistChatFlags): self.whitelistChatFlags = whitelistChatFlags self.considerUnderstandable() if self == base.localAvatar: reconsiderAllUnderstandable() def considerUnderstandable(self): speed = 0 if self.playerType in (NametagGroup.CCNormal, NametagGroup.CCFreeChat, NametagGroup.CCSpeedChat): self.setPlayerType(NametagGroup.CCSpeedChat) speed = 1 if hasattr(base, 'localAvatar') and self == base.localAvatar: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif self.playerType == NametagGroup.CCSuit: self.understandable = 1 self.setPlayerType(NametagGroup.CCSuit) elif self.playerType not in (NametagGroup.CCNormal, NametagGroup.CCFreeChat, NametagGroup.CCSpeedChat): self.understandable = 1 self.setPlayerType(NametagGroup.CCNoChat) elif hasattr( base, 'localAvatar' ) and self.commonChatFlags & base.localAvatar.commonChatFlags & OTPGlobals.CommonChat: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif self.commonChatFlags & OTPGlobals.SuperChat: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif hasattr( base, 'localAvatar' ) and base.localAvatar.commonChatFlags & OTPGlobals.SuperChat: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif base.cr.getFriendFlags(self.doId) & OTPGlobals.FriendChat: self.understandable = 1 self.setPlayerType(NametagGroup.CCFreeChat) elif base.cr.playerFriendsManager.findPlayerIdFromAvId( self.doId) is not None: playerInfo = base.cr.playerFriendsManager.findPlayerInfoFromAvId( self.doId) if playerInfo.openChatFriendshipYesNo: self.understandable = 1 self.nametag.setColorCode(NametagGroup.CCFreeChat) elif playerInfo.isUnderstandable(): self.understandable = 1 else: self.understandable = 0 elif hasattr( base, 'localAvatar' ) and self.whitelistChatFlags & base.localAvatar.whitelistChatFlags: self.understandable = 1 else: self.understandable = 0 if not hasattr(self, 'nametag'): self.notify.warning( 'no nametag attributed, but would have been used') else: self.nametag.setColorCode(self.playerType) return def isUnderstandable(self): return self.understandable def setDNAString(self, dnaString): pass def setDNA(self, dna): pass def getAvatarScale(self): return self.scale def setAvatarScale(self, scale): if self.scale != scale: self.scale = scale self.getGeomNode().setScale(scale) self.setHeight(self.height) def getNametagScale(self): return self.nametagScale def setNametagScale(self, scale): self.nametagScale = scale self.nametag3d.setScale(scale) def adjustNametag3d(self, parentScale=1.0): self.nametag3d.setPos(0, 0, self.height + 0.5) def getHeight(self): return self.height def setHeight(self, height): self.height = height self.adjustNametag3d() if self.collTube: self.collTube.setPointB(0, 0, height - self.getRadius()) if self.collNodePath: self.collNodePath.forceRecomputeBounds() if self.battleTube: self.battleTube.setPointB(0, 0, height - self.getRadius()) def getRadius(self): return OTPGlobals.AvatarDefaultRadius def getName(self): return self.name def getType(self): return self.avatarType def setName(self, name): if hasattr(self, 'isDisguised'): if self.isDisguised: return self.name = name if hasattr(self, 'nametag'): self.nametag.setName(name) def setDisplayName(self, str): if hasattr(self, 'isDisguised'): if self.isDisguised: return self.nametag.setDisplayName(str) def getFont(self): return self.__font def setFont(self, font): self.__font = font self.nametag.setFont(font) def getSpeechFont(self): return self.__speechFont def setSpeechFont(self, font): self.__speechFont = font self.nametag.setSpeechFont(font) def getStyle(self): return self.style def setStyle(self, style): self.style = style def getDialogueArray(self): return None def playCurrentDialogue(self, dialogue, chatFlags, interrupt=1): if interrupt and self.__currentDialogue is not None: self.__currentDialogue.stop() self.__currentDialogue = dialogue if dialogue: base.playSfx(dialogue, node=self) elif chatFlags & CFSpeech != 0 and self.nametag.getNumChatPages() > 0: self.playDialogueForString(self.nametag.getChat()) if self.soundChatBubble != None: base.playSfx(self.soundChatBubble, node=self) return def playDialogueForString(self, chatString): searchString = chatString.lower() if searchString.find(OTPLocalizer.DialogSpecial) >= 0: type = 'special' elif searchString.find(OTPLocalizer.DialogExclamation) >= 0: type = 'exclamation' elif searchString.find(OTPLocalizer.DialogQuestion) >= 0: type = 'question' elif random.randint(0, 1): type = 'statementA' else: type = 'statementB' stringLength = len(chatString) if stringLength <= OTPLocalizer.DialogLength1: length = 1 elif stringLength <= OTPLocalizer.DialogLength2: length = 2 elif stringLength <= OTPLocalizer.DialogLength3: length = 3 else: length = 4 self.playDialogue(type, length) def playDialogue(self, type, length): dialogueArray = self.getDialogueArray() if dialogueArray == None: return sfxIndex = None if type == 'statementA' or type == 'statementB': if length == 1: sfxIndex = 0 elif length == 2: sfxIndex = 1 elif length >= 3: sfxIndex = 2 elif type == 'question': sfxIndex = 3 elif type == 'exclamation': sfxIndex = 4 elif type == 'special': sfxIndex = 5 else: notify.error('unrecognized dialogue type: ', type) # The standard cog phrase gets too repetitive when there are so many cogs running around. # Let's just choose a random one. if config.GetBool('want-doomsday', False) and self.playerType == NametagGroup.CCSuit: sfxIndex = random.choice([1, 2, 2, 2, 2, 3, 3, 3]) #Duplicates are Intentional if sfxIndex != None and sfxIndex < len( dialogueArray) and dialogueArray[sfxIndex] != None: base.playSfx(dialogueArray[sfxIndex], node=self) return def getDialogueSfx(self, type, length): retval = None dialogueArray = self.getDialogueArray() if dialogueArray == None: return sfxIndex = None if type == 'statementA' or type == 'statementB': if length == 1: sfxIndex = 0 elif length == 2: sfxIndex = 1 elif length >= 3: sfxIndex = 2 elif type == 'question': sfxIndex = 3 elif type == 'exclamation': sfxIndex = 4 elif type == 'special': sfxIndex = 5 else: notify.error('unrecognized dialogue type: ', type) if sfxIndex != None and sfxIndex < len( dialogueArray) and dialogueArray[sfxIndex] != None: retval = dialogueArray[sfxIndex] return retval def setChatAbsolute(self, chatString, chatFlags, dialogue=None, interrupt=1): self.clearChat() self.nametag.setChat(chatString, chatFlags) self.playCurrentDialogue(dialogue, chatFlags, interrupt) def setChatMuted(self, chatString, chatFlags, dialogue=None, interrupt=1, quiet=0): pass def displayTalk(self, chatString): if not base.cr.avatarFriendsManager.checkIgnored(self.doId): if base.talkAssistant.isThought(chatString): self.nametag.setChat( base.talkAssistant.removeThoughtPrefix(chatString), CFThought) else: self.nametag.setChat(chatString, CFSpeech | CFTimeout) def clearChat(self): self.nametag.clearChat() def isInView(self): pos = self.getPos(camera) eyePos = Point3(pos[0], pos[1], pos[2] + self.getHeight()) return base.camNode.isInView(eyePos) def getNameVisible(self): return self.__nameVisible def setNameVisible(self, bool): self.__nameVisible = bool if bool: self.showName() if not bool: self.hideName() def hideName(self): self.nametag.getNametag3d().setContents(Nametag.CSpeech | Nametag.CThought) def showName(self): if self.__nameVisible and not self.ghostMode: self.nametag.getNametag3d().setContents(Nametag.CName | Nametag.CSpeech | Nametag.CThought) def hideNametag2d(self): self.nametag2dContents = 0 self.nametag.getNametag2d().setContents(self.nametag2dContents & self.nametag2dDist) def showNametag2d(self): self.nametag2dContents = self.nametag2dNormalContents if self.ghostMode: self.nametag2dContents = Nametag.CSpeech self.nametag.getNametag2d().setContents(self.nametag2dContents & self.nametag2dDist) def hideNametag3d(self): self.nametag.getNametag3d().setContents(0) def showNametag3d(self): if self.__nameVisible and not self.ghostMode: self.nametag.getNametag3d().setContents(Nametag.CName | Nametag.CSpeech | Nametag.CThought) else: self.nametag.getNametag3d().setContents(0) def setPickable(self, flag): self.nametag.setActive(flag) def clickedNametag(self): MagicWordManager.lastClickedNametag = self if self.nametag.hasButton(): self.advancePageNumber() elif self.nametag.isActive(): messenger.send('clickedNametag', [self]) def setPageChat(self, addressee, paragraph, message, quitButton, extraChatFlags=None, dialogueList=[], pageButton=True): self.__chatAddressee = addressee self.__chatPageNumber = None self.__chatParagraph = paragraph self.__chatMessage = message if extraChatFlags is None: self.__chatFlags = CFSpeech else: self.__chatFlags = CFSpeech | extraChatFlags self.__chatDialogueList = dialogueList self.__chatSet = 0 self.__chatLocal = 0 self.__updatePageChat() if addressee == base.localAvatar.doId: if pageButton: self.__chatFlags |= CFPageButton if quitButton == None: self.__chatFlags |= CFNoQuitButton elif quitButton: self.__chatFlags |= CFQuitButton self.b_setPageNumber(self.__chatParagraph, 0) return def setLocalPageChat(self, message, quitButton, extraChatFlags=None, dialogueList=[]): self.__chatAddressee = base.localAvatar.doId self.__chatPageNumber = None self.__chatParagraph = None self.__chatMessage = message if extraChatFlags is None: self.__chatFlags = CFSpeech else: self.__chatFlags = CFSpeech | extraChatFlags self.__chatDialogueList = dialogueList self.__chatSet = 1 self.__chatLocal = 1 self.__chatFlags |= CFPageButton if quitButton == None: self.__chatFlags |= CFNoQuitButton elif quitButton: self.__chatFlags |= CFQuitButton if len(dialogueList) > 0: dialogue = dialogueList[0] else: dialogue = None self.clearChat() self.setChatAbsolute(message, self.__chatFlags, dialogue) self.setPageNumber(None, 0) return def setPageNumber(self, paragraph, pageNumber, timestamp=None): if timestamp == None: elapsed = 0.0 else: elapsed = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.__chatPageNumber = [paragraph, pageNumber] self.__updatePageChat() if hasattr(self, 'uniqueName'): if pageNumber >= 0: messenger.send(self.uniqueName('nextChatPage'), [pageNumber, elapsed]) else: messenger.send(self.uniqueName('doneChatPage'), [elapsed]) elif pageNumber >= 0: messenger.send('nextChatPage', [pageNumber, elapsed]) else: messenger.send('doneChatPage', [elapsed]) return def advancePageNumber(self): if self.__chatAddressee == base.localAvatar.doId and self.__chatPageNumber != None and self.__chatPageNumber[ 0] == self.__chatParagraph: pageNumber = self.__chatPageNumber[1] if pageNumber >= 0: pageNumber += 1 if pageNumber >= self.nametag.getNumChatPages(): pageNumber = -1 if self.__chatLocal: self.setPageNumber(self.__chatParagraph, pageNumber) else: self.b_setPageNumber(self.__chatParagraph, pageNumber) return def __updatePageChat(self): if self.__chatPageNumber != None and self.__chatPageNumber[ 0] == self.__chatParagraph: pageNumber = self.__chatPageNumber[1] if pageNumber >= 0: if not self.__chatSet: if len(self.__chatDialogueList) > 0: dialogue = self.__chatDialogueList[0] else: dialogue = None self.setChatAbsolute(self.__chatMessage, self.__chatFlags, dialogue) self.__chatSet = 1 if pageNumber < self.nametag.getNumChatPages(): self.nametag.setPageNumber(pageNumber) if pageNumber > 0: if len(self.__chatDialogueList) > pageNumber: dialogue = self.__chatDialogueList[pageNumber] else: dialogue = None self.playCurrentDialogue(dialogue, self.__chatFlags) else: self.clearChat() else: self.clearChat() return def getAirborneHeight(self): height = self.getPos(self.shadowPlacer.shadowNodePath) return height.getZ() + 0.025 def initializeNametag3d(self): self.deleteNametag3d() nametagNode = self.nametag.getNametag3d() self.nametagNodePath = self.nametag3d.attachNewNode(nametagNode) iconNodePath = self.nametag.getNameIcon() for cJoint in self.getNametagJoints(): cJoint.clearNetTransforms() cJoint.addNetTransform(nametagNode) def nametagAmbientLightChanged(self, newlight): self.nametag3d.setLightOff() if newlight: self.nametag3d.setLight(newlight) def deleteNametag3d(self): if self.nametagNodePath: self.nametagNodePath.removeNode() self.nametagNodePath = None return def initializeBodyCollisions(self, collIdStr): self.collTube = CollisionTube(0, 0, 0.5, 0, 0, self.height - self.getRadius(), self.getRadius()) self.collNode = CollisionNode(collIdStr) self.collNode.addSolid(self.collTube) self.collNodePath = self.attachNewNode(self.collNode) if self.ghostMode: self.collNode.setCollideMask(OTPGlobals.GhostBitmask) else: self.collNode.setCollideMask(OTPGlobals.WallBitmask) def stashBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.stash() def unstashBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.unstash() def disableBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.removeNode() del self.collNodePath self.collTube = None return def addActive(self): if base.wantNametags: try: Avatar.ActiveAvatars.remove(self) except ValueError: pass Avatar.ActiveAvatars.append(self) self.nametag.manage(base.marginManager) self.accept(self.nametag.getUniqueId(), self.clickedNametag) def removeActive(self): if base.wantNametags: try: Avatar.ActiveAvatars.remove(self) except ValueError: pass self.nametag.unmanage(base.marginManager) self.ignore(self.nametag.getUniqueId()) def loop(self, animName, restart=1, partName=None, fromFrame=None, toFrame=None): return Actor.loop(self, animName, restart, partName, fromFrame, toFrame)
class DistributedKnockKnockDoor(DistributedAnimatedProp.DistributedAnimatedProp): def __init__(self, cr): DistributedAnimatedProp.DistributedAnimatedProp.__init__(self, cr) self.fsm.setName('DistributedKnockKnockDoor') self.rimshot = None self.knockSfx = None return def generate(self): DistributedAnimatedProp.DistributedAnimatedProp.generate(self) self.avatarTracks = [] self.avatarId = 0 def announceGenerate(self): DistributedAnimatedProp.DistributedAnimatedProp.announceGenerate(self) self.accept('exitKnockKnockDoorSphere_' + str(self.propId), self.exitTrigger) self.acceptAvatar() def disable(self): self.ignore('exitKnockKnockDoorSphere_' + str(self.propId)) self.ignore('enterKnockKnockDoorSphere_' + str(self.propId)) DistributedAnimatedProp.DistributedAnimatedProp.disable(self) def delete(self): DistributedAnimatedProp.DistributedAnimatedProp.delete(self) if self.rimshot: self.rimshot = None if self.knockSfx: self.knockSfx = None return def acceptAvatar(self): self.acceptOnce('enterKnockKnockDoorSphere_' + str(self.propId), self.enterTrigger) def setAvatarInteract(self, avatarId): DistributedAnimatedProp.DistributedAnimatedProp.setAvatarInteract(self, avatarId) def avatarExit(self, avatarId): if avatarId == self.avatarId: for track in self.avatarTracks: track.finish() DelayDelete.cleanupDelayDeletes(track) self.avatarTracks = [] def knockKnockTrack(self, avatar, duration): if avatar == None: return self.rimshot = base.loadSfx('phase_5/audio/sfx/AA_heal_telljoke.ogg') self.knockSfx = base.loadSfx('phase_5/audio/sfx/GUI_knock_3.ogg') joke = KnockKnockJokes[self.propId % len(KnockKnockJokes)] place = base.cr.playGame.getPlace() doorName = TTLocalizer.DoorNametag if place: zone = place.getZoneId() branch = ZoneUtil.getBranchZone(zone) if branch == ToontownGlobals.SillyStreet: if self.propId in KnockKnockContestJokes[ToontownGlobals.SillyStreet].keys(): joke = KnockKnockContestJokes[ToontownGlobals.SillyStreet][self.propId] doorName = KnockKnockDoorNames[self.propId] elif branch == ToontownGlobals.LoopyLane: if self.propId in KnockKnockContestJokes[ToontownGlobals.LoopyLane].keys(): joke = KnockKnockContestJokes[ToontownGlobals.LoopyLane][self.propId] elif branch == ToontownGlobals.PunchlinePlace: if self.propId == 1: joke = KnockKnockContestJokes[ToontownGlobals.PunchlinePlace] elif branch == ToontownGlobals.PolarPlace: if self.propId in KnockKnockContestJokes[ToontownGlobals.PolarPlace].keys(): joke = KnockKnockContestJokes[ToontownGlobals.PolarPlace][self.propId] self.nametag = None self.nametagNP = None doorNP = render.find('**/KnockKnockDoorSphere_' + str(self.propId) + ';+s') if doorNP.isEmpty(): self.notify.warning('Could not find KnockKnockDoorSphere_%s' % self.propId) return self.nametag = NametagGroup() self.nametag.setAvatar(doorNP) self.nametag.setFont(ToontownGlobals.getToonFont()) self.nametag.setSpeechFont(ToontownGlobals.getToonFont()) self.nametag.setName(doorName) self.nametag.setActive(0) self.nametag.manage(base.marginManager) self.nametag.getNametag3d().setBillboardOffset(4) nametagNode = self.nametag.getNametag3d() self.nametagNP = render.attachNewNode(nametagNode) self.nametagNP.setName('knockKnockDoor_nt_' + str(self.propId)) pos = doorNP.node().getSolid(0).getCenter() self.nametagNP.setPos(pos + Vec3(0, 0, avatar.getHeight() + 2)) d = duration * 0.125 track = Sequence(Parallel(Sequence(Wait(d * 0.5), SoundInterval(self.knockSfx)), Func(self.nametag.setChat, TTLocalizer.DoorKnockKnock, CFSpeech), Wait(d)), Func(avatar.setChatAbsolute, TTLocalizer.DoorWhosThere, CFSpeech | CFTimeout, openEnded=0), Wait(d), Func(self.nametag.setChat, joke[0], CFSpeech), Wait(d), Func(avatar.setChatAbsolute, joke[0] + TTLocalizer.DoorWhoAppendix, CFSpeech | CFTimeout, openEnded=0), Wait(d), Func(self.nametag.setChat, joke[1], CFSpeech), Parallel(SoundInterval(self.rimshot, startTime=2.0), Wait(d * 4)), Func(self.cleanupTrack)) track.delayDelete = DelayDelete.DelayDelete(avatar, 'knockKnockTrack') return track def cleanupTrack(self): avatar = self.cr.doId2do.get(self.avatarId, None) if avatar: avatar.clearChat() if self.nametag: self.nametag.unmanage(base.marginManager) self.nametagNP.removeNode() self.nametag.destroy() self.nametag = None self.nametagNP = None return def enterOff(self): DistributedAnimatedProp.DistributedAnimatedProp.enterOff(self) def exitOff(self): DistributedAnimatedProp.DistributedAnimatedProp.exitOff(self) def enterAttract(self, ts): DistributedAnimatedProp.DistributedAnimatedProp.enterAttract(self, ts) self.acceptAvatar() def exitAttract(self): DistributedAnimatedProp.DistributedAnimatedProp.exitAttract(self) def enterPlaying(self, ts): DistributedAnimatedProp.DistributedAnimatedProp.enterPlaying(self, ts) if self.avatarId: avatar = self.cr.doId2do.get(self.avatarId, None) track = self.knockKnockTrack(avatar, 8) if track != None: track.start(ts) self.avatarTracks.append(track) return def exitPlaying(self): DistributedAnimatedProp.DistributedAnimatedProp.exitPlaying(self) for track in self.avatarTracks: track.finish() DelayDelete.cleanupDelayDeletes(track) self.avatarTracks = [] self.avatarId = 0
class DistributedKnockKnockDoor(DistributedAnimatedProp.DistributedAnimatedProp ): def __init__(self, cr): DistributedAnimatedProp.DistributedAnimatedProp.__init__(self, cr) self.fsm.setName('DistributedKnockKnockDoor') self.rimshot = None self.knockSfx = None return def generate(self): DistributedAnimatedProp.DistributedAnimatedProp.generate(self) self.avatarTracks = [] self.avatarId = 0 def announceGenerate(self): DistributedAnimatedProp.DistributedAnimatedProp.announceGenerate(self) self.accept('exitKnockKnockDoorSphere_' + str(self.propId), self.exitTrigger) self.acceptAvatar() def disable(self): self.ignore('exitKnockKnockDoorSphere_' + str(self.propId)) self.ignore('enterKnockKnockDoorSphere_' + str(self.propId)) DistributedAnimatedProp.DistributedAnimatedProp.disable(self) def delete(self): DistributedAnimatedProp.DistributedAnimatedProp.delete(self) if self.rimshot: self.rimshot = None if self.knockSfx: self.knockSfx = None return def acceptAvatar(self): self.acceptOnce('enterKnockKnockDoorSphere_' + str(self.propId), self.enterTrigger) def setAvatarInteract(self, avatarId): DistributedAnimatedProp.DistributedAnimatedProp.setAvatarInteract( self, avatarId) def avatarExit(self, avatarId): if avatarId == self.avatarId: for track in self.avatarTracks: track.finish() DelayDelete.cleanupDelayDeletes(track) self.avatarTracks = [] def knockKnockTrack(self, avatar, duration): if avatar == None: return self.rimshot = base.loadSfx('phase_5/audio/sfx/AA_heal_telljoke.ogg') self.knockSfx = base.loadSfx('phase_5/audio/sfx/GUI_knock_3.ogg') joke = KnockKnockJokes[self.propId % len(KnockKnockJokes)] place = base.cr.playGame.getPlace() doorName = TTLocalizer.DoorNametag self.nametag = None self.nametagNP = None doorNP = render.find('**/KnockKnockDoorSphere_' + str(self.propId) + ';+s') if doorNP.isEmpty(): self.notify.warning('Could not find KnockKnockDoorSphere_%s' % self.propId) return self.nametag = NametagGroup() self.nametag.setAvatar(doorNP) self.nametag.setFont(ToontownGlobals.getToonFont()) self.nametag.setName(doorName) self.nametag.setActive(0) self.nametag.manage(base.marginManager) self.nametag.getNametag3d().setBillboardOffset(4) nametagNode = self.nametag.getNametag3d() self.nametagNP = render.attachNewNode(nametagNode) self.nametagNP.setName('knockKnockDoor_nt_' + str(self.propId)) pos = doorNP.node().getSolid(0).getCenter() self.nametagNP.setPos(pos + Vec3(0, 0, avatar.getHeight() + 2)) d = duration * 0.125 track = Sequence( Parallel( Sequence(Wait(d * 0.5), SoundInterval(self.knockSfx)), Func(self.nametag.setChat, TTLocalizer.DoorKnockKnock, CFSpeech), Wait(d)), Func(avatar.setChatAbsolute, TTLocalizer.DoorWhosThere, CFSpeech | CFTimeout, openEnded=0), Wait(d), Func(self.nametag.setChat, joke[0], CFSpeech), Wait(d), Func(avatar.setChatAbsolute, joke[0] + TTLocalizer.DoorWhoAppendix, CFSpeech | CFTimeout, openEnded=0), Wait(d), Func(self.nametag.setChat, joke[1], CFSpeech), Parallel(SoundInterval(self.rimshot, startTime=2.0), Wait(d * 4)), Func(self.cleanupTrack)) track.delayDelete = DelayDelete.DelayDelete(avatar, 'knockKnockTrack') return track def cleanupTrack(self): avatar = self.cr.doId2do.get(self.avatarId, None) if avatar: avatar.clearChat() if self.nametag: self.nametag.unmanage(base.marginManager) self.nametagNP.removeNode() self.nametag.destroy() self.nametag = None self.nametagNP = None return def enterOff(self): DistributedAnimatedProp.DistributedAnimatedProp.enterOff(self) def exitOff(self): DistributedAnimatedProp.DistributedAnimatedProp.exitOff(self) def enterAttract(self, ts): DistributedAnimatedProp.DistributedAnimatedProp.enterAttract(self, ts) self.acceptAvatar() def exitAttract(self): DistributedAnimatedProp.DistributedAnimatedProp.exitAttract(self) def enterPlaying(self, ts): DistributedAnimatedProp.DistributedAnimatedProp.enterPlaying(self, ts) if self.avatarId: avatar = self.cr.doId2do.get(self.avatarId, None) track = self.knockKnockTrack(avatar, 8) if track != None: track.start(ts) self.avatarTracks.append(track) return def exitPlaying(self): DistributedAnimatedProp.DistributedAnimatedProp.exitPlaying(self) for track in self.avatarTracks: track.finish() DelayDelete.cleanupDelayDeletes(track) self.avatarTracks = [] self.avatarId = 0
class PartyPlanner(DirectFrame, FSM): notify = DirectNotifyGlobal.directNotify.newCategory('PartyPlanner') def __init__(self, doneEvent = None): FSM.__init__(self, 'PartyPlannerFSM') DirectFrame.__init__(self) self.doneEvent = doneEvent self.stateArray = ['Off', 'Welcome', 'PartyEditor', #'Guests', jjkoletar: this should mean that it skips over the guests state 'Date', 'Time', 'Invitation', 'Farewell'] self.partyTime = base.cr.toontownTimeManager.getCurServerDateTime() self.partyNowTime = base.cr.toontownTimeManager.getCurServerDateTime() minutesToNextFifteen = 15 - self.partyTime.minute % 15 self.cleanPartyTime = self.partyTime + timedelta(minutes=minutesToNextFifteen, seconds=-self.partyTime.second) self.partyTime = self.cleanPartyTime self.guests = [] self.isPrivate = False self.selectedCalendarGuiDay = None self.gui = loader.loadModel('phase_4/models/parties/partyPlannerGUI') self.partyDuration = timedelta(hours=PartyGlobals.DefaultPartyDuration) self.timeTypeToMaxValue = {'hour': 23, 'minute': 59} self.timeTypeToChangeAmount = {'hour': (1, -1), 'minute': (15, -15), 'ampm': (1, -1)} self.partyInfo = None self.asapMinuteRounding = config.GetInt('party-asap-minute-rounding', PartyGlobals.PartyPlannerAsapMinuteRounding) self.load() self.request('Welcome') return def enterWelcome(self, *args): self.prevButton['state'] = DirectGuiGlobals.DISABLED self.prevButton.hide() self.nextButton['state'] = DirectGuiGlobals.NORMAL self.welcomePage.show() self.partyPlannerHead.reparentTo(self.welcomePage) self.partyPlannerHead.startBlink() self.partyPlannerHead.startLookAround() self.nametagNP.reparentTo(self.welcomePage) self.chatNP.reparentTo(self.welcomePage) def exitWelcome(self): self.welcomePage.hide() self.prevButton.show() self.partyPlannerHead.stopBlink() self.partyPlannerHead.stopLookAround() def enterPartyEditor(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() self.partyEditorPage.show() self.okWithGroundsGui.doneStatus = '' self.partyEditor.request('Idle') def exitPartyEditor(self): self.partyEditor.request('Hidden') self.partyEditorPage.hide() def enterGuests(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() self.guestPage.show() def exitGuests(self): self.guests = [] for friendCheckBox in self.friendList['items']: if friendCheckBox['indicatorValue']: self.guests.append(friendCheckBox.getPythonTag('id')) self.guestPage.hide() def enterDate(self, *args): self.prevButton.show() self.prevButton['state'] = DirectGuiGlobals.NORMAL if self.selectedCalendarGuiDay is None: self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() self.makePartyNowButton.show() self.datePage.show() return def exitDate(self): self.datePage.hide() self.nextButton.show() if self.selectedCalendarGuiDay is not None: self.partyTime = self.cleanPartyTime self.alterPartyTime(year=self.selectedCalendarGuiDay.myDate.year, month=self.selectedCalendarGuiDay.myDate.month, day=self.selectedCalendarGuiDay.myDate.day) else: self.partyNowTime = self.calcAsapTime() self.partyTime = self.partyNowTime return def calcAsapTime(self): curServerTime = base.cr.toontownTimeManager.getCurServerDateTime() baseTime = curServerTime baseTime = baseTime.replace(baseTime.year, baseTime.month, baseTime.day, baseTime.hour, baseTime.minute, second=0, microsecond=0) minute = curServerTime.minute remainder = minute % self.asapMinuteRounding if remainder: baseTime += timedelta(minutes=self.asapMinuteRounding - remainder) else: baseTime += timedelta(minutes=self.asapMinuteRounding) return baseTime def enterTime(self, *args): self.prevButton.show() self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() self.timePage.show() self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime) self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)) def exitTime(self): self.timePage.hide() self.nextButton.show() def enterInvitation(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.hide() defaultInviteTheme = PartyGlobals.InviteTheme.GenericMale if hasattr(base.cr, 'newsManager') and base.cr.newsManager: if ToontownGlobals.VICTORY_PARTY_HOLIDAY in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.VictoryParty elif ToontownGlobals.KARTING_TICKETS_HOLIDAY in base.cr.newsManager.getHolidayIdList() or ToontownGlobals.CIRCUIT_RACING_EVENT in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.Racing elif ToontownGlobals.VALENTINES_DAY in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.Valentoons if self.partyInfo is not None: del self.partyInfo activityList = self.partyEditor.partyEditorGrid.getActivitiesOnGrid() decorationList = self.partyEditor.partyEditorGrid.getDecorationsOnGrid() endTime = self.partyTime + self.partyDuration self.partyInfo = PartyInfo(0, 0, self.partyTime.year, self.partyTime.month, self.partyTime.day, self.partyTime.hour, self.partyTime.minute, endTime.year, endTime.month, endTime.day, endTime.hour, endTime.minute, self.isPrivate, defaultInviteTheme, activityList, decorationList, 0) if self.noFriends or len(self.getInvitees()) == 0: self.inviteVisual.setNoFriends(True) self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitleNoFriends self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButtonNoFriends self.selectedInviteThemeLabel.stash() self.nextThemeButton.stash() self.prevThemeButton.stash() self.setInviteTheme(defaultInviteTheme) else: self.inviteVisual.setNoFriends(False) self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitle self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButton self.selectedInviteThemeLabel.unstash() self.nextThemeButton.unstash() self.prevThemeButton.unstash() self.setInviteTheme(defaultInviteTheme) self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo) self.invitationPage.show() return def __prevTheme(self): self.nextThemeButton.show() prevTheme = self.currentInvitationTheme - 1 while prevTheme not in self.inviteThemes: prevTheme -= 1 if prevTheme == self.currentInvitationTheme: self.notify.warning('No previous invite theme found.') break elif prevTheme < 0: prevTheme = len(self.inviteVisual.inviteThemesIdToInfo) - 1 self.setInviteTheme(prevTheme) def __nextTheme(self): self.prevThemeButton.show() nextTheme = self.currentInvitationTheme + 1 while nextTheme not in self.inviteThemes: nextTheme += 1 if nextTheme == self.currentInvitationTheme: self.notify.warning('No next invite theme found.') break elif nextTheme >= len(self.inviteVisual.inviteThemesIdToInfo): nextTheme = 0 self.setInviteTheme(nextTheme) def setInviteTheme(self, themeNumber): self.currentInvitationTheme = themeNumber self.selectedInviteThemeLabel['text'] = '%s %s (%d/%d)' % (self.inviteVisual.inviteThemesIdToInfo[self.currentInvitationTheme][1], TTLocalizer.PartyPlannerInvitationTheme, self.inviteThemes.index(self.currentInvitationTheme) + 1, len(self.inviteThemes)) self.partyInfo.inviteTheme = self.currentInvitationTheme self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo) def exitInvitation(self): self.invitationPage.hide() self.nextButton.show() def enterFarewell(self, goingBackAllowed): self.farewellPage.show() if goingBackAllowed: self.prevButton.show() else: self.prevButton.hide() self.nextButton.hide() self.partyPlannerHead.reparentTo(self.farewellPage) self.partyPlannerHead.startBlink() self.partyPlannerHead.startLookAround() self.nametagNP.reparentTo(self.farewellPage) self.chatNP.reparentTo(self.farewellPage) def exitFarewell(self): self.farewellPage.hide() self.nextButton.show() self.prevButton.show() self.partyPlannerHead.stopBlink() self.partyPlannerHead.stopLookAround() def load(self): self.frame = DirectFrame(parent=aspect2d, geom=self.gui.find('**/background'), relief=None, scale=0.85, pos=(0.05, 0.0, 0.1)) self.titleScale = TTLocalizer.PPtitleScale self._createNavButtons() self.welcomePage = self._createWelcomePage() self.welcomePage.hide() self.datePage = self._createDatePage() self.datePage.hide() self.timePage = self._createTimePage() self.timePage.hide() self.guestPage = self._createGuestPage() self.guestPage.hide() self.partyEditorPage = self._createPartyEditorPage() self.partyEditorPage.hide() self.invitationPage = self._createInvitationPage() self.invitationPage.hide() self.farewellPage = self._createFarewellPage() self.farewellPage.hide() return def _createNavButtons(self): self.quitButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/cancelButton_up'), self.gui.find('**/cancelButton_down'), self.gui.find('**/cancelButton_rollover')), command=self.__acceptExit) self.nextButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomNext_button/nextButton_up'), self.gui.find('**/bottomNext_button/nextButton_down'), self.gui.find('**/bottomNext_button/nextButton_rollover')), command=self.__nextItem, state=DirectGuiGlobals.DISABLED) self.prevButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomPrevious_button/previousButton_up'), self.gui.find('**/bottomPrevious_button/previousButton_down'), self.gui.find('**/bottomPrevious_button/previousButton_rollover')), command=self.__prevItem, state=DirectGuiGlobals.DISABLED) self.currentItem = None return def __createNametag(self, parent): if self.nametagGroup == None: self.nametagGroup = NametagGroup() self.nametagGroup.setFont(ToontownGlobals.getToonFont()) self.nametagGroup.setSpeechFont(ToontownGlobals.getToonFont()) self.nametagGroup.setActive(0) self.nametagGroup.setAvatar(self.partyPlannerHead) self.nametagGroup.manage(base.marginManager) self.nametagGroup.setColorCode(self.nametagGroup.CCNonPlayer) self.nametagGroup.getNametag2d().setContents(0) self.nametagNode = NametagFloat2d() self.nametagNode.setContents(Nametag.CName) self.nametagGroup.addNametag(self.nametagNode) self.nametagGroup.setName(base.cr.partyManager.getPartyPlannerName()) self.nametagNP = parent.attachNewNode(self.nametagNode) nametagPos = self.gui.find('**/step_01_partymanPeteNametag_locator').getPos() self.nametagNP.setPosHprScale(nametagPos[0], 0, nametagPos[2], 0, 0, 0, 0.1, 1, 0.1) self.chatNode = NametagFloat2d() self.chatNode.setContents(Nametag.CSpeech | Nametag.CThought) self.nametagGroup.addNametag(self.chatNode) self.nametagGroup.setChat(TTLocalizer.PartyPlannerInstructions, CFSpeech) self.chatNP = parent.attachNewNode(self.chatNode) chatPos = self.gui.find('**/step_01_partymanPeteText_locator').getPos() self.chatNP.setPosHprScale(chatPos[0], 0, chatPos[2], 0, 0, 0, 0.08, 1, 0.08) return def clearNametag(self): if self.nametagGroup != None: self.nametagGroup.unmanage(base.marginManager) self.nametagGroup.removeNametag(self.nametagNode) self.nametagGroup.removeNametag(self.chatNode) self.nametagNP.removeNode() self.chatNP.removeNode() del self.nametagNP del self.chatNP del self.nametagNode del self.chatNode self.nametagGroup.setAvatar(NodePath()) self.nametagGroup.destroy() self.nametagGroup = None return def _createWelcomePage(self): self.nametagGroup = None page = DirectFrame(self.frame) page.setName('PartyPlannerWelcomePage') self.welcomeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerWelcomeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.partyPlannerHead = ToonHead.ToonHead() partyPlannerStyle = base.cr.partyManager.getPartyPlannerStyle() self.partyPlannerHead.setupHead(partyPlannerStyle, forGui=True) self.partyPlannerHead.setPos(self.gui.find('**/step_01_partymanPete_locator').getPos()) animal = partyPlannerStyle.getAnimal() if animal == 'cat' or animal == 'pig': headScale = 0.4 elif animal == 'dog' or animal == 'bear': headScale = 0.45 elif animal == 'rabbit': headScale = 0.35 else: headScale = 0.3 self.partyPlannerHead.setScale(headScale) self.partyPlannerHead.setH(180.0) self.partyPlannerHead.reparentTo(page) self.__createNametag(page) return page def _createDatePage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerDatePage') self.createDateTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerDateTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) pos = self.gui.find('**/step_06_sendInvitation_locator').getPos() self.makePartyNowButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerPartyNow, text_pos=(pos[0], pos[2]), text_scale=0.05, command=self.__doMakePartyNow) curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() self.calendarGuiMonth = CalendarGuiMonth(page, curServerDate, scale=0.95, pos=(-0.05, 0.0, -0.33), dayClickCallback=self._dayClickCallback, onlyFutureDaysClickable=True) return page def __doMakePartyNow(self): self.request('Invitation') def _dayClickCallback(self, calendarGuiDay): self.selectedCalendarGuiDay = calendarGuiDay self.nextButton['state'] = DirectGuiGlobals.NORMAL self.makePartyNowButton.hide() self.nextButton.show() def alterPartyTime(self, year = None, month = None, day = None, hour = None, minute = None): self.partyTime = datetime(year=self.positiveTime('year', year), month=self.positiveTime('month', month), day=self.positiveTime('day', day), hour=self.positiveTime('hour', hour), minute=self.positiveTime('minute', minute), tzinfo=self.partyTime.tzinfo) def positiveTime(self, type, amount): if amount is None: return getattr(self.partyTime, type) if type == 'hour' or type == 'minute': if amount < 0: return self.timeTypeToMaxValue[type] + 1 + self.timeTypeToChangeAmount[type][1] elif amount > self.timeTypeToMaxValue[type]: return 0 return amount def _createTimePage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerTimePage') self.createTimeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.clockImage = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/toontownTime_background')) self.timePageToontownLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontown, pos=self.gui.find('**/step_03_toontown_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont()) self.timePageTimeLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTime, pos=self.gui.find('**/step_03_time_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont()) self.timePageRecapLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeRecap, pos=self.gui.find('**/step_03_partyDateAndTime_locator').getPos(), scale=0.09) self.timePageRecapToontownTimeLabel1 = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontownTime, pos=self.gui.find('**/step_03_toontownTime_locator').getPos(), scale=0.06) self.timePageRecapToontownTimeLabel2 = DirectLabel(parent=page, relief=None, text='%s' % PartyUtils.formatDateTime(self.partyTime), pos=self.gui.find('**/step_03_toontownDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06) self.timePageRecapLocalTimeLabel = DirectLabel(parent=page, relief=None, text='%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)), pos=self.gui.find('**/step_03_localDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06, text_fg=(1.0, 0.0, 0.0, 1.0)) self.timeInputHourLabel, self.timeInputHourUpButton, self.timeInputHourDownButton = self.getTimeWidgets(page, 'hour') self.timeInputMinuteLabel, self.timeInputMinuteUpButton, self.timeInputMinuteDownButton = self.getTimeWidgets(page, 'minute') self.timeInputAmPmLabel, self.timeInputAmPmUpButton, self.timeInputAmPmDownButton = self.getTimeWidgets(page, 'ampm') self.timePagecolonLabel = DirectLabel(parent=page, relief=None, text=':', pos=self.gui.find('**/step_03_colon_locator').getPos(), scale=0.15) return page def getTimeWidgets(self, page, type): if type == 'ampm': data = self.getCurrentAmPm() else: data = getattr(self.partyTime, type) if data == 0 and type == 'minute': data = '00' else: if type == 'hour': data = data % 12 if data == 0: data = 12 data = '%d' % data label = DirectLabel(parent=page, relief=None, text='%s' % data, textMayChange=True, pos=self.gui.find('**/step_03_%s_locator' % type).getPos(), scale=0.12) def changeValue(self, amount): if type == 'ampm': self.alterPartyTime(hour=(self.partyTime.hour + 12) % 24) newAmount = self.getCurrentAmPm() label['text'] = newAmount else: if type == 'hour': newAmount = getattr(self.partyTime, type) + amount newAmount = newAmount % 12 if self.timeInputAmPmLabel['text'] == TTLocalizer.PartyTimeFormatMeridiemPM: newAmount = newAmount % 12 + 12 self.alterPartyTime(hour=newAmount) elif type == 'minute': newAmount = getattr(self.partyTime, type) + amount self.alterPartyTime(minute=newAmount) else: PartyPlanner.notify.error('Invalid type for changeValue in PartyPlanner: %s' % type) newAmount = getattr(self.partyTime, type) if newAmount < 10 and type == 'minute': label['text'] = '0%d' % newAmount else: if type == 'hour': newAmount = newAmount % 12 if newAmount == 0: newAmount = 12 label['text'] = '%d' % newAmount self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime) self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)) upButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonUp_up' % type), self.gui.find('**/%sButtonUp_down' % type), self.gui.find('**/%sButtonUp_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][0]]) downButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonDown_up' % type), self.gui.find('**/%sButtonDown_down' % type), self.gui.find('**/%sButtonDown_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][1]]) return (label, upButton, downButton) def getCurrentAmPm(self): if self.partyTime.hour < 12: return TTLocalizer.PartyTimeFormatMeridiemAM else: return TTLocalizer.PartyTimeFormatMeridiemPM def _createGuestPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerGuestPage') self.guestTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerGuestTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.guestBackgroundLabel = DirectLabel(parent=page, relief=None, image=self.gui.find('**/guestListBackground_flat'), scale=(1.2, 1.0, 1.0)) self.friendList = ScrolledFriendList(page, self.gui, makeItemsCheckBoxes=True) if len(base.localAvatar.friendsList) == 0: self.noFriends = True else: self.noFriends = False for friendPair in base.localAvatar.friendsList: self.friendList.addFriend(determineFriendName(friendPair), friendPair[0]) self.friendList.scrollTo(0) pos = self.gui.find('**/step_04_partyWillBe_locator').getPos() self.publicPrivateLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicPrivateLabel, text_align=TextNode.ACenter, text_scale=0.065, pos=pos) self.publicDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPpbulicDescriptionLabel, pos=(pos[0] - 0.52, pos[1], pos[2])) self.publicDescriptionLabel.stash() self.privateDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPrivateDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPprivateDescriptionLabel, pos=(pos[0] + 0.55, pos[1], pos[2])) self.privateDescriptionLabel.stash() pos = self.gui.find('**/step_04_public_locator').getPos() self.publicButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/publicButton_up'), self.gui.find('**/publicButton_down'), self.gui.find('**/publicButton_rollover'), self.gui.find('**/publicButton_inactive')), text=TTLocalizer.PartyPlannerPublic, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPpublicButton, command=self.__doTogglePublicPrivate) self.publicButton['state'] = DirectGuiGlobals.DISABLED self.publicButton.bind(DirectGuiGlobals.ENTER, self.__enterPublic) self.publicButton.bind(DirectGuiGlobals.EXIT, self.__exitPublic) pos = self.gui.find('**/step_04_private_locator').getPos() self.privateButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/privateButton_up'), self.gui.find('**/privateButton_down'), self.gui.find('**/privateButton_rollover'), self.gui.find('**/privateButton_inactive')), text=TTLocalizer.PartyPlannerPrivate, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPprivateButton, command=self.__doTogglePublicPrivate) self.privateButton.bind(DirectGuiGlobals.ENTER, self.__enterPrivate) self.privateButton.bind(DirectGuiGlobals.EXIT, self.__exitPrivate) self.checkAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/checkAllButton_up'), self.gui.find('**/checkAllButton_down'), self.gui.find('**/checkAllButton_rollover')), command=self.__doCheckAll) self.uncheckAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/uncheckAllButton_up'), self.gui.find('**/uncheckAllButton_down'), self.gui.find('**/uncheckAllButton_rollover')), command=self.__doUncheckAll) return page def __doCheckAll(self): for friendBox in self.friendList['items']: friendBox['indicatorValue'] = True def __doUncheckAll(self): for friendBox in self.friendList['items']: friendBox['indicatorValue'] = False def __enterPrivate(self, mouseEvent): self.privateDescriptionLabel.unstash() def __exitPrivate(self, mouseEvent): self.privateDescriptionLabel.stash() def __enterPublic(self, mouseEvent): self.publicDescriptionLabel.unstash() def __exitPublic(self, mouseEvent): self.publicDescriptionLabel.stash() def __doTogglePublicPrivate(self): if self.isPrivate: self.isPrivate = False self.privateButton['state'] = DirectGuiGlobals.NORMAL self.publicButton['state'] = DirectGuiGlobals.DISABLED else: self.isPrivate = True self.privateButton['state'] = DirectGuiGlobals.DISABLED self.publicButton['state'] = DirectGuiGlobals.NORMAL def _createPartyEditorPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerEditorPage') self.LayoutTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerEditorTitle, pos=self.gui.find('**/title_locator').getPos() + Point3(0.0, 0.0, 0.075), scale=self.titleScale) self.costLabel = DirectLabel(parent=page, pos=(-0.74, 0.0, 0.17), relief=None, text=TTLocalizer.PartyPlannerTotalCost % 0, text_align=TextNode.ACenter, scale=TTLocalizer.PPcostLabel, textMayChange=True) self.partyGridBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/partyGrid_flat')) self.partyGroundsLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPartyGrounds, text_font=ToontownGlobals.getSignFont(), text_fg=VBase4(1.0, 0.0, 0.0, 1.0), text_scale=TTLocalizer.PPpartyGroundsLabel, pos=self.gui.find('**/step_05_partyGrounds_text_locator').getPos(), scale=0.1) self.activityBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/activitiesDecorations_flat1'), pos=(0.0, 0.0, 0.04)) pos = self.gui.find('**/step_05_instructions_locator').getPos() self.instructionLabel = DirectLabel(parent=page, relief=None, text=' ', text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPinstructionLabel, textMayChange=True, geom=self.gui.find('**/instructions_flat')) self.elementTitleLabel = DirectLabel(parent=page, relief=None, text=' ', pos=self.gui.find('**/step_05_activitiesName_text_locator').getPos() + Point3(0.0, 0.0, 0.04), text_scale=TTLocalizer.PPelementTitleLabel, textMayChange=True) self.elementPriceNode = TextNode('ElementPrice') self.elementPriceNode.setAlign(TextNode.ALeft) self.elementPriceNode.setTextColor(0.0, 0.0, 0.0, 1.0) self.elementPriceNode.setFont(ToontownGlobals.getToonFont()) self.elementPrice = page.attachNewNode(self.elementPriceNode) self.elementPrice.setScale(TTLocalizer.PPelementPriceNode) self.elementPrice.setPos(self.gui.find('**/step_05_activityPrice_text_locator').getPos() + Point3(-0.02, 0.0, 0.04)) self.elementDescriptionNode = TextNode('ElementDescription') self.elementDescriptionNode.setAlign(TextNode.ACenter) self.elementDescriptionNode.setWordwrap(8) self.elementDescriptionNode.setFont(ToontownGlobals.getToonFont()) self.elementDescriptionNode.setTextColor(0.0, 0.0, 0.0, 1.0) self.elementDescription = page.attachNewNode(self.elementDescriptionNode) self.elementDescription.setScale(TTLocalizer.PPelementDescription) self.elementDescription.setPos(self.gui.find('**/step_05_activityDescription_text_locator').getPos() + Point3(0.0, 0.0, 0.04)) self.totalMoney = base.localAvatar.getTotalMoney() catalogGui = loader.loadModel('phase_5.5/models/gui/catalog_gui') self.beanBank = DirectLabel(parent=page, relief=None, text=str(self.totalMoney), text_align=TextNode.ARight, text_scale=0.075, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1), text_pos=(0.495, -0.53), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=catalogGui.find('**/bean_bank'), image_scale=(0.65, 0.65, 0.65), scale=0.9, pos=(-0.75, 0.0, 0.6)) catalogGui.removeNode() del catalogGui self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange) self.accept(localAvatar.uniqueName('bankMoneyChange'), self.__moneyChange) self.partyEditor = PartyEditor(self, page) self.partyEditor.request('Hidden') pos = self.gui.find('**/step_05_add_text_locator').getPos() self.elementBuyButton = DirectButton(parent=page, relief=None, text=TTLocalizer.PartyPlannerBuy, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPelementBuyButton, geom=(self.gui.find('**/add_up'), self.gui.find('**/add_down'), self.gui.find('**/add_rollover')), geom3_color=VBase4(0.5, 0.5, 0.5, 1.0), textMayChange=True, pos=(0.0, 0.0, 0.04), command=self.partyEditor.buyCurrentElement) self.okWithPartyGroundsLayoutEvent = 'okWithPartyGroundsLayoutEvent' self.accept(self.okWithPartyGroundsLayoutEvent, self.okWithPartyGroundsLayout) self.okWithGroundsGui = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('PartyEditorOkGui'), doneEvent=self.okWithPartyGroundsLayoutEvent, message=TTLocalizer.PartyPlannerOkWithGroundsLayout, style=TTDialog.YesNo, okButtonText=OTPLocalizer.DialogYes, cancelButtonText=OTPLocalizer.DialogNo) self.okWithGroundsGui.doneStatus = '' self.okWithGroundsGui.hide() return page def okWithPartyGroundsLayout(self): self.okWithGroundsGui.hide() if self.okWithGroundsGui.doneStatus == 'ok': self.__nextItem() def setNextButtonState(self, enabled): if enabled: self.nextButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() else: self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() def _createInvitationPage(self): self.__handleHolidays() page = DirectFrame(self.frame) page.setName('PartyPlannerInvitationPage') self.invitationTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.invitationBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/invitationBackground')) self.inviteVisual = InviteVisual(page) self.selectedInviteThemeLabel = DirectLabel(parent=page, relief=None, pos=self.gui.find('**/step_06_theme_locator').getPos(), text='', text_scale=0.06, textMayChange=True) self.nextThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topNext_button/nextButton_up'), self.gui.find('**/topNext_button/nextButton_down'), self.gui.find('**/topNext_button/nextButton_rollover')), command=self.__nextTheme) self.prevThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topPrevious_button/previousButton_up'), self.gui.find('**/topPrevious_button/previousButton_down'), self.gui.find('**/topPrevious_button/previousButton_rollover')), command=self.__prevTheme) pos = self.gui.find('**/step_06_sendInvitation_locator').getPos() self.inviteButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerInviteButton, textMayChange=True, text_scale=0.05, text_pos=(pos[0], pos[2]), command=self.__handleComplete) return page def __handleHolidays(self): self.inviteThemes = range(len(PartyGlobals.InviteTheme)) if hasattr(base.cr, 'newsManager') and base.cr.newsManager: holidayIds = base.cr.newsManager.getHolidayIdList() if ToontownGlobals.VALENTINES_DAY not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.Valentoons) if ToontownGlobals.VICTORY_PARTY_HOLIDAY not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.VictoryParty) if ToontownGlobals.WINTER_DECORATIONS not in holidayIds and ToontownGlobals.WACKY_WINTER_DECORATIONS not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.Winter) def _createFarewellPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerFarewellPage') self.confirmTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmationAllOkTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) pos = self.gui.find('**/step_07_close_text_locator').getPos() self.closePlannerButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/close_up'), self.gui.find('**/close_down'), self.gui.find('**/close_rollover')), text=TTLocalizer.PartyPlannerClosePlanner, text_scale=0.055, text_pos=(pos[0], pos[2]), command=self.__acceptExit) return page def close(self): self.ignore('addPartyResponseReceived') self.ignore(localAvatar.uniqueName('moneyChange')) self.ignore(localAvatar.uniqueName('bankMoneyChange')) self.timeInputHourUpButton.destroy() self.timeInputHourDownButton.destroy() self.timeInputMinuteUpButton.destroy() self.timeInputMinuteDownButton.destroy() self.timeInputAmPmUpButton.destroy() self.timeInputAmPmDownButton.destroy() self.privateButton.destroy() self.publicButton.destroy() self.makePartyNowButton.destroy() self.checkAllButton.destroy() self.uncheckAllButton.destroy() self.elementBuyButton.destroy() self.nextThemeButton.destroy() self.prevThemeButton.destroy() self.inviteButton.destroy() self.closePlannerButton.destroy() self.ignore(self.okWithPartyGroundsLayoutEvent) if hasattr(self, 'okWithGroundsGui'): self.okWithGroundsGui.cleanup() del self.okWithGroundsGui if hasattr(self, 'frame') and not self.frame.isEmpty(): messenger.send(self.doneEvent) self.hide() self.cleanup() self.friendList.removeAndDestroyAllItems() self.friendList.destroy() self.calendarGuiMonth.destroy() self.frame.destroy() self.partyPlannerHead.delete() self.partyPlannerHead.removeNode() self.clearNametag() self.partyEditor.request('Cleanup') self.partyEditor = None self.destroy() del self return def __handleComplete(self): self.inviteButton['state'] = DirectGuiGlobals.DISABLED self.prevButton['state'] = DirectGuiGlobals.DISABLED endTime = self.partyTime + self.partyDuration hostId = base.localAvatar.doId self.partyActivities = self.partyEditor.partyEditorGrid.getActivitiesOnGrid() decorations = self.partyEditor.partyEditorGrid.getDecorationsOnGrid() invitees = self.getInvitees() self.accept('addPartyResponseReceived', self.processAddPartyResponse) base.cr.partyManager.sendAddParty(hostId, self.partyTime.strftime('%Y-%m-%d %H:%M:%S'), endTime.strftime('%Y-%m-%d %H:%M:%S'), self.isPrivate, self.currentInvitationTheme, self.partyActivities, decorations, invitees) def getInvitees(self): invitees = [] for friendBox in self.friendList['items']: if friendBox['indicatorValue']: invitees.append(friendBox.getPythonTag('id')) return invitees def processAddPartyResponse(self, hostId, errorCode): PartyPlanner.notify.debug('processAddPartyResponse : hostId=%d errorCode=%s' % (hostId, PartyGlobals.AddPartyErrorCode.getString(errorCode))) goingBackAllowed = False if errorCode == PartyGlobals.AddPartyErrorCode.AllOk: goingBackAllowed = False self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationAllOkTitle if self.noFriends or len(self.getInvitees()) == 0: confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkTextNoFriends else: confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkText elif errorCode == PartyGlobals.AddPartyErrorCode.ValidationError: self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationValidationErrorText elif errorCode == PartyGlobals.AddPartyErrorCode.DatabaseError: self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationDatabaseErrorText elif errorCode == PartyGlobals.AddPartyErrorCode.TooManyHostedParties: goingBackAllowed = False self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationTooManyText self.nametagGroup.setChat(confirmRecapText, CFSpeech) self.request('Farewell', goingBackAllowed) def __acceptExit(self): PartyPlanner.notify.debug('__acceptExit') if hasattr(self, 'frame'): self.hide() messenger.send(self.doneEvent) def __nextItem(self): messenger.send('wakeup') if self.state == 'PartyEditor' and self.okWithGroundsGui.doneStatus != 'ok': self.okWithGroundsGui.show() return if self.state == 'PartyEditor' and self.noFriends: self.request('Date') self.selectedCalendarGuiDay = None self.calendarGuiMonth.clearSelectedDay() return if self.state == 'Guests': self.selectedCalendarGuiDay = None self.calendarGuiMonth.clearSelectedDay() if self.state == 'Time': if self.partyTime < base.cr.toontownTimeManager.getCurServerDateTime(): self.okChooseFutureTimeEvent = 'okChooseFutureTimeEvent' self.acceptOnce(self.okChooseFutureTimeEvent, self.okChooseFutureTime) self.chooseFutureTimeDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('chooseFutureTimeDialog'), doneEvent=self.okChooseFutureTimeEvent, message=TTLocalizer.PartyPlannerChooseFutureTime, style=TTDialog.Acknowledge) self.chooseFutureTimeDialog.show() return self.requestNext() return def okChooseFutureTime(self): if hasattr(self, 'chooseFutureTimeDialog'): self.chooseFutureTimeDialog.cleanup() del self.chooseFutureTimeDialog if hasattr(self, 'okChooseFutureTimeEvent'): self.ignore(self.okChooseFutureTimeEvent) def __prevItem(self): messenger.send('wakeup') if self.state == 'Date' and self.noFriends: self.request('PartyEditor') return if self.state == 'Invitation' and self.selectedCalendarGuiDay is None: self.request('Guests') return self.requestPrev() return def __moneyChange(self, newMoney): if hasattr(self, 'totalMoney'): self.totalMoney = base.localAvatar.getTotalMoney() if hasattr(self, 'beanBank'): self.beanBank['text'] = str(int(self.totalMoney))
class DistributedElevatorExt(DistributedElevator.DistributedElevator): def __init__(self, cr): DistributedElevator.DistributedElevator.__init__(self, cr) self.nametag = None self.currentFloor = -1 return def setupElevator(self): if self.isSetup: self.elevatorSphereNodePath.removeNode() self.leftDoor = self.bldg.leftDoor self.rightDoor = self.bldg.rightDoor DistributedElevator.DistributedElevator.setupElevator(self) self.setupNametag() def disable(self): self.clearNametag() DistributedElevator.DistributedElevator.disable(self) def setupNametag(self): 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.CCSuitBuilding) self.nametag.setActive(0) self.nametag.setAvatar(self.getElevatorModel()) name = self.cr.playGame.dnaData.getBlock(self.bldg.block).title if not name: name = TTLocalizer.CogsInc else: name += TTLocalizer.CogsIncExt 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.destroy() self.nametag = None return def getBldgDoorOrigin(self): return self.bldg.getSuitDoorOrigin() def gotBldg(self, buildingList): self.bldgRequest = None self.bldg = buildingList[0] if not self.bldg: self.notify.error('setBldgDoId: elevator %d cannot find bldg %d!' % (self.doId, self.bldgDoId)) return if self.getBldgDoorOrigin(): self.bossLevel = self.bldg.getBossLevel() self.setupElevator() else: self.notify.warning('setBldgDoId: elevator %d cannot find suitDoorOrigin for bldg %d!' % (self.doId, self.bldgDoId)) return def setFloor(self, floorNumber): if self.currentFloor >= 0: if self.bldg.floorIndicator[self.currentFloor]: self.bldg.floorIndicator[self.currentFloor].setColor(LIGHT_OFF_COLOR) if floorNumber >= 0: if self.bldg.floorIndicator[floorNumber]: self.bldg.floorIndicator[floorNumber].setColor(LIGHT_ON_COLOR) self.currentFloor = floorNumber def handleEnterSphere(self, collEntry): self.notify.debug('Entering Elevator Sphere....') if hasattr(localAvatar, 'boardingParty') and localAvatar.boardingParty and localAvatar.boardingParty.getGroupLeader(localAvatar.doId) and localAvatar.boardingParty.getGroupLeader(localAvatar.doId) != localAvatar.doId: base.localAvatar.elevatorNotifier.showMe(TTLocalizer.ElevatorGroupMember) elif self.allowedToEnter(self.zoneId): self.cr.playGame.getPlace().detectedElevatorCollision(self) else: place = base.cr.playGame.getPlace() if place: place.fsm.request('stopped') self.dialog = TeaserPanel.TeaserPanel(pageName='cogHQ', doneFunc=self.handleOkTeaser) def handleEnterElevator(self): if hasattr(localAvatar, 'boardingParty') and localAvatar.boardingParty and localAvatar.boardingParty.getGroupLeader(localAvatar.doId): if localAvatar.boardingParty.getGroupLeader(localAvatar.doId) == localAvatar.doId: localAvatar.boardingParty.handleEnterElevator(self) elif self.elevatorTripId and localAvatar.lastElevatorLeft == self.elevatorTripId: self.rejectBoard(base.localAvatar.doId, REJECT_SHUFFLE) elif base.localAvatar.hp > 0: toon = base.localAvatar self.sendUpdate('requestBoard', []) else: self.notify.warning('Tried to board elevator with hp: %d' % base.localAvatar.hp) def enterWaitEmpty(self, ts): self.elevatorSphereNodePath.unstash() self.forceDoorsOpen() self.accept(self.uniqueName('enterelevatorSphere'), self.handleEnterSphere) self.accept(self.uniqueName('enterElevatorOK'), self.handleEnterElevator) DistributedElevator.DistributedElevator.enterWaitEmpty(self, ts) def exitWaitEmpty(self): self.elevatorSphereNodePath.stash() self.ignore(self.uniqueName('enterelevatorSphere')) self.ignore(self.uniqueName('enterElevatorOK')) DistributedElevator.DistributedElevator.exitWaitEmpty(self) def enterWaitCountdown(self, ts): DistributedElevator.DistributedElevator.enterWaitCountdown(self, ts) self.forceDoorsOpen() self.accept(self.uniqueName('enterElevatorOK'), self.handleEnterElevator) self.startCountdownClock(self.countdownTime, ts) def exitWaitCountdown(self): self.ignore(self.uniqueName('enterElevatorOK')) DistributedElevator.DistributedElevator.exitWaitCountdown(self) def getZoneId(self): return self.bldg.interiorZoneId def getElevatorModel(self): np = self.bldg.getSuitElevatorNodePath() if np.isEmpty(): self.notify.error("np not ok") return self.bldg.getSuitElevatorNodePath()
class Avatar(Actor, ShadowCaster): notify = directNotify.newCategory('Avatar') ActiveAvatars = [] def __init__(self, other = None): Actor.__init__(self, None, None, other, flattenable=0, setFinal=1) ShadowCaster.__init__(self) self.__font = OTPGlobals.getInterfaceFont() self.name = '' self.soundChatBubble = None self.avatarType = '' self.nametagNodePath = None self.__nameVisible = 1 self.nametag = NametagGroup() self.nametag.setAvatar(self) self.nametag.setFont(OTPGlobals.getInterfaceFont()) self.nametag.setSpeechFont(OTPGlobals.getInterfaceFont()) self.nametag2dContents = Nametag.CName | Nametag.CSpeech self.nametag2dDist = Nametag.CName | Nametag.CSpeech self.nametag2dNormalContents = Nametag.CName | Nametag.CSpeech self.nametag3d = self.attachNewNode('nametag3d') self.nametag3d.setTag('cam', 'nametag') self.nametag3d.setLightOff() self.getGeomNode().showThrough(OTPRender.ShadowCameraBitmask) self.nametag3d.hide(OTPRender.ShadowCameraBitmask) self.collTube = None self.scale = 1.0 self.height = 0.0 self.style = None self.understandable = 1 self.setPlayerType(NametagGroup.CCNormal) self.ghostMode = 0 self.__chatParagraph = None self.__chatMessage = None self.__chatFlags = 0 self.__chatPageNumber = None self.__chatAddressee = None self.__chatDialogueList = [] self.__chatSet = 0 self.__chatLocal = 0 self.__currentDialogue = None self.wantAdminTag = True def delete(self): try: self.Avatar_deleted except: self.deleteNametag3d() Actor.cleanup(self) self.Avatar_deleted = 1 del self.__font del self.style del self.soundChatBubble self.nametag.destroy() del self.nametag self.nametag3d.removeNode() ShadowCaster.delete(self) Actor.delete(self) def isLocal(self): return 0 def isPet(self): return False def isProxy(self): return False def setPlayerType(self, playerType): self.playerType = playerType if not hasattr(self, 'nametag'): self.notify.warning('no nametag attributed, but would have been used.') return if self.isUnderstandable(): self.nametag.setColorCode(self.playerType) else: self.nametag.setColorCode(NametagGroup.CCNonPlayer) self.setNametagName() def considerUnderstandable(self): if self.playerType in (NametagGroup.CCNormal, NametagGroup.CCSpeedChat): self.setPlayerType(NametagGroup.CCSpeedChat) if hasattr(base, 'localAvatar') and (self == base.localAvatar): self.understandable = 1 self.setPlayerType(NametagGroup.CCNormal) elif self.playerType == NametagGroup.CCSuit: self.understandable = 1 self.setPlayerType(NametagGroup.CCSuit) elif self.playerType not in (NametagGroup.CCNormal, NametagGroup.CCSpeedChat): self.understandable = 1 self.setPlayerType(NametagGroup.CCNonPlayer) elif base.localAvatar.isTrueFriends(self.doId): self.understandable = 2 self.setPlayerType(NametagGroup.CCNormal) elif base.cr.wantSpeedchatPlus(): self.understandable = 1 self.setPlayerType(NametagGroup.CCSpeedChat) else: self.understandable = 0 self.setPlayerType(NametagGroup.CCSpeedChat) if base.cr.wantSpeedchatPlus() and hasattr(self, 'adminAccess') and self.isAdmin() and self != base.localAvatar: self.understandable = 2 if not hasattr(self, 'nametag'): self.notify.warning('no nametag attributed, but would have been used') else: self.nametag.setColorCode(self.playerType) def isUnderstandable(self): return self.understandable def setDNAString(self, dnaString): pass def setDNA(self, dna): pass def getAvatarScale(self): return self.scale def setAvatarScale(self, scale): if self.scale != scale: self.scale = scale self.getGeomNode().setScale(scale) self.setHeight(self.height) def adjustNametag3d(self, parentScale = 1.0): self.nametag3d.setPos(0, 0, self.height + 0.5) def getHeight(self): return self.height def setHeight(self, height): self.height = height self.adjustNametag3d() if self.collTube: self.collTube.setPointB(0, 0, height - self.getRadius()) if self.collNodePath: self.collNodePath.forceRecomputeBounds() def getRadius(self): return OTPGlobals.AvatarDefaultRadius def getName(self): return self.name def getType(self): return self.avatarType def setWantAdminTag(self, bool): self.wantAdminTag = bool def getWantAdminTag(self): return self.wantAdminTag def setName(self, name): if hasattr(self, 'isDisguised') and self.isDisguised: return self.name = name if hasattr(self, 'nametag'): self.setNametagName() def setDisplayName(self, str): if hasattr(self, 'isDisguised'): if self.isDisguised: return self.setNametagName(str) def setNametagName(self, name=None): if not name: name = self.name self.nametag.setName(name) if hasattr(self, 'adminAccess') and self.isAdmin() and self.getWantAdminTag(): access = self.getAdminAccess() if access in OTPLocalizer.AccessToString: name += '\n\x01shadow\x01%s\x02' % OTPLocalizer.AccessToString[access] self.nametag.setDisplayName(name) def getFont(self): return self.__font def setFont(self, font): self.__font = font self.nametag.setFont(font) def getStyle(self): return self.style def setStyle(self, style): self.style = style def getDialogueArray(self): return None def playCurrentDialogue(self, dialogue, chatFlags, interrupt = 1): if interrupt and self.__currentDialogue is not None: self.__currentDialogue.stop() self.__currentDialogue = dialogue if dialogue: base.playSfx(dialogue, node=self) elif chatFlags & CFSpeech != 0 and self.nametag.getNumChatPages() > 0: self.playDialogueForString(self.nametag.getChat()) if self.soundChatBubble != None: base.playSfx(self.soundChatBubble, node=self) def playDialogueForString(self, chatString): searchString = chatString.lower() if searchString.find(OTPLocalizer.DialogSpecial) >= 0: type = 'special' elif searchString.find(OTPLocalizer.DialogExclamation) >= 0: type = 'exclamation' elif searchString.find(OTPLocalizer.DialogQuestion) >= 0: type = 'question' elif random.randint(0, 1): type = 'statementA' else: type = 'statementB' stringLength = len(chatString) if stringLength <= OTPLocalizer.DialogLength1: length = 1 elif stringLength <= OTPLocalizer.DialogLength2: length = 2 elif stringLength <= OTPLocalizer.DialogLength3: length = 3 else: length = 4 self.playDialogue(type, length) def playDialogue(self, type, length): dialogueArray = self.getDialogueArray() if dialogueArray == None: return sfxIndex = None if type == 'statementA' or type == 'statementB': if length == 1: sfxIndex = 0 elif length == 2: sfxIndex = 1 elif length >= 3: sfxIndex = 2 elif type == 'question': sfxIndex = 3 elif type == 'exclamation': sfxIndex = 4 elif type == 'special': sfxIndex = 5 else: notify.error('unrecognized dialogue type: ', type) if sfxIndex != None and sfxIndex < len(dialogueArray) and dialogueArray[sfxIndex] != None: base.playSfx(dialogueArray[sfxIndex], node=self) return def getDialogueSfx(self, type, length): retval = None dialogueArray = self.getDialogueArray() if dialogueArray == None: return sfxIndex = None if type == 'statementA' or type == 'statementB': if length == 1: sfxIndex = 0 elif length == 2: sfxIndex = 1 elif length >= 3: sfxIndex = 2 elif type == 'question': sfxIndex = 3 elif type == 'exclamation': sfxIndex = 4 elif type == 'special': sfxIndex = 5 else: notify.error('unrecognized dialogue type: ', type) if sfxIndex != None and sfxIndex < len(dialogueArray) and dialogueArray[sfxIndex] != None: retval = dialogueArray[sfxIndex] return retval def setChatAbsolute(self, chatString, chatFlags, dialogue=None, interrupt=1): self.clearChat() self.nametag.setChat(chatString, chatFlags) self.playCurrentDialogue(dialogue, chatFlags, interrupt) def displayTalk(self, chatString): if not base.localAvatar.isIgnored(self.doId): self.clearChat() if ChatUtil.isThought(chatString): chatString = ChatUtil.removeThoughtPrefix(chatString) self.nametag.setChat(chatString, CFThought) else: self.nametag.setChat(chatString, CFSpeech | CFTimeout) def clearChat(self): self.nametag.clearChat() def getNameVisible(self): return self.__nameVisible def setNameVisible(self, bool): self.__nameVisible = bool if bool: self.showName() if not bool: self.hideName() def hideName(self): nametag3d = self.nametag.getNametag3d() nametag3d.setContents(Nametag.CSpeech | Nametag.CThought) def showName(self): if self.__nameVisible and (not self.ghostMode): nametag3d = self.nametag.getNametag3d() nametag3d.setContents(Nametag.CName | Nametag.CSpeech | Nametag.CThought) def hideNametag2d(self): nametag2d = self.nametag.getNametag2d() self.nametag2dContents = 0 nametag2d.setContents(self.nametag2dContents & self.nametag2dDist) def showNametag2d(self): nametag2d = self.nametag.getNametag2d() self.nametag2dContents = self.nametag2dNormalContents if self.ghostMode: self.nametag2dContents = Nametag.CSpeech nametag2d.setContents(self.nametag2dContents & self.nametag2dDist) def hideNametag3d(self): nametag3d = self.nametag.getNametag3d() nametag3d.setContents(0) def showNametag3d(self): nametag3d = self.nametag.getNametag3d() if self.__nameVisible and (not self.ghostMode): nametag3d.setContents(Nametag.CName | Nametag.CSpeech | Nametag.CThought) else: nametag3d.setContents(0) def setPickable(self, flag): self.nametag.setActive(flag) def clickedNametag(self): MagicWordManager.lastClickedNametag = self if self.nametag.hasButton(): self.advancePageNumber() elif self.nametag.isActive(): messenger.send('clickedNametag', [self]) def setPageChat(self, addressee, paragraph, message, quitButton, extraChatFlags=None, dialogueList=[], pageButton=True): self.__chatAddressee = addressee self.__chatPageNumber = None self.__chatParagraph = paragraph self.__chatMessage = message if extraChatFlags is None: self.__chatFlags = CFSpeech else: self.__chatFlags = CFSpeech | extraChatFlags self.__chatDialogueList = dialogueList self.__chatSet = 0 self.__chatLocal = 0 self.__updatePageChat() if addressee == base.localAvatar.doId: if pageButton: self.__chatFlags |= CFPageButton if quitButton == None: self.__chatFlags |= CFNoQuitButton elif quitButton: self.__chatFlags |= CFQuitButton self.b_setPageNumber(self.__chatParagraph, 0) def setLocalPageChat(self, message, quitButton, extraChatFlags=None, dialogueList=[]): self.__chatAddressee = base.localAvatar.doId self.__chatPageNumber = None self.__chatParagraph = None self.__chatMessage = message if extraChatFlags is None: self.__chatFlags = CFSpeech else: self.__chatFlags = CFSpeech | extraChatFlags self.__chatDialogueList = dialogueList self.__chatSet = 1 self.__chatLocal = 1 self.__chatFlags |= CFPageButton if quitButton == None: self.__chatFlags |= CFNoQuitButton elif quitButton: self.__chatFlags |= CFQuitButton if len(dialogueList) > 0: dialogue = dialogueList[0] else: dialogue = None self.clearChat() self.setChatAbsolute(message, self.__chatFlags, dialogue) self.setPageNumber(None, 0) def setPageNumber(self, paragraph, pageNumber, timestamp=None): if timestamp is None: elapsed = 0.0 else: elapsed = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.__chatPageNumber = [paragraph, pageNumber] self.__updatePageChat() if hasattr(self, 'uniqueName'): if pageNumber >= 0: messenger.send(self.uniqueName('nextChatPage'), [pageNumber, elapsed]) else: messenger.send(self.uniqueName('doneChatPage'), [elapsed]) elif pageNumber >= 0: messenger.send('nextChatPage', [pageNumber, elapsed]) else: messenger.send('doneChatPage', [elapsed]) def advancePageNumber(self): if (self.__chatAddressee == base.localAvatar.doId) and ( self.__chatPageNumber is not None) and ( self.__chatPageNumber[0] == self.__chatParagraph): pageNumber = self.__chatPageNumber[1] if pageNumber >= 0: pageNumber += 1 if pageNumber >= self.nametag.getNumChatPages(): pageNumber = -1 if self.__chatLocal: self.setPageNumber(self.__chatParagraph, pageNumber) else: self.b_setPageNumber(self.__chatParagraph, pageNumber) def __updatePageChat(self): if (self.__chatPageNumber is not None) and ( self.__chatPageNumber[0] == self.__chatParagraph): pageNumber = self.__chatPageNumber[1] if pageNumber >= 0: if not self.__chatSet: if len(self.__chatDialogueList) > 0: dialogue = self.__chatDialogueList[0] else: dialogue = None self.setChatAbsolute(self.__chatMessage, self.__chatFlags, dialogue) self.__chatSet = 1 if pageNumber < self.nametag.getNumChatPages(): self.nametag.setPageNumber(pageNumber) if pageNumber > 0: if len(self.__chatDialogueList) > pageNumber: dialogue = self.__chatDialogueList[pageNumber] else: dialogue = None self.playCurrentDialogue(dialogue, self.__chatFlags) else: self.clearChat() else: self.clearChat() def getAirborneHeight(self): height = self.getPos(self.shadowPlacer.shadowNodePath) return height.getZ() + 0.025 def initializeNametag3d(self): self.deleteNametag3d() nametagNode = self.nametag.getNametag3d() self.nametagNodePath = self.nametag3d.attachNewNode(nametagNode) iconNodePath = self.nametag.getNameIcon() for cJoint in self.getNametagJoints(): cJoint.clearNetTransforms() cJoint.addNetTransform(nametagNode) def deleteNametag3d(self): if self.nametagNodePath: self.nametagNodePath.removeNode() self.nametagNodePath = None def initializeBodyCollisions(self, collIdStr): self.collTube = CollisionTube(0, 0, 0.5, 0, 0, self.height - self.getRadius(), self.getRadius()) self.collNode = CollisionNode(collIdStr) self.collNode.addSolid(self.collTube) self.collNodePath = self.attachNewNode(self.collNode) if self.ghostMode: self.collNode.setCollideMask(OTPGlobals.GhostBitmask) else: self.collNode.setCollideMask(OTPGlobals.WallBitmask) def stashBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.stash() def unstashBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.unstash() def disableBodyCollisions(self): if hasattr(self, 'collNodePath'): self.collNodePath.removeNode() del self.collNodePath self.collTube = None return def addActive(self): if base.wantNametags: try: Avatar.ActiveAvatars.remove(self) except ValueError: pass Avatar.ActiveAvatars.append(self) self.nametag.manage(base.marginManager) self.accept(self.nametag.getUniqueId(), self.clickedNametag) def removeActive(self): if base.wantNametags: try: Avatar.ActiveAvatars.remove(self) except ValueError: pass self.nametag.unmanage(base.marginManager) self.ignore(self.nametag.getUniqueId()) def loop(self, animName, restart = 1, partName = None, fromFrame = None, toFrame = None): return Actor.loop(self, animName, restart, partName, fromFrame, toFrame) def createTalkSequence(self, speech, waitTime, name='talkSequence'): sequence = Sequence(name=name) for text in speech: sequence.append(Func(self.setChatAbsolute, text, CFSpeech)) sequence.append(Wait(len(text.split(' ')))) sequence.append(Func(self.clearChat)) sequence.append(Wait(waitTime)) return sequence
class PartyPlanner(DirectFrame, FSM): notify = DirectNotifyGlobal.directNotify.newCategory('PartyPlanner') def __init__(self, doneEvent = None): FSM.__init__(self, 'PartyPlannerFSM') DirectFrame.__init__(self) self.doneEvent = doneEvent self.stateArray = ['Off', 'Welcome', 'PartyEditor', #'Guests', jjkoletar: this should mean that it skips over the guests state 'Date', 'Time', 'Invitation', 'Farewell'] self.partyTime = base.cr.toontownTimeManager.getCurServerDateTime() self.partyNowTime = base.cr.toontownTimeManager.getCurServerDateTime() minutesToNextFifteen = 15 - self.partyTime.minute % 15 self.cleanPartyTime = self.partyTime + timedelta(minutes=minutesToNextFifteen, seconds=-self.partyTime.second) self.partyTime = self.cleanPartyTime self.guests = [] self.isPrivate = False self.selectedCalendarGuiDay = None self.gui = loader.loadModel('phase_4/models/parties/partyPlannerGUI') self.partyDuration = timedelta(hours=PartyGlobals.DefaultPartyDuration) self.timeTypeToMaxValue = {'hour': 23, 'minute': 59} self.timeTypeToChangeAmount = {'hour': (1, -1), 'minute': (15, -15), 'ampm': (1, -1)} self.partyInfo = None self.asapMinuteRounding = config.GetInt('party-asap-minute-rounding', PartyGlobals.PartyPlannerAsapMinuteRounding) self.load() self.request('Welcome') return def enterWelcome(self, *args): self.prevButton['state'] = DirectGuiGlobals.DISABLED self.prevButton.hide() self.nextButton['state'] = DirectGuiGlobals.NORMAL self.welcomePage.show() self.partyPlannerHead.reparentTo(self.welcomePage) self.partyPlannerHead.startBlink() self.partyPlannerHead.startLookAround() self.nametagNP.reparentTo(self.welcomePage) self.chatNP.reparentTo(self.welcomePage) def exitWelcome(self): self.welcomePage.hide() self.prevButton.show() self.partyPlannerHead.stopBlink() self.partyPlannerHead.stopLookAround() def enterPartyEditor(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() self.partyEditorPage.show() self.okWithGroundsGui.doneStatus = '' self.partyEditor.request('Idle') def exitPartyEditor(self): self.partyEditor.request('Hidden') self.partyEditorPage.hide() def enterGuests(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() self.guestPage.show() def exitGuests(self): self.guests = [] for friendCheckBox in self.friendList['items']: if friendCheckBox['indicatorValue']: self.guests.append(friendCheckBox.getPythonTag('id')) self.guestPage.hide() def enterDate(self, *args): self.prevButton.show() self.prevButton['state'] = DirectGuiGlobals.NORMAL if self.selectedCalendarGuiDay is None: self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() self.makePartyNowButton.show() self.datePage.show() return def exitDate(self): self.datePage.hide() self.nextButton.show() if self.selectedCalendarGuiDay is not None: self.partyTime = self.cleanPartyTime self.alterPartyTime(year=self.selectedCalendarGuiDay.myDate.year, month=self.selectedCalendarGuiDay.myDate.month, day=self.selectedCalendarGuiDay.myDate.day) else: self.partyNowTime = self.calcAsapTime() self.partyTime = self.partyNowTime return def calcAsapTime(self): curServerTime = base.cr.toontownTimeManager.getCurServerDateTime() baseTime = curServerTime baseTime = baseTime.replace(baseTime.year, baseTime.month, baseTime.day, baseTime.hour, baseTime.minute, second=0, microsecond=0) minute = curServerTime.minute remainder = minute % self.asapMinuteRounding if remainder: baseTime += timedelta(minutes=self.asapMinuteRounding - remainder) else: baseTime += timedelta(minutes=self.asapMinuteRounding) return baseTime def enterTime(self, *args): self.prevButton.show() self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() self.timePage.show() self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime) self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)) def exitTime(self): self.timePage.hide() self.nextButton.show() def enterInvitation(self, *args): self.prevButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.hide() defaultInviteTheme = PartyGlobals.InviteTheme.GenericMale if hasattr(base.cr, 'newsManager') and base.cr.newsManager: if ToontownGlobals.VICTORY_PARTY_HOLIDAY in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.VictoryParty elif ToontownGlobals.KARTING_TICKETS_HOLIDAY in base.cr.newsManager.getHolidayIdList() or ToontownGlobals.CIRCUIT_RACING_EVENT in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.Racing elif ToontownGlobals.VALENTINES_DAY in base.cr.newsManager.getHolidayIdList(): defaultInviteTheme = PartyGlobals.InviteTheme.Valentoons if self.partyInfo is not None: del self.partyInfo activityList = self.partyEditor.partyEditorGrid.getActivitiesOnGrid() decorationList = self.partyEditor.partyEditorGrid.getDecorationsOnGrid() endTime = self.partyTime + self.partyDuration self.partyInfo = PartyInfo(0, 0, self.partyTime.year, self.partyTime.month, self.partyTime.day, self.partyTime.hour, self.partyTime.minute, endTime.year, endTime.month, endTime.day, endTime.hour, endTime.minute, self.isPrivate, defaultInviteTheme, activityList, decorationList, 0) if self.noFriends or len(self.getInvitees()) == 0: self.inviteVisual.setNoFriends(True) self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitleNoFriends self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButtonNoFriends self.selectedInviteThemeLabel.stash() self.nextThemeButton.stash() self.prevThemeButton.stash() self.setInviteTheme(defaultInviteTheme) else: self.inviteVisual.setNoFriends(False) self.invitationTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmTitle self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButton self.selectedInviteThemeLabel.unstash() self.nextThemeButton.unstash() self.prevThemeButton.unstash() self.setInviteTheme(defaultInviteTheme) self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo) self.invitationPage.show() return def __prevTheme(self): self.nextThemeButton.show() prevTheme = self.currentInvitationTheme - 1 while prevTheme not in self.inviteThemes: prevTheme -= 1 if prevTheme == self.currentInvitationTheme: self.notify.warning('No previous invite theme found.') break elif prevTheme < 0: prevTheme = len(self.inviteVisual.inviteThemesIdToInfo) - 1 self.setInviteTheme(prevTheme) def __nextTheme(self): self.prevThemeButton.show() nextTheme = self.currentInvitationTheme + 1 while nextTheme not in self.inviteThemes: nextTheme += 1 if nextTheme == self.currentInvitationTheme: self.notify.warning('No next invite theme found.') break elif nextTheme >= len(self.inviteVisual.inviteThemesIdToInfo): nextTheme = 0 self.setInviteTheme(nextTheme) def setInviteTheme(self, themeNumber): self.currentInvitationTheme = themeNumber self.selectedInviteThemeLabel['text'] = '%s %s (%d/%d)' % (self.inviteVisual.inviteThemesIdToInfo[self.currentInvitationTheme][1], TTLocalizer.PartyPlannerInvitationTheme, self.inviteThemes.index(self.currentInvitationTheme) + 1, len(self.inviteThemes)) self.partyInfo.inviteTheme = self.currentInvitationTheme self.inviteVisual.updateInvitation(base.localAvatar.getName(), self.partyInfo) def exitInvitation(self): self.invitationPage.hide() self.nextButton.show() def enterFarewell(self, goingBackAllowed): self.farewellPage.show() if goingBackAllowed: self.prevButton.show() else: self.prevButton.hide() self.nextButton.hide() self.partyPlannerHead.reparentTo(self.farewellPage) self.partyPlannerHead.startBlink() self.partyPlannerHead.startLookAround() self.nametagNP.reparentTo(self.farewellPage) self.chatNP.reparentTo(self.farewellPage) def exitFarewell(self): self.farewellPage.hide() self.nextButton.show() self.prevButton.show() self.partyPlannerHead.stopBlink() self.partyPlannerHead.stopLookAround() def load(self): self.frame = DirectFrame(parent=aspect2d, geom=self.gui.find('**/background'), relief=None, scale=0.85, pos=(0.05, 0.0, 0.1)) self.titleScale = TTLocalizer.PPtitleScale self._createNavButtons() self.welcomePage = self._createWelcomePage() self.welcomePage.hide() self.datePage = self._createDatePage() self.datePage.hide() self.timePage = self._createTimePage() self.timePage.hide() self.guestPage = self._createGuestPage() self.guestPage.hide() self.partyEditorPage = self._createPartyEditorPage() self.partyEditorPage.hide() self.invitationPage = self._createInvitationPage() self.invitationPage.hide() self.farewellPage = self._createFarewellPage() self.farewellPage.hide() return def _createNavButtons(self): self.quitButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/cancelButton_up'), self.gui.find('**/cancelButton_down'), self.gui.find('**/cancelButton_rollover')), command=self.__acceptExit) self.nextButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomNext_button/nextButton_up'), self.gui.find('**/bottomNext_button/nextButton_down'), self.gui.find('**/bottomNext_button/nextButton_rollover')), command=self.__nextItem, state=DirectGuiGlobals.DISABLED) self.prevButton = DirectButton(parent=self.frame, relief=None, geom=(self.gui.find('**/bottomPrevious_button/previousButton_up'), self.gui.find('**/bottomPrevious_button/previousButton_down'), self.gui.find('**/bottomPrevious_button/previousButton_rollover')), command=self.__prevItem, state=DirectGuiGlobals.DISABLED) self.currentItem = None return def __createNametag(self, parent): if self.nametagGroup == None: self.nametagGroup = NametagGroup() self.nametagGroup.setFont(ToontownGlobals.getToonFont()) self.nametagGroup.setSpeechFont(ToontownGlobals.getToonFont()) self.nametagGroup.setActive(0) self.nametagGroup.setAvatar(self.partyPlannerHead) self.nametagGroup.manage(base.marginManager) self.nametagGroup.setColorCode(self.nametagGroup.CCNonPlayer) self.nametagGroup.getNametag2d().setContents(0) self.nametagNode = NametagFloat2d() self.nametagNode.setContents(Nametag.CName) self.nametagGroup.addNametag(self.nametagNode) self.nametagGroup.setName(base.cr.partyManager.getPartyPlannerName()) self.nametagNP = parent.attachNewNode(self.nametagNode) nametagPos = self.gui.find('**/step_01_partymanPeteNametag_locator').getPos() self.nametagNP.setPosHprScale(nametagPos[0], 0, nametagPos[2], 0, 0, 0, 0.1, 1, 0.1) self.chatNode = NametagFloat2d() self.chatNode.setContents(Nametag.CSpeech | Nametag.CThought) self.nametagGroup.addNametag(self.chatNode) self.nametagGroup.setChat(TTLocalizer.PartyPlannerInstructions, CFSpeech) self.chatNP = parent.attachNewNode(self.chatNode) chatPos = self.gui.find('**/step_01_partymanPeteText_locator').getPos() self.chatNP.setPosHprScale(chatPos[0], 0, chatPos[2], 0, 0, 0, 0.08, 1, 0.08) return def clearNametag(self): if self.nametagGroup != None: self.nametagGroup.unmanage(base.marginManager) self.nametagGroup.removeNametag(self.nametagNode) self.nametagGroup.removeNametag(self.chatNode) self.nametagNP.removeNode() self.chatNP.removeNode() del self.nametagNP del self.chatNP del self.nametagNode del self.chatNode self.nametagGroup.setAvatar(NodePath()) self.nametagGroup.destroy() self.nametagGroup = None return def _createWelcomePage(self): self.nametagGroup = None page = DirectFrame(self.frame) page.setName('PartyPlannerWelcomePage') self.welcomeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerWelcomeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.partyPlannerHead = ToonHead.ToonHead() partyPlannerStyle = base.cr.partyManager.getPartyPlannerStyle() self.partyPlannerHead.setupHead(partyPlannerStyle, forGui=True) self.partyPlannerHead.setPos(self.gui.find('**/step_01_partymanPete_locator').getPos()) animal = partyPlannerStyle.getAnimal() if animal == 'cat' or animal == 'pig': headScale = 0.4 elif animal == 'dog' or animal == 'bear': headScale = 0.45 elif animal == 'rabbit': headScale = 0.35 else: headScale = 0.3 self.partyPlannerHead.setScale(headScale) self.partyPlannerHead.setH(180.0) self.partyPlannerHead.reparentTo(page) self.__createNametag(page) return page def _createDatePage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerDatePage') self.createDateTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerDateTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) pos = self.gui.find('**/step_06_sendInvitation_locator').getPos() self.makePartyNowButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerPartyNow, text_pos=(pos[0], pos[2]), text_scale=0.05, command=self.__doMakePartyNow) curServerDate = base.cr.toontownTimeManager.getCurServerDateTime() self.calendarGuiMonth = CalendarGuiMonth(page, curServerDate, scale=0.95, pos=(-0.05, 0.0, -0.33), dayClickCallback=self._dayClickCallback, onlyFutureDaysClickable=True) return page def __doMakePartyNow(self): self.request('Invitation') def _dayClickCallback(self, calendarGuiDay): self.selectedCalendarGuiDay = calendarGuiDay self.nextButton['state'] = DirectGuiGlobals.NORMAL self.makePartyNowButton.hide() self.nextButton.show() def alterPartyTime(self, year = None, month = None, day = None, hour = None, minute = None): self.partyTime = datetime(year=self.positiveTime('year', year), month=self.positiveTime('month', month), day=self.positiveTime('day', day), hour=self.positiveTime('hour', hour), minute=self.positiveTime('minute', minute), tzinfo=self.partyTime.tzinfo) def positiveTime(self, type, amount): if amount is None: return getattr(self.partyTime, type) if type == 'hour' or type == 'minute': if amount < 0: return self.timeTypeToMaxValue[type] + 1 + self.timeTypeToChangeAmount[type][1] elif amount > self.timeTypeToMaxValue[type]: return 0 return amount def _createTimePage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerTimePage') self.createTimeTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.clockImage = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/toontownTime_background')) self.timePageToontownLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontown, pos=self.gui.find('**/step_03_toontown_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont()) self.timePageTimeLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeTime, pos=self.gui.find('**/step_03_time_locator').getPos(), scale=0.15, text_fg=(1.0, 0.0, 0.0, 1.0), text_font=ToontownGlobals.getSignFont()) self.timePageRecapLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeRecap, pos=self.gui.find('**/step_03_partyDateAndTime_locator').getPos(), scale=0.09) self.timePageRecapToontownTimeLabel1 = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerTimeToontownTime, pos=self.gui.find('**/step_03_toontownTime_locator').getPos(), scale=0.06) self.timePageRecapToontownTimeLabel2 = DirectLabel(parent=page, relief=None, text='%s' % PartyUtils.formatDateTime(self.partyTime), pos=self.gui.find('**/step_03_toontownDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06) self.timePageRecapLocalTimeLabel = DirectLabel(parent=page, relief=None, text='%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)), pos=self.gui.find('**/step_03_localDateAndTime_loactor').getPos(), textMayChange=True, scale=0.06, text_fg=(1.0, 0.0, 0.0, 1.0)) self.timeInputHourLabel, self.timeInputHourUpButton, self.timeInputHourDownButton = self.getTimeWidgets(page, 'hour') self.timeInputMinuteLabel, self.timeInputMinuteUpButton, self.timeInputMinuteDownButton = self.getTimeWidgets(page, 'minute') self.timeInputAmPmLabel, self.timeInputAmPmUpButton, self.timeInputAmPmDownButton = self.getTimeWidgets(page, 'ampm') self.timePagecolonLabel = DirectLabel(parent=page, relief=None, text=':', pos=self.gui.find('**/step_03_colon_locator').getPos(), scale=0.15) return page def getTimeWidgets(self, page, type): if type == 'ampm': data = self.getCurrentAmPm() else: data = getattr(self.partyTime, type) if data == 0 and type == 'minute': data = '00' else: if type == 'hour': data = data % 12 if data == 0: data = 12 data = '%d' % data label = DirectLabel(parent=page, relief=None, text='%s' % data, textMayChange=True, pos=self.gui.find('**/step_03_%s_locator' % type).getPos(), scale=0.12) def changeValue(self, amount): if type == 'ampm': self.alterPartyTime(hour=(self.partyTime.hour + 12) % 24) newAmount = self.getCurrentAmPm() label['text'] = newAmount else: if type == 'hour': newAmount = getattr(self.partyTime, type) + amount newAmount = newAmount % 12 if self.timeInputAmPmLabel['text'] == TTLocalizer.PartyTimeFormatMeridiemPM: newAmount = newAmount % 12 + 12 self.alterPartyTime(hour=newAmount) elif type == 'minute': newAmount = getattr(self.partyTime, type) + amount self.alterPartyTime(minute=newAmount) else: PartyPlanner.notify.error('Invalid type for changeValue in PartyPlanner: %s' % type) newAmount = getattr(self.partyTime, type) if newAmount < 10 and type == 'minute': label['text'] = '0%d' % newAmount else: if type == 'hour': newAmount = newAmount % 12 if newAmount == 0: newAmount = 12 label['text'] = '%d' % newAmount self.timePageRecapToontownTimeLabel2['text'] = '%s' % PartyUtils.formatDateTime(self.partyTime) self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (TTLocalizer.PartyPlannerTimeLocalTime, PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)) upButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonUp_up' % type), self.gui.find('**/%sButtonUp_down' % type), self.gui.find('**/%sButtonUp_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][0]]) downButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/%sButtonDown_up' % type), self.gui.find('**/%sButtonDown_down' % type), self.gui.find('**/%sButtonDown_rollover' % type)), command=changeValue, extraArgs=[self, self.timeTypeToChangeAmount[type][1]]) return (label, upButton, downButton) def getCurrentAmPm(self): if self.partyTime.hour < 12: return TTLocalizer.PartyTimeFormatMeridiemAM else: return TTLocalizer.PartyTimeFormatMeridiemPM def _createGuestPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerGuestPage') self.guestTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerGuestTitle, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.guestBackgroundLabel = DirectLabel(parent=page, relief=None, image=self.gui.find('**/guestListBackground_flat'), scale=(1.2, 1.0, 1.0)) self.friendList = ScrolledFriendList(page, self.gui, makeItemsCheckBoxes=True) if len(base.localAvatar.friendsList) == 0: self.noFriends = True else: self.noFriends = False for friendPair in base.localAvatar.friendsList: self.friendList.addFriend(determineFriendName(friendPair), friendPair[0]) self.friendList.scrollTo(0) pos = self.gui.find('**/step_04_partyWillBe_locator').getPos() self.publicPrivateLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicPrivateLabel, text_align=TextNode.ACenter, text_scale=0.065, pos=pos) self.publicDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPublicDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPpbulicDescriptionLabel, pos=(pos[0] - 0.52, pos[1], pos[2])) self.publicDescriptionLabel.stash() self.privateDescriptionLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPrivateDescription, text_align=TextNode.ACenter, text_scale=TTLocalizer.PPprivateDescriptionLabel, pos=(pos[0] + 0.55, pos[1], pos[2])) self.privateDescriptionLabel.stash() pos = self.gui.find('**/step_04_public_locator').getPos() self.publicButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/publicButton_up'), self.gui.find('**/publicButton_down'), self.gui.find('**/publicButton_rollover'), self.gui.find('**/publicButton_inactive')), text=TTLocalizer.PartyPlannerPublic, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPpublicButton, command=self.__doTogglePublicPrivate) self.publicButton['state'] = DirectGuiGlobals.DISABLED self.publicButton.bind(DirectGuiGlobals.ENTER, self.__enterPublic) self.publicButton.bind(DirectGuiGlobals.EXIT, self.__exitPublic) pos = self.gui.find('**/step_04_private_locator').getPos() self.privateButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/privateButton_up'), self.gui.find('**/privateButton_down'), self.gui.find('**/privateButton_rollover'), self.gui.find('**/privateButton_inactive')), text=TTLocalizer.PartyPlannerPrivate, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPprivateButton, command=self.__doTogglePublicPrivate) self.privateButton.bind(DirectGuiGlobals.ENTER, self.__enterPrivate) self.privateButton.bind(DirectGuiGlobals.EXIT, self.__exitPrivate) self.checkAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/checkAllButton_up'), self.gui.find('**/checkAllButton_down'), self.gui.find('**/checkAllButton_rollover')), command=self.__doCheckAll) self.uncheckAllButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/uncheckAllButton_up'), self.gui.find('**/uncheckAllButton_down'), self.gui.find('**/uncheckAllButton_rollover')), command=self.__doUncheckAll) return page def __doCheckAll(self): for friendBox in self.friendList['items']: friendBox['indicatorValue'] = True def __doUncheckAll(self): for friendBox in self.friendList['items']: friendBox['indicatorValue'] = False def __enterPrivate(self, mouseEvent): self.privateDescriptionLabel.unstash() def __exitPrivate(self, mouseEvent): self.privateDescriptionLabel.stash() def __enterPublic(self, mouseEvent): self.publicDescriptionLabel.unstash() def __exitPublic(self, mouseEvent): self.publicDescriptionLabel.stash() def __doTogglePublicPrivate(self): if self.isPrivate: self.isPrivate = False self.privateButton['state'] = DirectGuiGlobals.NORMAL self.publicButton['state'] = DirectGuiGlobals.DISABLED else: self.isPrivate = True self.privateButton['state'] = DirectGuiGlobals.DISABLED self.publicButton['state'] = DirectGuiGlobals.NORMAL def _createPartyEditorPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerEditorPage') self.LayoutTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerEditorTitle, pos=self.gui.find('**/title_locator').getPos() + Point3(0.0, 0.0, 0.075), scale=self.titleScale) self.costLabel = DirectLabel(parent=page, pos=(-0.74, 0.0, 0.17), relief=None, text=TTLocalizer.PartyPlannerTotalCost % 0, text_align=TextNode.ACenter, scale=TTLocalizer.PPcostLabel, textMayChange=True) self.partyGridBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/partyGrid_flat')) self.partyGroundsLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerPartyGrounds, text_font=ToontownGlobals.getSignFont(), text_fg=VBase4(1.0, 0.0, 0.0, 1.0), text_scale=TTLocalizer.PPpartyGroundsLabel, pos=self.gui.find('**/step_05_partyGrounds_text_locator').getPos(), scale=0.1) self.activityBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/activitiesDecorations_flat1'), pos=(0.0, 0.0, 0.04)) pos = self.gui.find('**/step_05_instructions_locator').getPos() self.instructionLabel = DirectLabel(parent=page, relief=None, text=' ', text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPinstructionLabel, textMayChange=True, geom=self.gui.find('**/instructions_flat')) self.elementTitleLabel = DirectLabel(parent=page, relief=None, text=' ', pos=self.gui.find('**/step_05_activitiesName_text_locator').getPos() + Point3(0.0, 0.0, 0.04), text_scale=TTLocalizer.PPelementTitleLabel, textMayChange=True) self.elementPriceNode = TextNode('ElementPrice') self.elementPriceNode.setAlign(TextNode.ALeft) self.elementPriceNode.setTextColor(0.0, 0.0, 0.0, 1.0) self.elementPriceNode.setFont(ToontownGlobals.getToonFont()) self.elementPrice = page.attachNewNode(self.elementPriceNode) self.elementPrice.setScale(TTLocalizer.PPelementPriceNode) self.elementPrice.setPos(self.gui.find('**/step_05_activityPrice_text_locator').getPos() + Point3(-0.02, 0.0, 0.04)) self.elementDescriptionNode = TextNode('ElementDescription') self.elementDescriptionNode.setAlign(TextNode.ACenter) self.elementDescriptionNode.setWordwrap(8) self.elementDescriptionNode.setFont(ToontownGlobals.getToonFont()) self.elementDescriptionNode.setTextColor(0.0, 0.0, 0.0, 1.0) self.elementDescription = page.attachNewNode(self.elementDescriptionNode) self.elementDescription.setScale(TTLocalizer.PPelementDescription) self.elementDescription.setPos(self.gui.find('**/step_05_activityDescription_text_locator').getPos() + Point3(0.0, 0.0, 0.04)) self.totalMoney = base.localAvatar.getTotalMoney() catalogGui = loader.loadModel('phase_5.5/models/gui/catalog_gui') self.beanBank = DirectLabel(parent=page, relief=None, text=str(self.totalMoney), text_align=TextNode.ARight, text_scale=0.075, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1), text_pos=(0.495, -0.53), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=catalogGui.find('**/bean_bank'), image_scale=(0.65, 0.65, 0.65), scale=0.9, pos=(-0.75, 0.0, 0.6)) catalogGui.removeNode() del catalogGui self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange) self.accept(localAvatar.uniqueName('bankMoneyChange'), self.__moneyChange) self.partyEditor = PartyEditor(self, page) self.partyEditor.request('Hidden') pos = self.gui.find('**/step_05_add_text_locator').getPos() self.elementBuyButton = DirectButton(parent=page, relief=None, text=TTLocalizer.PartyPlannerBuy, text_pos=(pos[0], pos[2]), text_scale=TTLocalizer.PPelementBuyButton, geom=(self.gui.find('**/add_up'), self.gui.find('**/add_down'), self.gui.find('**/add_rollover')), geom3_color=VBase4(0.5, 0.5, 0.5, 1.0), textMayChange=True, pos=(0.0, 0.0, 0.04), command=self.partyEditor.buyCurrentElement) self.okWithPartyGroundsLayoutEvent = 'okWithPartyGroundsLayoutEvent' self.accept(self.okWithPartyGroundsLayoutEvent, self.okWithPartyGroundsLayout) self.okWithGroundsGui = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('PartyEditorOkGui'), doneEvent=self.okWithPartyGroundsLayoutEvent, message=TTLocalizer.PartyPlannerOkWithGroundsLayout, style=TTDialog.YesNo, okButtonText=OTPLocalizer.DialogYes, cancelButtonText=OTPLocalizer.DialogNo) self.okWithGroundsGui.doneStatus = '' self.okWithGroundsGui.hide() return page def okWithPartyGroundsLayout(self): self.okWithGroundsGui.hide() if self.okWithGroundsGui.doneStatus == 'ok': self.__nextItem() def setNextButtonState(self, enabled): if enabled: self.nextButton['state'] = DirectGuiGlobals.NORMAL self.nextButton.show() else: self.nextButton['state'] = DirectGuiGlobals.DISABLED self.nextButton.hide() def _createInvitationPage(self): self.__handleHolidays() page = DirectFrame(self.frame) page.setName('PartyPlannerInvitationPage') self.invitationTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) self.invitationBackground = DirectFrame(parent=page, relief=None, geom=self.gui.find('**/invitationBackground')) self.inviteVisual = InviteVisual(page) self.selectedInviteThemeLabel = DirectLabel(parent=page, relief=None, pos=self.gui.find('**/step_06_theme_locator').getPos(), text='', text_scale=0.06, textMayChange=True) self.nextThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topNext_button/nextButton_up'), self.gui.find('**/topNext_button/nextButton_down'), self.gui.find('**/topNext_button/nextButton_rollover')), command=self.__nextTheme) self.prevThemeButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/topPrevious_button/previousButton_up'), self.gui.find('**/topPrevious_button/previousButton_down'), self.gui.find('**/topPrevious_button/previousButton_rollover')), command=self.__prevTheme) pos = self.gui.find('**/step_06_sendInvitation_locator').getPos() self.inviteButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'), self.gui.find('**/send_rollover')), text=TTLocalizer.PartyPlannerInviteButton, textMayChange=True, text_scale=0.05, text_pos=(pos[0], pos[2]), command=self.__handleComplete) return page def __handleHolidays(self): self.inviteThemes = range(len(PartyGlobals.InviteTheme)) if hasattr(base.cr, 'newsManager') and base.cr.newsManager: holidayIds = base.cr.newsManager.getHolidayIdList() if ToontownGlobals.VALENTINES_DAY not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.Valentoons) if ToontownGlobals.VICTORY_PARTY_HOLIDAY not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.VictoryParty) if ToontownGlobals.WINTER_DECORATIONS not in holidayIds and ToontownGlobals.WINTER_SNOWFALL not in holidayIds: self.inviteThemes.remove(PartyGlobals.InviteTheme.Winter) def _createFarewellPage(self): page = DirectFrame(self.frame) page.setName('PartyPlannerFarewellPage') self.confirmTitleLabel = DirectLabel(parent=page, relief=None, text=TTLocalizer.PartyPlannerConfirmationAllOkTitle, textMayChange=True, pos=self.gui.find('**/title_locator').getPos(), scale=self.titleScale) pos = self.gui.find('**/step_07_close_text_locator').getPos() self.closePlannerButton = DirectButton(parent=page, relief=None, geom=(self.gui.find('**/close_up'), self.gui.find('**/close_down'), self.gui.find('**/close_rollover')), text=TTLocalizer.PartyPlannerClosePlanner, text_scale=0.055, text_pos=(pos[0], pos[2]), command=self.__acceptExit) return page def close(self): self.ignore('addPartyResponseReceived') self.ignore(localAvatar.uniqueName('moneyChange')) self.ignore(localAvatar.uniqueName('bankMoneyChange')) self.timeInputHourUpButton.destroy() self.timeInputHourDownButton.destroy() self.timeInputMinuteUpButton.destroy() self.timeInputMinuteDownButton.destroy() self.timeInputAmPmUpButton.destroy() self.timeInputAmPmDownButton.destroy() self.privateButton.destroy() self.publicButton.destroy() self.makePartyNowButton.destroy() self.checkAllButton.destroy() self.uncheckAllButton.destroy() self.elementBuyButton.destroy() self.nextThemeButton.destroy() self.prevThemeButton.destroy() self.inviteButton.destroy() self.closePlannerButton.destroy() self.ignore(self.okWithPartyGroundsLayoutEvent) if hasattr(self, 'okWithGroundsGui'): self.okWithGroundsGui.cleanup() del self.okWithGroundsGui if hasattr(self, 'frame') and not self.frame.isEmpty(): messenger.send(self.doneEvent) self.hide() self.cleanup() self.friendList.removeAndDestroyAllItems() self.friendList.destroy() self.calendarGuiMonth.destroy() self.frame.destroy() self.partyPlannerHead.delete() self.partyPlannerHead.removeNode() self.clearNametag() self.partyEditor.request('Cleanup') self.partyEditor = None self.destroy() del self return def __handleComplete(self): self.inviteButton['state'] = DirectGuiGlobals.DISABLED self.prevButton['state'] = DirectGuiGlobals.DISABLED endTime = self.partyTime + self.partyDuration hostId = base.localAvatar.doId self.partyActivities = self.partyEditor.partyEditorGrid.getActivitiesOnGrid() decorations = self.partyEditor.partyEditorGrid.getDecorationsOnGrid() invitees = self.getInvitees() self.accept('addPartyResponseReceived', self.processAddPartyResponse) base.cr.partyManager.sendAddParty(hostId, self.partyTime.strftime('%Y-%m-%d %H:%M:%S'), endTime.strftime('%Y-%m-%d %H:%M:%S'), self.isPrivate, self.currentInvitationTheme, self.partyActivities, decorations, invitees) def getInvitees(self): invitees = [] for friendBox in self.friendList['items']: if friendBox['indicatorValue']: invitees.append(friendBox.getPythonTag('id')) return invitees def processAddPartyResponse(self, hostId, errorCode): PartyPlanner.notify.debug('processAddPartyResponse : hostId=%d errorCode=%s' % (hostId, PartyGlobals.AddPartyErrorCode.getString(errorCode))) goingBackAllowed = False if errorCode == PartyGlobals.AddPartyErrorCode.AllOk: goingBackAllowed = False self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationAllOkTitle if self.noFriends or len(self.getInvitees()) == 0: confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkTextNoFriends else: confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkText elif errorCode == PartyGlobals.AddPartyErrorCode.ValidationError: self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationValidationErrorText elif errorCode == PartyGlobals.AddPartyErrorCode.DatabaseError: self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationDatabaseErrorText elif errorCode == PartyGlobals.AddPartyErrorCode.TooManyHostedParties: goingBackAllowed = False self.confirmTitleLabel['text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle confirmRecapText = TTLocalizer.PartyPlannerConfirmationTooManyText self.nametagGroup.setChat(confirmRecapText, CFSpeech) self.request('Farewell', goingBackAllowed) def __acceptExit(self): PartyPlanner.notify.debug('__acceptExit') if hasattr(self, 'frame'): self.hide() messenger.send(self.doneEvent) def __nextItem(self): messenger.send('wakeup') if self.state == 'PartyEditor' and self.okWithGroundsGui.doneStatus != 'ok': self.okWithGroundsGui.show() return if self.state == 'PartyEditor' and self.noFriends: self.request('Date') self.selectedCalendarGuiDay = None self.calendarGuiMonth.clearSelectedDay() return if self.state == 'Guests': self.selectedCalendarGuiDay = None self.calendarGuiMonth.clearSelectedDay() if self.state == 'Time': if self.partyTime < base.cr.toontownTimeManager.getCurServerDateTime(): self.okChooseFutureTimeEvent = 'okChooseFutureTimeEvent' self.acceptOnce(self.okChooseFutureTimeEvent, self.okChooseFutureTime) self.chooseFutureTimeDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('chooseFutureTimeDialog'), doneEvent=self.okChooseFutureTimeEvent, message=TTLocalizer.PartyPlannerChooseFutureTime, style=TTDialog.Acknowledge) self.chooseFutureTimeDialog.show() return self.requestNext() return def okChooseFutureTime(self): if hasattr(self, 'chooseFutureTimeDialog'): self.chooseFutureTimeDialog.cleanup() del self.chooseFutureTimeDialog if hasattr(self, 'okChooseFutureTimeEvent'): self.ignore(self.okChooseFutureTimeEvent) def __prevItem(self): messenger.send('wakeup') if self.state == 'Date' and self.noFriends: self.request('PartyEditor') return if self.state == 'Invitation' and self.selectedCalendarGuiDay is None: self.request('Guests') return self.requestPrev() return def __moneyChange(self, newMoney): if hasattr(self, 'totalMoney'): self.totalMoney = base.localAvatar.getTotalMoney() if hasattr(self, 'beanBank'): self.beanBank['text'] = str(int(self.totalMoney))
class DistributedKnockKnockDoor(DistributedAnimatedProp.DistributedAnimatedProp): def __init__(self, cr): DistributedAnimatedProp.DistributedAnimatedProp.__init__(self, cr) self.fsm.setName("DistributedKnockKnockDoor") self.rimshot = None self.knockSfx = None def generate(self): DistributedAnimatedProp.DistributedAnimatedProp.generate(self) self.avatarTracks = [] self.avatarId = 0 def announceGenerate(self): DistributedAnimatedProp.DistributedAnimatedProp.announceGenerate(self) self.accept("exitKnockKnockDoorSphere_" + str(self.propId), self.exitTrigger) self.acceptAvatar() def disable(self): self.ignoreAll() DistributedAnimatedProp.DistributedAnimatedProp.disable(self) def delete(self): DistributedAnimatedProp.DistributedAnimatedProp.delete(self) if self.rimshot: self.rimshot = None if self.knockSfx: self.knockSfx = None def acceptAvatar(self): self.acceptOnce("enterKnockKnockDoorSphere_" + str(self.propId), self.enterTrigger) def setAvatarInteract(self, avatarId): DistributedAnimatedProp.DistributedAnimatedProp.setAvatarInteract(self, avatarId) def avatarExit(self, avatarId): if avatarId == self.avatarId: self.stopTracks() def knockKnockTrack(self, avatar, duration): if avatar is None: return self.rimshot = base.loadSfx("phase_5/audio/sfx/AA_heal_telljoke.ogg") self.knockSfx = base.loadSfx("phase_5/audio/sfx/GUI_knock_%s.ogg" % random.randint(1, 4)) joke = KnockKnockJokes[self.propId % len(KnockKnockJokes)] place = base.cr.playGame.getPlace() doorName = TTLocalizer.DoorNametag self.nametag = None self.nametagNP = None doorNP = render.find("**/KnockKnockDoorSphere_" + str(self.propId) + ";+s") if doorNP.isEmpty(): self.notify.warning("Could not find KnockKnockDoorSphere_%s" % self.propId) return self.nametag = NametagGroup() self.nametag.setAvatar(doorNP) self.nametag.setFont(ToontownGlobals.getToonFont()) self.nametag.setSpeechFont(ToontownGlobals.getToonFont()) self.nametag.setName(doorName) self.nametag.setActive(0) self.nametag.manage(base.marginManager) self.nametag.getNametag3d().setBillboardOffset(4) nametagNode = self.nametag.getNametag3d() self.nametagNP = render.attachNewNode(nametagNode) self.nametagNP.setName("knockKnockDoor_nt_" + str(self.propId)) pos = doorNP.getBounds().getCenter() self.nametagNP.setPos(pos + Vec3(0, 0, avatar.getHeight() + 2)) d = duration * 0.125 track = Sequence( Parallel( Sequence(Wait(d * 0.5), SoundInterval(self.knockSfx)), Func(self.nametag.setChat, TTLocalizer.DoorKnockKnock, CFSpeech), Wait(d), ), Func(avatar.setChatAbsolute, TTLocalizer.DoorWhosThere, CFSpeech | CFTimeout, openEnded=0), Wait(d), Func(self.nametag.setChat, joke[0], CFSpeech), Wait(d), Func(avatar.setChatAbsolute, joke[0] + TTLocalizer.DoorWhoAppendix, CFSpeech | CFTimeout, openEnded=0), Wait(d), Func(self.nametag.setChat, joke[1], CFSpeech), ) if avatar == base.localAvatar: track.append(Func(self.sendUpdate, "requestToonup")) track.append(Parallel(SoundInterval(self.rimshot, startTime=2.0), Wait(d * 4))) track.append(Func(self.cleanupTrack)) track.delayDelete = DelayDelete.DelayDelete(avatar, "knockKnockTrack") return track def cleanupTrack(self): avatar = self.cr.doId2do.get(self.avatarId) if avatar: avatar.clearChat() if self.nametag: self.nametag.unmanage(base.marginManager) self.nametagNP.removeNode() self.nametag.destroy() self.nametag = None self.nametagNP = None def enterOff(self): DistributedAnimatedProp.DistributedAnimatedProp.enterOff(self) def exitOff(self): DistributedAnimatedProp.DistributedAnimatedProp.exitOff(self) def enterAttract(self, ts): DistributedAnimatedProp.DistributedAnimatedProp.enterAttract(self, ts) self.acceptAvatar() def exitAttract(self): DistributedAnimatedProp.DistributedAnimatedProp.exitAttract(self) def enterPlaying(self, ts): DistributedAnimatedProp.DistributedAnimatedProp.enterPlaying(self, ts) if self.avatarId: avatar = self.cr.doId2do.get(self.avatarId, None) track = self.knockKnockTrack(avatar, 8) if track != None: track.start(ts) self.avatarTracks.append(track) return def exitPlaying(self): DistributedAnimatedProp.DistributedAnimatedProp.exitPlaying(self) self.stopTracks() def stopTracks(self): for track in self.avatarTracks: track.pause() DelayDelete.cleanupDelayDeletes(track) self.cleanupTrack() self.avatarTracks = [] self.avatarId = 0