from direct.directnotify import DirectNotifyGlobal from direct.gui import DirectGuiGlobals as DGG from direct.showbase.PythonUtil import Functor from direct.task.Task import Task import MinigameGlobals from PurchaseBase import * from toontown.distributed import DelayDelete from otp.nametag.NametagFloat2d import * from otp.nametag import NametagGlobals from toontown.toon import ToonHead from toontown.toonbase import ToontownGlobals from toontown.toonbase import ToontownTimer COUNT_UP_RATE = 0.15 COUNT_UP_DURATION = 0.5 DELAY_BEFORE_COUNT_UP = 1.0 DELAY_AFTER_COUNT_UP = 1.0 COUNT_DOWN_RATE = 0.075 COUNT_DOWN_DURATION = 0.5 DELAY_AFTER_COUNT_DOWN = 0.0 DELAY_AFTER_CELEBRATE = 2.6 COUNT_SFX_MIN_DELAY = 0.034 COUNT_SFX_START_T = 0.079 OVERMAX_SFX_MIN_DELAY = 0.067 OVERMAX_SFX_START_T = 0.021 class Purchase(PurchaseBase): notify = DirectNotifyGlobal.directNotify.newCategory('Purchase') def __init__(self, toon, pointsArray, playerMoney, ids, states, remain, doneEvent): PurchaseBase.__init__(self, toon, doneEvent) self.ids = ids self.pointsArray = pointsArray self.playerMoney = playerMoney self.states = states self.remain = remain self.tutorialMode = 0 self.fsm.addState(State.State('reward', self.enterReward, self.exitReward, ['purchase'])) doneState = self.fsm.getStateNamed('done') doneState.addTransition('reward') self.unexpectedEventNames = [] self.unexpectedExits = [] self.setupUnexpectedExitHooks() def load(self): purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui') PurchaseBase.load(self, purchaseModels) interiorPhase = 3.5 self.bg = loader.loadModel('phase_%s/models/modules/toon_interior' % interiorPhase) self.bg.setPos(0.0, 5.0, -1.0) self.wt = self.bg.find('**/random_tc1_TI_wallpaper') wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.jpg' % interiorPhase) self.wt.setTexture(wallTex, 100) self.wt.setColorScale(0.8, 0.67, 0.549, 1.0) self.bt = self.bg.find('**/random_tc1_TI_wallpaper_border') wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.jpg' % interiorPhase) self.bt.setTexture(wallTex, 100) self.bt.setColorScale(0.8, 0.67, 0.549, 1.0) self.wb = self.bg.find('**/random_tc1_TI_wainscotting') wainTex = loader.loadTexture('phase_%s/maps/wall_paper_b4.jpg' % interiorPhase) self.wb.setTexture(wainTex, 100) self.wb.setColorScale(0.473, 0.675, 0.488, 1.0) self.playAgain = DirectButton(parent=self.frame, relief=None, scale=1.04, pos=(0.72, 0, -0.24), image=(purchaseModels.find('**/PurchScrn_BTN_UP'), purchaseModels.find('**/PurchScrn_BTN_DN'), purchaseModels.find('**/PurchScrn_BTN_RLVR'), purchaseModels.find('**/PurchScrn_BTN_UP')), text=TTLocalizer.GagShopPlayAgain, text_fg=(0, 0.1, 0.7, 1), text_scale=0.05, text_pos=(0, 0.015, 0), image3_color=Vec4(0.6, 0.6, 0.6, 1), text3_fg=Vec4(0, 0, 0.4, 1), command=self.__handlePlayAgain) self.backToPlayground = DirectButton(parent=self.frame, relief=None, scale=1.04, pos=(0.72, 0, -0.045), image=(purchaseModels.find('**/PurchScrn_BTN_UP'), purchaseModels.find('**/PurchScrn_BTN_DN'), purchaseModels.find('**/PurchScrn_BTN_RLVR'), purchaseModels.find('**/PurchScrn_BTN_UP')), text=TTLocalizer.GagShopBackToPlayground, text_fg=(0, 0.1, 0.7, 1), text_scale=0.05, text_pos=(0, 0.015, 0), image3_color=Vec4(0.6, 0.6, 0.6, 1), text3_fg=Vec4(0, 0, 0.4, 1), command=self.__handleBackToPlayground) self.timer = ToontownTimer.ToontownTimer() self.timer.hide() self.timer.posInTopRightCorner() numAvs = 0 count = 0 localToonIndex = 0 for index in xrange(len(self.ids)): avId = self.ids[index] if avId == base.localAvatar.doId: localToonIndex = index if self.states[index] != PURCHASE_NO_CLIENT_STATE and self.states[index] != PURCHASE_DISCONNECTED_STATE: numAvs = numAvs + 1 layoutList = (None, (0,), (0, 2), (0, 1, 3), (0, 1, 2, 3)) layout = layoutList[numAvs] headFramePosList = (Vec3(0.105, 0, -0.384), Vec3(0.105, 0, -0.776), Vec3(0.85, 0, -0.555), Vec3(-0.654, 0, -0.555)) AVID_INDEX = 0 LAYOUT_INDEX = 1 TOON_INDEX = 2 self.avInfoArray = [(base.localAvatar.doId, headFramePosList[0], localToonIndex)] pos = 1 for index in xrange(len(self.ids)): avId = self.ids[index] if self.states[index] != PURCHASE_NO_CLIENT_STATE and self.states[index] != PURCHASE_DISCONNECTED_STATE: if avId != base.localAvatar.doId: if avId in base.cr.doId2do: self.avInfoArray.append((avId, headFramePosList[layout[pos]], index)) pos = pos + 1 self.headFrames = [] for avInfo in self.avInfoArray: av = base.cr.doId2do.get(avInfo[AVID_INDEX]) if av: headFrame = PurchaseHeadFrame(av, purchaseModels) headFrame.setAvatarState(self.states[avInfo[TOON_INDEX]]) headFrame.setPos(avInfo[LAYOUT_INDEX]) self.headFrames.append((avInfo[AVID_INDEX], headFrame)) purchaseModels.removeNode() self.foreground = loader.loadModel('phase_3.5/models/modules/TT_A1') self.foreground.setPos(12.5, -20, -5.5) self.foreground.setHpr(180, 0, 0) self.backgroundL = self.foreground.copyTo(hidden) self.backgroundL.setPos(-14.5, -25, -5) self.backgroundL.setHpr(180, 0, 0) self.backgroundR = self.backgroundL.copyTo(hidden) self.backgroundR.setPos(30, -25, -5) self.backgroundR.setHpr(180, 0, 0) streets = loader.loadModel('phase_3.5/models/modules/street_modules') sidewalk = streets.find('**/street_sidewalk_40x40') self.sidewalk = sidewalk.copyTo(hidden) self.sidewalkR = sidewalk.copyTo(hidden) self.sidewalkL = sidewalk.copyTo(hidden) self.sidewalk.setPos(-20, -25, -5.5) self.sidewalk.setColor(0.9, 0.6, 0.4) self.sidewalkL.setPos(-40, -25, -5.5) self.sidewalkL.setColor(0.9, 0.6, 0.4) self.sidewalkR.setPos(0, -25, -5.5) self.sidewalkR.setColor(0.9, 0.6, 0.4) streets.removeNode() doors = loader.loadModel('phase_4/models/modules/doors') door = doors.find('**/door_single_square_ur_door') self.door = door.copyTo(hidden) self.door.setH(180) self.door.setPos(0, -16.75, -5.5) self.door.setScale(1.5, 1.5, 2.0) self.door.setColor(1.0, 0.8, 0, 1) doors.removeNode() self.rewardDoubledJellybeanLabel = DirectLabel(text=TTLocalizer.PartyRewardDoubledJellybean, text_fg=(1.0, 0.125, 0.125, 1.0), text_shadow=(0, 0, 0, 1), relief=None, pos=(0.0, 0, -0.67), scale=0.08) self.rewardDoubledJellybeanLabel.hide() self.countSound = base.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg') self.overMaxSound = base.loadSfx('phase_3.5/audio/sfx/AV_collision.ogg') self.celebrateSound = base.loadSfx('phase_4/audio/sfx/MG_win.ogg') return def unload(self): PurchaseBase.unload(self) self.cleanupUnexpectedExitHooks() self.bg.removeNode() del self.bg self.notify.debug('destroying head frames') for headFrame in self.headFrames: if not headFrame[1].isEmpty(): headFrame[1].reparentTo(hidden) headFrame[1].destroy() del self.headFrames self.playAgain.destroy() del self.playAgain self.backToPlayground.destroy() del self.backToPlayground self.timer.stop() self.timer.destroy() del self.timer for counter in self.counters: counter.destroy() del counter del self.counters for total in self.totalCounters: total.destroy() del total del self.totalCounters loader.unloadModel('phase_3.5/models/modules/TT_A1') loader.unloadModel('phase_3.5/models/modules/street_modules') loader.unloadModel('phase_4/models/modules/doors') taskMgr.remove('countUpTask') taskMgr.remove('countDownTask') taskMgr.remove('celebrate') taskMgr.remove('purchase-trans') taskMgr.remove('delayAdd') taskMgr.remove('delaySubtract') self.foreground.removeNode() del self.foreground self.backgroundL.removeNode() del self.backgroundL self.backgroundR.removeNode() del self.backgroundR self.sidewalk.removeNode() self.sidewalkL.removeNode() self.sidewalkR.removeNode() del self.sidewalk del self.sidewalkL del self.sidewalkR self.door.removeNode() del self.door self.collisionFloor.removeNode() del self.collisionFloor del self.countSound del self.celebrateSound self.rewardDoubledJellybeanLabel.removeNode() del self.rewardDoubledJellybeanLabel def showStatusText(self, text): self.statusLabel['text'] = text taskMgr.remove('resetStatusText') taskMgr.doMethodLater(2.0, self.resetStatusText, 'resetStatusText') def resetStatusText(self, task): self.statusLabel['text'] = '' return Task.done def __handlePlayAgain(self): for headFrame in self.headFrames: headFrame[1].wrtReparentTo(aspect2d) self.toon.inventory.reparentTo(hidden) self.toon.inventory.hide() taskMgr.remove('resetStatusText') taskMgr.remove('showBrokeMsgTask') self.statusLabel['text'] = TTLocalizer.WaitingForOtherToons messenger.send('purchasePlayAgain') def handleDone(self, playAgain): base.localAvatar.b_setParent(ToontownGlobals.SPHidden) if playAgain: self.doneStatus = {'loader': 'minigame', 'where': 'minigame'} else: self.doneStatus = {'loader': 'safeZoneLoader', 'where': 'playground'} messenger.send(self.doneEvent) def __handleBackToPlayground(self): self.toon.inventory.reparentTo(hidden) self.toon.inventory.hide() messenger.send('purchaseBackToToontown') def __timerExpired(self): messenger.send('purchaseTimeout') def findHeadFrame(self, id): for headFrame in self.headFrames: if headFrame[0] == id: return headFrame[1] return None def __handleStateChange(self, playerStates): self.states = playerStates for avInfo in self.avInfoArray: index = avInfo[2] headFrame = self.findHeadFrame(avInfo[0]) state = self.states[index] headFrame.setAvatarState(state) def enter(self): base.playMusic(self.music, looping=1, volume=0.8) self.fsm.request('reward') def enterReward(self): numToons = 0 toonLayouts = ((2,), (1, 3), (0, 2, 4), (0, 1, 3, 4)) toonPositions = (5.0, 1.75, -0.25, -1.75, -5.0) self.toons = [] self.toonsKeep = [] self.counters = [] self.totalCounters = [] camera.reparentTo(render) camera.setPos(0, 16.0, 2.0) camera.lookAt(0, 0, 0.75) base.transitions.irisIn(0.4) base.camLens.setMinFov(60/(4./3.)) base.setBackgroundColor(Vec4(0, 0.6, 1, 1)) self.title.reparentTo(aspect2d) self.foreground.reparentTo(render) self.backgroundL.reparentTo(render) self.backgroundR.reparentTo(render) self.sidewalk.reparentTo(render) self.sidewalkL.reparentTo(render) self.sidewalkR.reparentTo(render) self.door.reparentTo(render) size = 20 z = -2.5 floor = CollisionPolygon(Point3(-size, -size, z), Point3(size, -size, z), Point3(size, size, z), Point3(-size, size, z)) floor.setTangible(1) floorNode = CollisionNode('collision_floor') floorNode.addSolid(floor) self.collisionFloor = render.attachNewNode(floorNode) NametagGlobals.setOnscreenChatForced(1) for index in xrange(len(self.ids)): avId = self.ids[index] if self.states[index] != PURCHASE_NO_CLIENT_STATE and self.states[index] != PURCHASE_DISCONNECTED_STATE and avId in base.cr.doId2do: numToons += 1 toon = base.cr.doId2do[avId] toon.stopSmooth() self.toons.append(toon) self.toonsKeep.append(DelayDelete.DelayDelete(toon, 'Purchase.enterReward')) counter = DirectLabel(parent=hidden, relief=None, pos=(0.0, 0.0, 0.0), text=str(0), text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -0.1, 0), text_font=ToontownGlobals.getSignFont()) counter['image'] = DGG.getDefaultDialogGeom() counter['image_scale'] = (0.33, 1, 0.33) counter.setScale(0.5) counter.count = 0 counter.max = self.pointsArray[index] self.counters.append(counter) money = self.playerMoney[index] totalCounter = DirectLabel(parent=hidden, relief=None, pos=(0.0, 0.0, 0.0), text=str(money), text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -0.1, 0), text_font=ToontownGlobals.getSignFont(), image=self.jarImage) totalCounter.setScale(0.5) totalCounter.count = money totalCounter.max = toon.getMaxMoney() self.totalCounters.append(totalCounter) self.accept('clientCleanup', self._handleClientCleanup) pos = 0 toonLayout = toonLayouts[numToons - 1] for toon in self.toons: thisPos = toonPositions[toonLayout[pos]] toon.setPos(Vec3(thisPos, 1.0, -2.5)) toon.setHpr(Vec3(0, 0, 0)) toon.setAnimState('neutral', 1) toon.setShadowHeight(0) if not toon.isDisabled(): toon.reparentTo(render) self.counters[pos].setPos(thisPos * -0.17, 0, toon.getHeight() / 10 + 0.25) self.counters[pos].reparentTo(aspect2d) self.totalCounters[pos].setPos(thisPos * -0.17, 0, -0.825) self.totalCounters[pos].reparentTo(aspect2d) pos += 1 self.maxPoints = max(self.pointsArray) def reqCountUp(state): self.countUp() return Task.done countUpDelay = DELAY_BEFORE_COUNT_UP taskMgr.doMethodLater(countUpDelay, reqCountUp, 'countUpTask') def reqCountDown(state): self.countDown() return Task.done countDownDelay = countUpDelay + COUNT_UP_DURATION + DELAY_AFTER_COUNT_UP taskMgr.doMethodLater(countDownDelay, reqCountDown, 'countDownTask') def celebrate(task): for counter in task.counters: counter.hide() winningPoints = max(task.pointsArray) for i in xrange(len(task.ids)): if task.pointsArray[i] == winningPoints: avId = task.ids[i] if avId in base.cr.doId2do: toon = base.cr.doId2do[avId] toon.setAnimState('jump', 1.0) base.playSfx(task.celebrateSound) return Task.done celebrateDelay = countDownDelay + COUNT_DOWN_DURATION + DELAY_AFTER_COUNT_DOWN celebrateTask = taskMgr.doMethodLater(celebrateDelay, celebrate, 'celebrate') celebrateTask.counters = self.counters celebrateTask.pointsArray = self.pointsArray celebrateTask.ids = self.ids celebrateTask.celebrateSound = self.celebrateSound def reqPurchase(state): self.fsm.request('purchase') return Task.done purchaseDelay = celebrateDelay + DELAY_AFTER_CELEBRATE taskMgr.doMethodLater(purchaseDelay, reqPurchase, 'purchase-trans') if base.skipMinigameReward: self.fsm.request('purchase') return def _changeCounterUp(self, task, counter, newCount, toonId): counter.count = newCount counter['text'] = str(counter.count) if toonId == base.localAvatar.doId: now = globalClock.getRealTime() if task.lastSfxT + COUNT_SFX_MIN_DELAY < now: base.playSfx(task.countSound, time=COUNT_SFX_START_T) task.lastSfxT = now def _countUpTask(self, task): now = globalClock.getRealTime() startT = task.getStartTime() if now >= startT + task.duration: for counter, toonId in zip(self.counters, self.ids): if counter.count != counter.max: self._changeCounterUp(task, counter, counter.max, toonId) return Task.done t = (now - startT) / task.duration for counter, toonId in zip(self.counters, self.ids): curCount = int(t * counter.max) if curCount != counter.count: self._changeCounterUp(task, counter, curCount, toonId) return Task.cont def countUp(self): totalDelay = 0 if base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY) or base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY_MONTH): self.rewardDoubledJellybeanLabel.show() countUpTask = taskMgr.add(self._countUpTask, 'countUp') countUpTask.duration = COUNT_UP_DURATION countUpTask.countSound = self.countSound countUpTask.lastSfxT = 0 def _changeCounterDown(self, task, counter, newCount, total, toonId): counter.count = newCount counter['text'] = str(counter.count) total.count = total.startAmount + (counter.max - newCount) if total.count > total.max: total.count = total.max total['text'] = str(total.count) if total.count == total.max: total['text_fg'] = (1, 0, 0, 1) if toonId == base.localAvatar.doId: now = globalClock.getRealTime() if total.count < total.max: minDelay = COUNT_SFX_MIN_DELAY snd = task.countSound startT = COUNT_SFX_START_T else: minDelay = OVERMAX_SFX_MIN_DELAY snd = task.overMaxSound startT = OVERMAX_SFX_START_T if task.lastSfxT + minDelay < now: task.lastSfxT = now base.playSfx(snd, time=startT) def _countDownTask(self, task): now = globalClock.getRealTime() startT = task.getStartTime() if now >= startT + task.duration: for counter, total, toonId in zip(self.counters, self.totalCounters, self.ids): if counter.count != 0: self._changeCounterDown(task, counter, 0, total, toonId) return Task.done t = (now - startT) / task.duration for counter, total, toonId in zip(self.counters, self.totalCounters, self.ids): curCount = int(counter.max * (1 - t)) if curCount != counter.count: self._changeCounterDown(task, counter, curCount, total, toonId) return Task.cont def countDown(self): totalDelay = 0 for total in self.totalCounters: total.startAmount = total.count countDownTask = taskMgr.add(self._countDownTask, 'countDown') countDownTask.duration = COUNT_DOWN_DURATION countDownTask.countSound = self.countSound countDownTask.overMaxSound = self.overMaxSound countDownTask.lastSfxT = 0 def exitReward(self): self.ignore('clientCleanup') taskMgr.remove('countUpTask') taskMgr.remove('countDownTask') taskMgr.remove('celebrate') taskMgr.remove('purchase-trans') taskMgr.remove('delayAdd') taskMgr.remove('delaySubtract') for toon in self.toons: toon.detachNode() del self.toons if hasattr(self, 'toonsKeep'): for delayDelete in self.toonsKeep: delayDelete.destroy() del self.toonsKeep for counter in self.counters: counter.reparentTo(hidden) for total in self.totalCounters: total.reparentTo(hidden) self.foreground.reparentTo(hidden) self.backgroundL.reparentTo(hidden) self.backgroundR.reparentTo(hidden) self.sidewalk.reparentTo(hidden) self.sidewalkL.reparentTo(hidden) self.sidewalkR.reparentTo(hidden) self.door.reparentTo(hidden) self.title.reparentTo(self.frame) self.rewardDoubledJellybeanLabel.hide() base.camLens.setMinFov(settings['fov']/(4./3.)) NametagGlobals.setOnscreenChatForced(0) def _handleClientCleanup(self): if hasattr(self, 'toonsKeep'): for delayDelete in self.toonsKeep: delayDelete.destroy() del self.toonsKeep self.ignore('clientCleanup') def enterPurchase(self): PurchaseBase.enterPurchase(self) self.rewardDoubledJellybeanLabel.hide() self.bg.reparentTo(render) base.setBackgroundColor(0.78, 0.65, 0.53) self.accept('purchaseStateChange', self.__handleStateChange) self.playAgain.reparentTo(self.toon.inventory.purchaseFrame) self.backToPlayground.reparentTo(self.toon.inventory.purchaseFrame) self.pointDisplay.reparentTo(self.toon.inventory.purchaseFrame) self.statusLabel.reparentTo(self.toon.inventory.purchaseFrame) for headFrame in self.headFrames: headFrame[1].show() headFrame[1].reparentTo(self.toon.inventory.purchaseFrame) if not self.tutorialMode: if not config.GetBool('disable-purchase-timer', 0): self.timer.show() self.timer.countdown(self.remain, self.__timerExpired) else: self.timer.hide() self.disablePlayAgain() self.accept('disableGagPanel', Functor(self.toon.inventory.setActivateMode, 'gagTutDisabled', gagTutMode=1)) self.accept('disableBackToPlayground', self.disableBackToPlayground) self.accept('enableGagPanel', self.handleEnableGagPanel) self.accept('enableBackToPlayground', self.enableBackToPlayground) for avId, headFrame in self.headFrames: if avId != self.newbieId: headFrame.hide() messenger.send('gagScreenIsUp') if base.autoPlayAgain: base.transitions.fadeOut(0) self.__handlePlayAgain() def exitPurchase(self): PurchaseBase.exitPurchase(self) self.ignore('disableGagPanel') self.ignore('disableBackToPlayground') self.ignore('enableGagPanel') self.ignore('enableBackToPlayground') self.bg.reparentTo(hidden) self.playAgain.reparentTo(self.frame) self.backToPlayground.reparentTo(self.frame) self.pointDisplay.reparentTo(self.frame) self.statusLabel.reparentTo(self.frame) self.ignore('purchaseStateChange') base.setBackgroundColor(ToontownGlobals.DefaultBackgroundColor) if base.autoPlayAgain: base.transitions.fadeIn() def disableBackToPlayground(self): self.backToPlayground['state'] = DGG.DISABLED def enableBackToPlayground(self): self.backToPlayground['state'] = DGG.NORMAL def disablePlayAgain(self): self.playAgain['state'] = DGG.DISABLED def enablePlayAgain(self): self.playAgain['state'] = DGG.NORMAL def enterTutorialMode(self, newbieId): self.tutorialMode = 1 self.newbieId = newbieId def handleEnableGagPanel(self): self.toon.inventory.setActivateMode('purchase', gagTutMode=1) self.checkForBroke() def handleGagTutorialDone(self): self.enableBackToPlayground() def setupUnexpectedExitHooks(self): for avId in self.ids: if avId in base.cr.doId2do: toon = base.cr.doId2do[avId] eventName = toon.uniqueName('disable') self.accept(eventName, self.__handleUnexpectedExit, extraArgs=[avId]) self.unexpectedEventNames.append(eventName) def cleanupUnexpectedExitHooks(self): for eventName in self.unexpectedEventNames: self.ignore(eventName) def __handleUnexpectedExit(self, avId): self.unexpectedExits.append(avId) class PurchaseHeadFrame(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory('Purchase') def __init__(self, av, purchaseModels): DirectFrame.__init__(self, relief=None, image=purchaseModels.find('**/Char_Pnl')) self.initialiseoptions(PurchaseHeadFrame) self.statusLabel = DirectLabel(parent=self, relief=None, text='', text_scale=TTLocalizer.PstatusLabel, text_wordwrap=7.5, text_fg=(0.05, 0.14, 0.4, 1), text_pos=(0.1, 0, 0)) self.av = av self.avKeep = DelayDelete.DelayDelete(av, 'PurchaseHeadFrame.av') self.accept('clientCleanup', self._handleClientCleanup) self.head = self.stateNodePath[0].attachNewNode('head', 20) self.head.setPosHprScale(-0.22, 10.0, -0.1, 180.0, 0.0, 0.0, 0.1, 0.1, 0.1) self.headModel = ToonHead.ToonHead() self.headModel.setupHead(self.av.style, forGui=1) self.headModel.reparentTo(self.head) self.tag2Node = NametagFloat2d() self.tag2Node.setContents(Nametag.CName) self.av.nametag.addNametag(self.tag2Node) self.tag2 = self.attachNewNode(self.tag2Node) self.tag2.setPosHprScale(-0.22, 10.0, 0.12, 0, 0, 0, 0.046, 0.046, 0.046) self.tag1Node = NametagFloat2d() self.tag1Node.setContents(Nametag.CSpeech | Nametag.CThought) self.av.nametag.addNametag(self.tag1Node) self.tag1 = self.attachNewNode(self.tag1Node) self.tag1.setPosHprScale(-0.15, 0, -0.1, 0, 0, 0, 0.046, 0.046, 0.046) self.hide() def destroy(self): DirectFrame.destroy(self) del self.statusLabel self.headModel.delete() del self.headModel self.head.removeNode() del self.head self.av.nametag.removeNametag(self.tag1Node) self.av.nametag.removeNametag(self.tag2Node) self.tag1.removeNode() self.tag2.removeNode() del self.tag1 del self.tag2 del self.tag1Node del self.tag2Node del self.av self.removeAvKeep() def setAvatarState(self, state): if state == PURCHASE_DISCONNECTED_STATE: self.statusLabel['text'] = TTLocalizer.GagShopPlayerDisconnected % self.av.getName() self.statusLabel['text_pos'] = (0.015, 0.072, 0) self.head.hide() self.tag1.hide() self.tag2.hide() elif state == PURCHASE_EXIT_STATE: self.statusLabel['text'] = TTLocalizer.GagShopPlayerExited % self.av.getName() self.statusLabel['text_pos'] = (0.015, 0.072, 0) self.head.hide() self.tag1.hide() self.tag2.hide() elif state == PURCHASE_PLAYAGAIN_STATE: self.statusLabel['text'] = TTLocalizer.GagShopPlayerPlayAgain self.statusLabel['text_pos'] = (0.1, -0.12, 0) elif state == PURCHASE_WAITING_STATE: self.statusLabel['text'] = TTLocalizer.GagShopPlayerBuying self.statusLabel['text_pos'] = (0.1, -0.12, 0) elif state == PURCHASE_NO_CLIENT_STATE: Purchase.notify.warning("setAvatarState('no client state'); OK for gag purchase tutorial") else: Purchase.notify.warning('unknown avatar state: %s' % state) def _handleClientCleanup(self): self.destroy() def removeAvKeep(self): if hasattr(self, 'avKeep'): self.notify.debug('destroying avKeep %s' % self.avKeep) self.avKeep.destroy() del self.avKeep self.ignore('clientCleanup')