import random import math import time import re import zlib from direct.interval.IntervalGlobal import * from direct.distributed.ClockDelta import * from direct.showbase.PythonUtil import * from direct.gui.DirectGui import * from direct.task import Task from direct.showbase import PythonUtil from direct.directnotify import DirectNotifyGlobal from direct.gui import DirectGuiGlobals from pandac.PandaModules import * from libotp import * from otp.avatar import LocalAvatar from otp.login import LeaveToPayDialog from otp.avatar import PositionExaminer from otp.otpbase import OTPGlobals from otp.avatar import DistributedPlayer from toontown.shtiker import ShtikerBook from toontown.shtiker import InventoryPage from toontown.shtiker import MapPage from toontown.shtiker import OptionsPage from toontown.shtiker import ShardPage from toontown.shtiker import QuestPage from toontown.shtiker import TrackPage from toontown.shtiker import KartPage from toontown.shtiker import GardenPage from toontown.shtiker import GolfPage from toontown.shtiker import SuitPage from toontown.shtiker import DisguisePage from toontown.shtiker import PhotoAlbumPage from toontown.shtiker import FishPage from toontown.shtiker import NPCFriendPage from toontown.shtiker import EventsPage from toontown.shtiker import TIPPage from toontown.quest import Quests from toontown.quest import QuestParser from toontown.toonbase.ToontownGlobals import * from toontown.toonbase import ToontownGlobals from toontown.toonbase import TTLocalizer from toontown.catalog import CatalogNotifyDialog from toontown.chat import ToontownChatManager from toontown.chat import TTTalkAssistant from toontown.estate import GardenGlobals from toontown.battle.BattleSounds import * from toontown.battle import Fanfare from toontown.parties import PartyGlobals from toontown.toon import ElevatorNotifier from toontown.toon import ToonDNA from . import DistributedToon from . import Toon from . import LaffMeter from toontown.quest import QuestMap from toontown.toon.DistributedNPCToonBase import DistributedNPCToonBase WantNewsPage = base.config.GetBool('want-news-page', ToontownGlobals.DefaultWantNewsPageSetting) from toontown.toontowngui import NewsPageButtonManager if WantNewsPage: from toontown.shtiker import NewsPage AdjustmentForNewsButton = -0.275 ClaraBaseXPos = 1.45 if (__debug__): import pdb class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): neverDisable = 1 piePowerSpeed = base.config.GetDouble('pie-power-speed', 0.2) piePowerExponent = base.config.GetDouble('pie-power-exponent', 0.75) def __init__(self, cr): try: self.LocalToon_initialized except: self.LocalToon_initialized = 1 self.numFlowers = 0 self.maxFlowerBasket = 0 DistributedToon.DistributedToon.__init__(self, cr) chatMgr = ToontownChatManager.ToontownChatManager(cr, self) talkAssistant = TTTalkAssistant.TTTalkAssistant() LocalAvatar.LocalAvatar.__init__(self, cr, chatMgr, talkAssistant, passMessagesThrough=True) self.soundRun = base.loader.loadSfx('phase_3.5/audio/sfx/AV_footstep_runloop.wav') self.soundWalk = base.loader.loadSfx('phase_3.5/audio/sfx/AV_footstep_walkloop.wav') self.soundWhisper = base.loader.loadSfx('phase_3.5/audio/sfx/GUI_whisper_3.mp3') self.soundPhoneRing = base.loader.loadSfx('phase_3.5/audio/sfx/telephone_ring.mp3') self.soundSystemMessage = base.loader.loadSfx('phase_3/audio/sfx/clock03.mp3') self.positionExaminer = PositionExaminer.PositionExaminer() friendsGui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') friendsButtonNormal = friendsGui.find('**/FriendsBox_Closed') friendsButtonPressed = friendsGui.find('**/FriendsBox_Rollover') friendsButtonRollover = friendsGui.find('**/FriendsBox_Rollover') newScale = oldScale = 0.8 if WantNewsPage: newScale = oldScale * ToontownGlobals.NewsPageScaleAdjust self.bFriendsList = DirectButton(image=(friendsButtonNormal, friendsButtonPressed, friendsButtonRollover), relief=None, pos=(1.192, 0, 0.875), scale=newScale, text=('', TTLocalizer.FriendsListLabel, TTLocalizer.FriendsListLabel), text_scale=0.09, text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0, -0.18), text_font=ToontownGlobals.getInterfaceFont(), command=self.sendFriendsListEvent) self.bFriendsList.hide() self.friendsListButtonActive = 0 self.friendsListButtonObscured = 0 self.moveFurnitureButtonObscured = 0 self.clarabelleButtonObscured = 0 friendsGui.removeNode() self.__furnitureGui = None self.__clarabelleButton = None self.__clarabelleFlash = None self.furnitureManager = None self.furnitureDirector = None self.gotCatalogNotify = 0 self.__catalogNotifyDialog = None self.accept('phaseComplete-5.5', self.loadPhase55Stuff) Toon.loadDialog() self.isIt = 0 self.cantLeaveGame = 0 self.tunnelX = 0.0 self.estate = None self.__pieBubble = None self.allowPies = 0 self.__pieButton = None self.__piePowerMeter = None self.__piePowerMeterSequence = None self.__pieButtonType = None self.__pieButtonCount = None self.tossPieStart = None self.__presentingPie = 0 self.__pieSequence = 0 self.wantBattles = base.config.GetBool('want-battles', 1) self.seeGhosts = base.config.GetBool('see-ghosts', 0) wantNameTagAvIds = base.config.GetBool('want-nametag-avids', 0) if wantNameTagAvIds: messenger.send('nameTagShowAvId', []) base.idTags = 1 self.glitchX = 0 self.glitchY = 0 self.glitchZ = 0 self.glitchCount = 0 self.ticker = 0 self.glitchOkay = 1 self.tempGreySpacing = 0 self.wantStatePrint = base.config.GetBool('want-statePrint', 0) self.__gardeningGui = None self.__gardeningGuiFake = None self.__shovelButton = None self.shovelRelatedDoId = 0 self.shovelAbility = '' self.plantToWater = 0 self.shovelButtonActiveCount = 0 self.wateringCanButtonActiveCount = 0 self.showingWateringCan = 0 self.showingShovel = 0 self.touchingPlantList = [] self.inGardenAction = None self.guiConflict = 0 self.lastElevatorLeft = 0 self.elevatorNotifier = ElevatorNotifier.ElevatorNotifier() self.accept(OTPGlobals.AvatarFriendAddEvent, self.sbFriendAdd) self.accept(OTPGlobals.AvatarFriendUpdateEvent, self.sbFriendUpdate) self.accept(OTPGlobals.AvatarFriendRemoveEvent, self.sbFriendRemove) self._zoneId = None self.accept('system message aknowledge', self.systemWarning) self.systemMsgAckGuiDoneEvent = 'systemMsgAckGuiDoneEvent' self.accept(self.systemMsgAckGuiDoneEvent, self.hideSystemMsgAckGui) self.systemMsgAckGui = None self.createSystemMsgAckGui() if not hasattr(base.cr, 'lastLoggedIn'): base.cr.lastLoggedIn = self.cr.toontownTimeManager.convertStrToToontownTime('') self.setLastTimeReadNews(base.cr.lastLoggedIn) self.acceptingNewFriends = Settings.getAcceptingNewFriends() and base.config.GetBool('accepting-new-friends-default', True) self.acceptingNonFriendWhispers = Settings.getAcceptingNonFriendWhispers() and base.config.GetBool('accepting-non-friend-whispers-default', True) self.physControls.event.addAgainPattern('again%in') self.oldPos = None self.questMap = None self.prevToonIdx = 0 def wantLegacyLifter(self): return True def startGlitchKiller(self): if localAvatar.getZoneId() not in GlitchKillerZones: return if __dev__: self.glitchMessage = 'START GLITCH KILLER' randChoice = random.randint(0, 3) if randChoice == 0: self.glitchMessage = 'START GLITCH KILLER' elif randChoice == 1: self.glitchMessage = 'GLITCH KILLER ENGAGED' elif randChoice == 2: self.glitchMessage = 'GLITCH KILLER GO!' elif randChoice == 3: self.glitchMessage = 'GLITCH IN YO FACE FOOL!' self.notify.debug(self.glitchMessage) taskMgr.remove(self.uniqueName('glitchKiller')) taskMgr.add(self.glitchKiller, self.uniqueName('glitchKiller')) self.glitchOkay = 1 def pauseGlitchKiller(self): self.tempGreySpacing = 1 def unpauseGlitchKiller(self): self.tempGreySpacing = 0 def stopGlitchKiller(self): if __dev__ and hasattr(self, 'glitchMessage'): if self.glitchMessage == 'START GLITCH KILLER': self.notify.debug('STOP GLITCH KILLER') elif self.glitchMessage == 'GLITCH KILLER ENGAGED': self.notify.debug('GLITCH KILLER DISENGAGED') elif self.glitchMessage == 'GLITCH KILLER GO!': self.notify.debug('GLITCH KILLER NO GO!') elif self.glitchMessage == 'GLITCH IN YO FACE FOOL!': self.notify.debug('GLITCH OFF YO FACE FOOL!') taskMgr.remove(self.uniqueName('glitchKiller')) self.glitchOkay = 1 def glitchKiller(self, taskFooler = 0): if base.greySpacing or self.tempGreySpacing: return Task.cont self.ticker += 1 if not self.physControls.lifter.hasContact() and not self.glitchOkay: self.glitchCount += 1 else: self.glitchX = self.getX() self.glitchY = self.getY() self.glitchZ = self.getZ() self.glitchCount = 0 if self.physControls.lifter.hasContact(): self.glitchOkay = 0 if hasattr(self, 'physControls'): if self.ticker >= 10: self.ticker = 0 if self.glitchCount >= 7: print('GLITCH MAXED!!! resetting pos') self.setX(self.glitchX - 1 * (self.getX() - self.glitchX)) self.setY(self.glitchY - 1 * (self.getY() - self.glitchY)) self.glitchCount = 0 return Task.cont def announceGenerate(self): self.startLookAround() if base.wantNametags: self.nametag.manage(base.marginManager) self.startHackObservation() DistributedToon.DistributedToon.announceGenerate(self) from otp.friends import FriendInfo def toonPosCheck(self, task = None): toon = random.choice(list(self.cr.toons.values())) if toon and toon is not self and not isinstance(toon, DistributedNPCToonBase): self.notify.debug('checking position for %s' % toon.doId) realTimeStart = globalClock.getRealTime() numOtherToons = len(list(self.cr.toons.values())) for otherToonIdxBase in range(numOtherToons): otherToonIdx = otherToonIdxBase + self.prevToonIdx if otherToonIdx >= numOtherToons: otherToonIdx = otherToonIdx % numOtherToons if globalClock.getRealTime() > realTimeStart + AV_TOUCH_CHECK_TIMELIMIT_CL: self.notify.debug('too much time, exiting at index %s' % otherToonIdx) self.prevToonIdx = otherToonIdx break otherToon = list(self.cr.toons.values())[otherToonIdx] self.notify.debug('comparing with toon %s at index %s' % (otherToon.doId, otherToonIdx)) if otherToon and otherToon is not toon and otherToon is not self and not isinstance(otherToon, DistributedNPCToonBase): toonPos = toon.getPos(render) otherToonPos = otherToon.getPos(render) self.notify.debug('pos1: %s pos2: %s' % (toonPos, otherToonPos)) zDist = otherToonPos.getZ() - toonPos.getZ() toonPos.setZ(0) otherToonPos.setZ(0) moveVec = otherToonPos - toonPos dist = moveVec.length() self.notify.debug('distance to %s is %s %s' % (otherToon.doId, dist, zDist)) if dist < AV_TOUCH_CHECK_DIST and zDist < AV_TOUCH_CHECK_DIST_Z: self.notify.debug('inappropriate touching!!!') if toon.getParent() == render: toonToMoveId = toon.doId toonToNotMoveId = otherToon.doId else: toonToMoveId = otherToon.doId toonToNotMoveId = toon.doId self.sendUpdate('flagAv', [toonToMoveId, AV_FLAG_REASON_TOUCH, [str(toonToNotMoveId)]]) self.prevToonIdx = otherToonIdx break self.notify.debug('spent %s seconds doing pos check for %s' % (globalClock.getRealTime() - realTimeStart, toon.doId)) return Task.again def tmdcc(self, task = None): toon = random.choice(list(self.cr.toons.values())) result = self._tmdcc(toon) if task: if result: task.setDelay(5.0) else: task.setDelay(1.5) return Task.again def _tmdcc(self, toon, checks = []): result = None if isinstance(toon, DistributedNPCToonBase) or toon is localAvatar or toon.isEmpty() or toon.bFake or toon._delayDeleteForceAllow: return result startTime = globalClock.getRealTime() def delayedSend(toon, msg): if toon: toon.sendLogSuspiciousEvent(msg) return Task.done def sendT(header, msg, sToon, sendFooter = False, sendLs = True): uid = '[' + str(globalClock.getRealTime()) + ']' msgSize = 800 - (len(header) + len(uid) + 1) uname = self.uniqueName('ioorrd234') currCounter = 0 def sendAsParts(message, counter): for currBlock in range(0, len(message) / msgSize + 1): fmsg = '%s %02d: ' % (uid, currBlock + counter) + header + ': "%s"' % message[currBlock * msgSize:currBlock * msgSize + msgSize] taskMgr.doMethodLater(0.08 * (currBlock + counter), delayedSend, uname + str(currBlock + counter), extraArgs=[sToon, fmsg]) return currBlock + counter + 1 currCounter = sendAsParts(msg, currCounter) if sendLs: sstream = StringStream.StringStream() sToon.ls(sstream) sdata = sstream.getData() currCounter = sendAsParts(sdata, currCounter) if sendFooter: sstream.clearData() if hasattr(sToon, 'suitGeom'): sToon.suitGeom.ls(sstream) bs = '' nodeNames = config.GetString('send-suspicious-bam', 'to_head') if nodeNames != '': bs = ' bam ' + nodeNames + ': ' nodesToLog = [] for currName in nodeNames.split(): nodesToLog.append(sToon.find('**/' + currName)) for currNode in nodesToLog: bs += zlib.compress(currNode.encodeToBamStream()).encode('hex') + '_' footer = 'loc: %s dna: %s gmname: %s ntag: %s ceffect: %s disguise: %s sstyle: %s sgeom: %s %s' % (str(sToon.getLocation()), str(sToon.style.asTuple()), sToon.gmNameTagEnabled, str(sToon.nametag and sToon.nametag.getContents()), str(sToon.cheesyEffect), sToon.isDisguised, hasattr(sToon, 'suit') and str(sToon.suit.style), hasattr(sToon, 'suitGeom') and sstream.getData(), bs) currCounter = sendAsParts(footer, currCounter) self.sendUpdate('requestPing', [toon.doId]) if not checks: numChecks = 6 checks = [random.choice(list(range(1, numChecks + 1)))] def findParentAv(node): avId = 0 topParent = node while topParent and not topParent.getTag('avatarDoId'): topParent = topParent.getParent() if topParent: avIdStr = topParent.getTag('avatarDoId') if avIdStr: avId = int(avIdStr) return (self.cr.getDo(avId), avId) msgHeader = 'AvatarHackWarning!' def hacker_detect_immediate(cbdata): action = cbdata.getAction() node = cbdata.getNode() np = NodePath(node) if not self.cr or not self.cr.distributedDistrict or not self.cr.distributedDistrict.getAllowAHNNLog(): if self.cr and self.cr.distributedDistrict: sToon, avId = findParentAv(np) if sToon is localAvatar: return if sToon and isinstance(sToon, DistributedToon.DistributedToon): msg = "Blocking '%s' '%s' '%s'" % (self.cr.distributedDistrict.getAllowAHNNLog(), np, re.sub('<', '[', StackTrace(start=1).compact())) sendT(msgHeader, msg, sToon, sendFooter=False, sendLs=False) return try: parentNames = ['__Actor_modelRoot', 'to_head'] newParent = np.getParent() if newParent and newParent.getName() in parentNames: newParentParent = newParent.getParent() parentParentNames = ['actorGeom', '__Actor_modelRoot'] if newParentParent and newParentParent.getName() in parentParentNames: sToon, avId = findParentAv(newParentParent.getParent()) if sToon is localAvatar: return header = msgHeader + ' nodename' avInfo = "hacker activity '%s' avatar %s node name '%s' with parents '%s' and '%s'!" % (action, avId, np.getName(), newParent.getName(), newParentParent.getName()) if sToon and isinstance(sToon, DistributedToon.DistributedToon): avInfo += ' trace: ' avInfo += re.sub('<', '[', StackTrace(start=1).compact()) sendT(header, avInfo, sToon=sToon, sendFooter=True) else: sendLogSuspiciousEvent(header, 'got non-toon or missing parent %s...' % sToon + avInfo) except: pass if config.GetBool('detect-suspicious-nodename', True): PandaNode.setDetectCallback(PythonCallbackObject(hacker_detect_immediate)) def trackChat(chattingToon): def _spoke(cbdata): avId = cbdata.getId() av = self.cr.getDo(avId) chat = cbdata.getChat() if avId != localAvatar.doId and av: avInfo = 'suspicious chat "%s" trace: ' % chat avInfo += re.sub('<', '[', StackTrace(start=1).compact()) sendT(msgHeader + ' chat', avInfo, chattingToon, sendFooter=False, sendLs=False) chattingToon.nametag.setChatCallback(PythonCallbackObject(_spoke)) chattingToon.nametag.setChatCallbackId(chattingToon.doId) if 1 in checks: if base.config.GetBool('tmdcc-headcheck', 1): headNodes = toon.findAllMatches('**/__Actor_head') if len(headNodes) != 3 or not toon.getGeomNode().isHidden() and [x for x in headNodes if x.isHidden()]: sendT(msgHeader, 'missing head node', toon) result = toon if base.config.GetBool('tmdcc-chatcheck', 1): trackChat(toon) else: checks.append(2) if 2 in checks: if base.config.GetBool('tmdcc-handcheck', 1): if not toon.getGeomNode().isHidden(): handNodes = toon.findAllMatches('**/hands') for currHandNode in handNodes: if currHandNode.hasColor() and currHandNode.getColor() != VBase4(1, 1, 1, 1): sendT(msgHeader, 'invalid hand color: %s' % currHandNode.getColor(), toon) result = toon break else: checks.append(3) if 3 in checks: if base.config.GetBool('tmdcc-namecheck', 1): nameNode = toon.find('**/nametag3d') if not nameNode or nameNode.isHidden() and not toon.getGeomNode().isHidden() and toon.ghostMode == 0: sendT(msgHeader, 'missing nametag for name: %s' % toon.getName(), toon) result = toon else: checks.append(4) if 4 in checks: if base.config.GetBool('tmdcc-animcheck', 1): if toon.zoneId in [ToontownGlobals.DonaldsDock, ToontownGlobals.OutdoorZone, ToontownGlobals.ToontownCentral, ToontownGlobals.TheBrrrgh, ToontownGlobals.MinniesMelodyland, ToontownGlobals.DaisyGardens, ToontownGlobals.FunnyFarm, ToontownGlobals.GoofySpeedway, ToontownGlobals.DonaldsDreamland]: currAnim = toon.animFSM.getCurrentState().getName() if currAnim != None and currAnim not in ['neutral', 'Happy', 'off', 'Sad', 'TeleportIn', 'jumpAirborne', 'CloseBook', 'run', 'OpenBook', 'TeleportOut', 'TeleportedOut', 'ReadBook', 'walk', 'Sit', 'jumpLand', 'Sleep', 'cringe', 'jumpSquat', 'Died']: sendT(msgHeader, 'invalid animation playing: %s' % currAnim, toon) result = toon else: checks.append(5) if 5 in checks: if base.config.GetBool('tmdcc-cogsuit', 1): if toon.zoneId in [ToontownGlobals.DonaldsDock, ToontownGlobals.OutdoorZone, ToontownGlobals.ToontownCentral, ToontownGlobals.TheBrrrgh, ToontownGlobals.MinniesMelodyland, ToontownGlobals.DaisyGardens, ToontownGlobals.FunnyFarm, ToontownGlobals.GoofySpeedway, ToontownGlobals.DonaldsDreamland]: if toon.isDisguised: sendT(msgHeader, 'toon %s is in a cog suit' % toon.getName(), toon) result = toon else: checks.append(6) if 6 in checks: if base.config.GetBool('tmdcc-colorcheck', 1): torsoPieces = toon.getPieces(('torso', ('arms', 'neck'))) legPieces = toon.getPieces(('legs', ('legs', 'feet'))) headPieces = toon.getPieces(('head', '*head*')) if ([x for x in torsoPieces if x.hasColor() and x.getColor() not in ToonDNA.allowedColors] or [x for x in legPieces if x.hasColor() and x.getColor() not in ToonDNA.allowedColors] or [x for x in headPieces if x.hasColor() and x.getColor() not in ToonDNA.allowedColors]) and toon.cheesyEffect == ToontownGlobals.CENormal: torsoColors = str([not x.hasColor() and 'clear' or x.getColor() in ToonDNA.allowedColors and 'ok' or x.getColor() for x in torsoPieces]) legColors = str([not x.hasColor() and 'clear' or x.getColor() in ToonDNA.allowedColors and 'ok' or x.getColor() for x in legPieces]) headColors = str([not x.hasColor() and 'clear' or x.getColor() in ToonDNA.allowedColors and 'ok' or x.getColor() for x in headPieces]) sendT(msgHeader, 'invalid color...arm: %s leg: %s head: %s' % (torsoColors, legColors, headColors), toon) result = toon else: checks.append(7) endTime = globalClock.getRealTime() return result def startHackObservation(self): taskMgr.doMethodLater(AV_TOUCH_CHECK_DELAY_CL, self.toonPosCheck, self.uniqueName('toonPosCheck')) taskMgr.doMethodLater(config.GetDouble('tmdcc-delay', 5.0), self.tmdcc, self.uniqueName('tmdcc')) if __dev__ and base.config.GetBool('tmdcc-keys', 0): from toontown.testenv import safezoneAutoVisit safezoneAutoVisit.setupKeys() from toontown.testenv import watchDistObj watchDistObj.watchObj.setupKeys() def stopHackObservation(self): taskMgr.remove(self.uniqueName('toonPosCheck')) taskMgr.remove(self.uniqueName('tmdcc')) def disable(self): self.stopHackObservation() self.laffMeter.destroy() del self.laffMeter self.questMap.destroy() self.questMap = None if hasattr(self, 'purchaseButton'): self.purchaseButton.destroy() del self.purchaseButton self.newsButtonMgr.request('Off') base.whiteList.unload() self.book.unload() del self.optionsPage del self.shardPage del self.mapPage del self.invPage del self.questPage del self.suitPage del self.sosPage del self.disguisePage del self.fishPage del self.gardenPage del self.trackPage del self.book if base.wantKarts: if hasattr(self, 'kartPage'): del self.kartPage if base.wantNametags: self.nametag.unmanage(base.marginManager) taskMgr.removeTasksMatching('*ioorrd234*') self.ignoreAll() DistributedToon.DistributedToon.disable(self) return def disableBodyCollisions(self): pass def delete(self): try: self.LocalToon_deleted except: self.LocalToon_deleted = 1 Toon.unloadDialog() QuestParser.clear() DistributedToon.DistributedToon.delete(self) LocalAvatar.LocalAvatar.delete(self) self.bFriendsList.destroy() del self.bFriendsList if self.__pieButton: self.__pieButton.destroy() self.__pieButton = None if self.__piePowerMeter: self.__piePowerMeter.destroy() self.__piePowerMeter = None taskMgr.remove('unlockGardenButtons') taskMgr.remove('lerpFurnitureButton') if self.__furnitureGui: self.__furnitureGui.destroy() del self.__furnitureGui if self.__gardeningGui: self.__gardeningGui.destroy() del self.__gardeningGui if self.__gardeningGuiFake: self.__gardeningGuiFake.destroy() del self.__gardeningGuiFake if self.__clarabelleButton: self.__clarabelleButton.destroy() del self.__clarabelleButton if self.__clarabelleFlash: self.__clarabelleFlash.finish() del self.__clarabelleFlash if self.__catalogNotifyDialog: self.__catalogNotifyDialog.cleanup() del self.__catalogNotifyDialog return def initInterface(self): self.newsButtonMgr = NewsPageButtonManager.NewsPageButtonManager() self.newsButtonMgr.request('Hidden') self.book = ShtikerBook.ShtikerBook('bookDone') self.book.load() self.book.hideButton() self.optionsPage = OptionsPage.OptionsPage() self.optionsPage.load() self.book.addPage(self.optionsPage, pageName=TTLocalizer.OptionsPageTitle) self.shardPage = ShardPage.ShardPage() self.shardPage.load() self.book.addPage(self.shardPage, pageName=TTLocalizer.ShardPageTitle) self.mapPage = MapPage.MapPage() self.mapPage.load() self.book.addPage(self.mapPage, pageName=TTLocalizer.MapPageTitle) self.invPage = InventoryPage.InventoryPage() self.invPage.load() self.book.addPage(self.invPage, pageName=TTLocalizer.InventoryPageTitle) self.questPage = QuestPage.QuestPage() self.questPage.load() self.book.addPage(self.questPage, pageName=TTLocalizer.QuestPageToonTasks) self.trackPage = TrackPage.TrackPage() self.trackPage.load() self.book.addPage(self.trackPage, pageName=TTLocalizer.TrackPageShortTitle) self.suitPage = SuitPage.SuitPage() self.suitPage.load() self.book.addPage(self.suitPage, pageName=TTLocalizer.SuitPageTitle) if base.config.GetBool('want-photo-album', 0): self.photoAlbumPage = PhotoAlbumPage.PhotoAlbumPage() self.photoAlbumPage.load() self.book.addPage(self.photoAlbumPage, pageName=TTLocalizer.PhotoPageTitle) self.fishPage = FishPage.FishPage() self.fishPage.setAvatar(self) self.fishPage.load() self.book.addPage(self.fishPage, pageName=TTLocalizer.FishPageTitle) if base.wantKarts: self.addKartPage() if self.disguisePageFlag: self.loadDisguisePages() if self.sosPageFlag: self.loadSosPages() if self.gardenStarted: self.loadGardenPages() self.addGolfPage() self.addEventsPage() if WantNewsPage: self.addNewsPage() self.book.setPage(self.mapPage, enterPage=False) self.laffMeter = LaffMeter.LaffMeter(self.style, self.hp, self.maxHp) self.laffMeter.setAvatar(self) self.laffMeter.setScale(0.075) if self.style.getAnimal() == 'monkey': self.laffMeter.setPos(-1.18, 0.0, -0.87) else: self.laffMeter.setPos(-1.2, 0.0, -0.87) self.laffMeter.stop() self.questMap = QuestMap.QuestMap(self) self.questMap.stop() if not base.cr.isPaid(): guiButton = loader.loadModel('phase_3/models/gui/quit_button') self.purchaseButton = DirectButton(parent=aspect2d, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=0.9, text=TTLocalizer.OptionsPagePurchase, text_scale=0.05, text_pos=(0, -0.01), textMayChange=0, pos=(0.885, 0, -0.94), sortOrder=100, command=self.__handlePurchase) base.setCellsAvailable([base.bottomCells[4]], 0) self.accept('time-insert', self.__beginTossPie) self.accept('time-insert-up', self.__endTossPie) self.accept('time-delete', self.__beginTossPie) self.accept('time-delete-up', self.__endTossPie) self.accept('pieHit', self.__pieHit) self.accept('interrupt-pie', self.interruptPie) self.accept('InputState-jump', self.__toonMoved) self.accept('InputState-forward', self.__toonMoved) self.accept('InputState-reverse', self.__toonMoved) self.accept('InputState-turnLeft', self.__toonMoved) self.accept('InputState-turnRight', self.__toonMoved) self.accept('InputState-slide', self.__toonMoved) QuestParser.init() return def __handlePurchase(self): self.purchaseButton.hide() if (base.cr.isWebPlayToken() or __dev__): if base.cr.isPaid(): if base.cr.productName in ['DisneyOnline-UK', 'DisneyOnline-AP', 'JP', 'DE', 'BR', 'FR']: paidNoParentPassword = launcher and launcher.getParentPasswordSet() else: paidNoParentPassword = launcher and not launcher.getParentPasswordSet() else: paidNoParentPassword = 0 self.leaveToPayDialog = LeaveToPayDialog.LeaveToPayDialog(paidNoParentPassword, self.purchaseButton.show) self.leaveToPayDialog.show() else: self.notify.error('You should not get here without a PlayToken') if base.wantKarts: def addKartPage(self): if self.hasKart(): if hasattr(self, 'kartPage') and self.kartPage != None: return if not launcher.getPhaseComplete(6): self.acceptOnce('phaseComplete-6', self.addKartPage) return self.kartPage = KartPage.KartPage() self.kartPage.setAvatar(self) self.kartPage.load() self.book.addPage(self.kartPage, pageName=TTLocalizer.KartPageTitle) return def setWantBattles(self, wantBattles): self.wantBattles = wantBattles def loadDisguisePages(self): if self.disguisePage != None: return if not launcher.getPhaseComplete(9): self.acceptOnce('phaseComplete-9', self.loadDisguisePages) return self.disguisePage = DisguisePage.DisguisePage() self.disguisePage.load() self.book.addPage(self.disguisePage, pageName=TTLocalizer.DisguisePageTitle) self.loadSosPages() return def loadSosPages(self): if self.sosPage != None: return self.sosPage = NPCFriendPage.NPCFriendPage() self.sosPage.load() self.book.addPage(self.sosPage, pageName=TTLocalizer.NPCFriendPageTitle) return def loadGardenPages(self): if self.gardenPage != None: return if not launcher.getPhaseComplete(5.5): self.acceptOnce('phaseComplete-5.5', self.loadPhase55Stuff) return self.gardenPage = GardenPage.GardenPage() self.gardenPage.load() self.book.addPage(self.gardenPage, pageName=TTLocalizer.GardenPageTitle) return def loadPhase55Stuff(self): if self.gardenPage == None: self.gardenPage = GardenPage.GardenPage() self.gardenPage.load() self.book.addPage(self.gardenPage, pageName=TTLocalizer.GardenPageTitle) elif not launcher.getPhaseComplete(5.5): self.acceptOnce('phaseComplete-5.5', self.loadPhase55Stuff) self.refreshOnscreenButtons() return def setAsGM(self, state): self.notify.debug('Setting GM State: %s in LocalToon' % state) DistributedToon.DistributedToon.setAsGM(self, state) if self.gmState: if base.config.GetString('gm-nametag-string', '') != '': self.gmNameTagString = base.config.GetString('gm-nametag-string') if base.config.GetString('gm-nametag-color', '') != '': self.gmNameTagColor = base.config.GetString('gm-nametag-color') if base.config.GetInt('gm-nametag-enabled', 0): self.gmNameTagEnabled = 1 self.d_updateGMNameTag() def displayTalkWhisper(self, fromId, avatarName, rawString, mods): sender = base.cr.identifyAvatar(fromId) if sender: chatString, scrubbed = sender.scrubTalk(rawString, mods) else: chatString, scrubbed = self.scrubTalk(rawString, mods) sender = self sfx = self.soundWhisper chatString = avatarName + ': ' + chatString whisper = WhisperPopup(chatString, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) whisper.setClickable(avatarName, fromId) whisper.manage(base.marginManager) base.playSfx(sfx) def displayTalkAccount(self, fromId, senderName, rawString, mods): sender = None playerInfo = None sfx = self.soundWhisper playerInfo = base.cr.playerFriendsManager.playerId2Info.get(fromId, None) if playerInfo == None: return senderAvId = base.cr.playerFriendsManager.findAvIdFromPlayerId(fromId) if not senderName and base.cr.playerFriendsManager.playerId2Info.get(fromId): senderName = base.cr.playerFriendsManager.playerId2Info.get(fromId).playerName senderAvatar = base.cr.identifyAvatar(senderAvId) if sender: chatString, scrubbed = senderAvatar.scrubTalk(rawString, mods) else: chatString, scrubbed = self.scrubTalk(rawString, mods) chatString = senderName + ': ' + chatString whisper = WhisperPopup(chatString, OTPGlobals.getInterfaceFont(), WhisperPopup.WTNormal) if playerInfo != None: whisper.setClickable(senderName, fromId, 1) whisper.manage(base.marginManager) base.playSfx(sfx) return def isLocal(self): return 1 def canChat(self): if not self.cr.allowAnyTypedChat(): return 0 if self.commonChatFlags & (ToontownGlobals.CommonChat | ToontownGlobals.SuperChat): return 1 if base.cr.whiteListChatEnabled: return 1 for friendId, flags in self.friendsList: if flags & ToontownGlobals.FriendChat: return 1 return 0 def startChat(self): if self.tutorialAck: self.notify.info('calling LocalAvatar.startchat') LocalAvatar.LocalAvatar.startChat(self) self.accept('chatUpdateSCToontask', self.b_setSCToontask) self.accept('chatUpdateSCResistance', self.d_reqSCResistance) self.accept('chatUpdateSCSinging', self.b_setSCSinging) self.accept('whisperUpdateSCToontask', self.whisperSCToontaskTo) else: self.notify.info('NOT calling LocalAvatar.startchat, in tutorial') def stopChat(self): LocalAvatar.LocalAvatar.stopChat(self) self.ignore('chatUpdateSCToontask') self.ignore('chatUpdateSCResistance') self.ignore('chatUpdateSCSinging') self.ignore('whisperUpdateSCToontask') def tunnelIn(self, tunnelOrigin): self.b_setTunnelIn(self.tunnelX * 0.8, tunnelOrigin) def tunnelOut(self, tunnelOrigin): self.tunnelX = self.getX(tunnelOrigin) tunnelY = self.getY(tunnelOrigin) self.b_setTunnelOut(self.tunnelX * 0.95, tunnelY, tunnelOrigin) def handleTunnelIn(self, startTime, endX, x, y, z, h): self.notify.debug('LocalToon.handleTunnelIn') tunnelOrigin = render.attachNewNode('tunnelOrigin') tunnelOrigin.setPosHpr(x, y, z, h, 0, 0) self.b_setAnimState('run', self.animMultiplier) self.stopLookAround() self.reparentTo(render) self.runSound() camera.reparentTo(render) camera.setPosHpr(tunnelOrigin, 0, 20, 12, 180, -20, 0) base.transitions.irisIn(0.4) toonTrack = self.getTunnelInToonTrack(endX, tunnelOrigin) def cleanup(self = self, tunnelOrigin = tunnelOrigin): self.stopSound() tunnelOrigin.removeNode() messenger.send('tunnelInMovieDone') self.tunnelTrack = Sequence(toonTrack, Func(cleanup)) self.tunnelTrack.start(globalClock.getFrameTime() - startTime) def handleTunnelOut(self, startTime, startX, startY, x, y, z, h): self.notify.debug('LocalToon.handleTunnelOut') tunnelOrigin = render.attachNewNode('tunnelOrigin') tunnelOrigin.setPosHpr(x, y, z, h, 0, 0) self.b_setAnimState('run', self.animMultiplier) self.runSound() self.stopLookAround() tracks = Parallel() camera.wrtReparentTo(render) startPos = camera.getPos(tunnelOrigin) startHpr = camera.getHpr(tunnelOrigin) camLerpDur = 1.0 reducedCamH = fitDestAngle2Src(startHpr[0], 180) tracks.append(LerpPosHprInterval(camera, camLerpDur, pos=Point3(0, 20, 12), hpr=Point3(reducedCamH, -20, 0), startPos=startPos, startHpr=startHpr, other=tunnelOrigin, blendType='easeInOut', name='tunnelOutLerpCamPos')) toonTrack = self.getTunnelOutToonTrack(startX, startY, tunnelOrigin) tracks.append(toonTrack) irisDur = 0.4 tracks.append(Sequence(Wait(toonTrack.getDuration() - (irisDur + 0.1)), Func(base.transitions.irisOut, irisDur))) def cleanup(self = self, tunnelOrigin = tunnelOrigin): self.stopSound() self.detachNode() tunnelOrigin.removeNode() messenger.send('tunnelOutMovieDone') self.tunnelTrack = Sequence(tracks, Func(cleanup)) self.tunnelTrack.start(globalClock.getFrameTime() - startTime) def getPieBubble(self): if self.__pieBubble == None: bubble = CollisionSphere(0, 0, 0, 1) node = CollisionNode('pieBubble') node.addSolid(bubble) node.setFromCollideMask(ToontownGlobals.PieBitmask | ToontownGlobals.CameraBitmask | ToontownGlobals.FloorBitmask) node.setIntoCollideMask(BitMask32.allOff()) self.__pieBubble = NodePath(node) self.pieHandler = CollisionHandlerEvent() self.pieHandler.addInPattern('pieHit') self.pieHandler.addInPattern('pieHit-%in') return self.__pieBubble def __beginTossPieMouse(self, mouseParam): self.__beginTossPie(globalClock.getFrameTime()) def __endTossPieMouse(self, mouseParam): self.__endTossPie(globalClock.getFrameTime()) def __beginTossPie(self, time): if self.tossPieStart != None: return if not self.allowPies: return if self.numPies == 0: messenger.send('outOfPies') return if self.__pieInHand(): return if getattr(self.controlManager.currentControls, 'isAirborne', 0): return messenger.send('wakeup') self.localPresentPie(time) taskName = self.uniqueName('updatePiePower') taskMgr.add(self.__updatePiePower, taskName) return def __endTossPie(self, time): if self.tossPieStart == None: return taskName = self.uniqueName('updatePiePower') taskMgr.remove(taskName) messenger.send('wakeup') power = self.__getPiePower(time) self.tossPieStart = None self.localTossPie(power) return def localPresentPie(self, time): from . import TTEmote from otp.avatar import Emote self.__stopPresentPie() if self.tossTrack: tossTrack = self.tossTrack self.tossTrack = None tossTrack.finish() self.interruptPie() self.tossPieStart = time self.__pieSequence = self.__pieSequence + 1 & 255 sequence = self.__pieSequence self.__presentingPie = 1 pos = self.getPos() hpr = self.getHpr() timestamp32 = globalClockDelta.getFrameNetworkTime(bits=32) self.sendUpdate('presentPie', [pos[0], pos[1], pos[2], hpr[0] % 360.0, hpr[1], hpr[2], timestamp32]) Emote.globalEmote.disableBody(self) messenger.send('begin-pie') ival = self.getPresentPieInterval(pos[0], pos[1], pos[2], hpr[0], hpr[1], hpr[2]) ival = Sequence(ival, name=self.uniqueName('localPresentPie')) self.tossTrack = ival ival.start() self.makePiePowerMeter() self.__piePowerMeter.show() self.__piePowerMeterSequence = sequence self.__piePowerMeter['value'] = 0 return def __stopPresentPie(self): if self.__presentingPie: from . import TTEmote from otp.avatar import Emote Emote.globalEmote.releaseBody(self) messenger.send('end-pie') self.__presentingPie = 0 taskName = self.uniqueName('updatePiePower') taskMgr.remove(taskName) def __getPiePower(self, time): elapsed = max(time - self.tossPieStart, 0.0) t = elapsed / self.piePowerSpeed t = math.pow(t, self.piePowerExponent) power = int(t * 100) % 200 if power > 100: power = 200 - power return power def __updatePiePower(self, task): if not self.__piePowerMeter: return Task.done self.__piePowerMeter['value'] = self.__getPiePower(globalClock.getFrameTime()) return Task.cont def interruptPie(self): self.cleanupPieInHand() self.__stopPresentPie() if self.__piePowerMeter: self.__piePowerMeter.hide() pie = self.pieTracks.get(self.__pieSequence) if pie and pie.getT() < 14.0 / 24.0: del self.pieTracks[self.__pieSequence] pie.pause() def __pieInHand(self): pie = self.pieTracks.get(self.__pieSequence) return pie and pie.getT() < 15.0 / 24.0 def __toonMoved(self, isSet): if isSet: self.interruptPie() def localTossPie(self, power): if not self.__presentingPie: return pos = self.getPos() hpr = self.getHpr() timestamp32 = globalClockDelta.getFrameNetworkTime(bits=32) sequence = self.__pieSequence if self.tossTrack: tossTrack = self.tossTrack self.tossTrack = None tossTrack.finish() if sequence in self.pieTracks: pieTrack = self.pieTracks[sequence] del self.pieTracks[sequence] pieTrack.finish() if sequence in self.splatTracks: splatTrack = self.splatTracks[sequence] del self.splatTracks[sequence] splatTrack.finish() self.makePiePowerMeter() self.__piePowerMeter['value'] = power self.__piePowerMeter.show() self.__piePowerMeterSequence = sequence pieBubble = self.getPieBubble().instanceTo(NodePath()) def pieFlies(self = self, pos = pos, hpr = hpr, sequence = sequence, power = power, timestamp32 = timestamp32, pieBubble = pieBubble): self.sendUpdate('tossPie', [pos[0], pos[1], pos[2], hpr[0] % 360.0, hpr[1], hpr[2], sequence, power, timestamp32]) if self.numPies != ToontownGlobals.FullPies: self.setNumPies(self.numPies - 1) base.cTrav.addCollider(pieBubble, self.pieHandler) toss, pie, flyPie = self.getTossPieInterval(pos[0], pos[1], pos[2], hpr[0], hpr[1], hpr[2], power, beginFlyIval=Func(pieFlies)) pieBubble.reparentTo(flyPie) flyPie.setTag('pieSequence', str(sequence)) toss = Sequence(toss) self.tossTrack = toss toss.start() pie = Sequence(pie, Func(base.cTrav.removeCollider, pieBubble), Func(self.pieFinishedFlying, sequence)) self.pieTracks[sequence] = pie pie.start() return def pieFinishedFlying(self, sequence): DistributedToon.DistributedToon.pieFinishedFlying(self, sequence) if self.__piePowerMeterSequence == sequence: self.__piePowerMeter.hide() def __finishPieTrack(self, sequence): if sequence in self.pieTracks: pieTrack = self.pieTracks[sequence] del self.pieTracks[sequence] pieTrack.finish() def __pieHit(self, entry): if not entry.hasSurfacePoint() or not entry.hasInto(): return if not entry.getInto().isTangible(): return sequence = int(entry.getFromNodePath().getNetTag('pieSequence')) self.__finishPieTrack(sequence) if sequence in self.splatTracks: splatTrack = self.splatTracks[sequence] del self.splatTracks[sequence] splatTrack.finish() pieCode = 0 pieCodeStr = entry.getIntoNodePath().getNetTag('pieCode') if pieCodeStr: pieCode = int(pieCodeStr) pos = entry.getSurfacePoint(render) timestamp32 = globalClockDelta.getFrameNetworkTime(bits=32) self.sendUpdate('pieSplat', [pos[0], pos[1], pos[2], sequence, pieCode, timestamp32]) splat = self.getPieSplatInterval(pos[0], pos[1], pos[2], pieCode) splat = Sequence(splat, Func(self.pieFinishedSplatting, sequence)) self.splatTracks[sequence] = splat splat.start() messenger.send('pieSplat', [self, pieCode]) messenger.send('localPieSplat', [pieCode, entry]) def beginAllowPies(self): self.allowPies = 1 self.updatePieButton() def endAllowPies(self): self.allowPies = 0 self.updatePieButton() def makePiePowerMeter(self): from direct.gui.DirectGui import DirectWaitBar, DGG if self.__piePowerMeter == None: self.__piePowerMeter = DirectWaitBar(frameSize=(-0.2, 0.2, -0.03, 0.03), relief=DGG.SUNKEN, borderWidth=(0.005, 0.005), barColor=(0.4, 0.6, 1.0, 1), pos=(0, 0.1, 0.8)) self.__piePowerMeter.hide() return def updatePieButton(self): from toontown.toonbase import ToontownBattleGlobals from direct.gui.DirectGui import DirectButton, DGG wantButton = 0 if self.allowPies and self.numPies > 0: wantButton = 1 if not launcher.getPhaseComplete(5): wantButton = 0 haveButton = self.__pieButton != None if not haveButton and not wantButton: return if haveButton and not wantButton: self.__pieButton.destroy() self.__pieButton = None self.__pieButtonType = None self.__pieButtonCount = None return if self.__pieButtonType != self.pieType: if self.__pieButton: self.__pieButton.destroy() self.__pieButton = None if self.__pieButton == None: inv = self.inventory if self.pieType >= len(inv.invModels[ToontownBattleGlobals.THROW_TRACK]): gui = loader.loadModel('phase_3.5/models/gui/stickerbook_gui') pieGui = gui.find('**/summons') pieScale = 0.1 else: gui = None pieGui = (inv.invModels[ToontownBattleGlobals.THROW_TRACK][self.pieType],) pieScale = 0.85 self.__pieButton = DirectButton(image=(inv.upButton, inv.downButton, inv.rolloverButton), geom=pieGui, text='50', text_scale=0.04, text_align=TextNode.ARight, geom_scale=pieScale, geom_pos=(-0.01, 0, 0), text_fg=Vec4(1, 1, 1, 1), text_pos=(0.07, -0.04), relief=None, image_color=(0, 0.6, 1, 1), pos=(0, 0.1, 0.9)) self.__pieButton.bind(DGG.B1PRESS, self.__beginTossPieMouse) self.__pieButton.bind(DGG.B1RELEASE, self.__endTossPieMouse) self.__pieButtonType = self.pieType self.__pieButtonCount = None if gui: del gui if self.__pieButtonCount != self.numPies: if self.numPies == ToontownGlobals.FullPies: self.__pieButton['text'] = '' else: self.__pieButton['text'] = str(self.numPies) self.__pieButtonCount = self.numPies return def displayWhisper(self, fromId, chatString, whisperType): sender = None sfx = self.soundWhisper if fromId == TTLocalizer.Clarabelle: chatString = TTLocalizer.Clarabelle + ': ' + chatString sfx = self.soundPhoneRing elif fromId != 0: sender = base.cr.identifyAvatar(fromId) if whisperType == WhisperPopup.WTNormal or whisperType == WhisperPopup.WTQuickTalker: if sender == None: return chatString = sender.getName() + ': ' + chatString elif whisperType == WhisperPopup.WTSystem: sfx = self.soundSystemMessage whisper = WhisperPopup(chatString, OTPGlobals.getInterfaceFont(), whisperType) if sender != None: whisper.setClickable(sender.getName(), fromId) whisper.manage(base.marginManager) base.playSfx(sfx) return def displaySystemClickableWhisper(self, fromId, chatString, whisperType): sender = None sfx = self.soundWhisper if fromId == TTLocalizer.Clarabelle: chatString = TTLocalizer.Clarabelle + ': ' + chatString sfx = self.soundPhoneRing elif fromId != 0: sender = base.cr.identifyAvatar(fromId) if whisperType == WhisperPopup.WTNormal or whisperType == WhisperPopup.WTQuickTalker: if sender == None: return chatString = sender.getName() + ': ' + chatString elif whisperType == WhisperPopup.WTSystem: sfx = self.soundSystemMessage whisper = WhisperPopup(chatString, OTPGlobals.getInterfaceFont(), whisperType) whisper.setClickable('', fromId) whisper.manage(base.marginManager) base.playSfx(sfx) return def clickedWhisper(self, doId, isPlayer = None): if doId > 0: LocalAvatar.LocalAvatar.clickedWhisper(self, doId, isPlayer) else: foundCanStart = False for partyInfo in self.hostedParties: if partyInfo.status == PartyGlobals.PartyStatus.CanStart: foundCanStart = True break if base.cr and base.cr.playGame and base.cr.playGame.getPlace() and base.cr.playGame.getPlace().fsm: fsm = base.cr.playGame.getPlace().fsm curState = fsm.getCurrentState().getName() if curState == 'walk': if hasattr(self, 'eventsPage'): desiredMode = -1 if doId == -1: desiredMode = EventsPage.EventsPage_Invited elif foundCanStart: desiredMode = EventsPage.EventsPage_Host if desiredMode >= 0: self.book.setPage(self.eventsPage) self.eventsPage.setMode(desiredMode) fsm.request('stickerBook') def loadFurnitureGui(self): if self.__furnitureGui: return guiModels = loader.loadModel('phase_5.5/models/gui/house_design_gui') self.__furnitureGui = DirectFrame(relief=None, pos=(-1.19, 0.0, 0.33), scale=0.04, image=guiModels.find('**/attic')) DirectLabel(parent=self.__furnitureGui, relief=None, image=guiModels.find('**/rooftile')) bMoveStartUp = guiModels.find('**/bu_attic/bu_attic_up') bMoveStartDown = guiModels.find('**/bu_attic/bu_attic_down') bMoveStartRollover = guiModels.find('**/bu_attic/bu_attic_rollover') DirectButton(parent=self.__furnitureGui, relief=None, image=[bMoveStartUp, bMoveStartDown, bMoveStartRollover, bMoveStartUp], text=['', TTLocalizer.HDMoveFurnitureButton, TTLocalizer.HDMoveFurnitureButton], text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_font=ToontownGlobals.getInterfaceFont(), pos=(-0.3, 0, 9.4), command=self.__startMoveFurniture) self.__furnitureGui.hide() guiModels.removeNode() return def showFurnitureGui(self): self.loadFurnitureGui() self.__furnitureGui.show() def hideFurnitureGui(self): if self.__furnitureGui: self.__furnitureGui.hide() def clarabelleNewsPageCollision(self, show = True): if self.__clarabelleButton == None: return claraXPos = ClaraBaseXPos notifyXPos = CatalogNotifyDialog.CatalogNotifyBaseXPos if show: claraXPos += AdjustmentForNewsButton notifyXPos += AdjustmentForNewsButton newPos = (claraXPos - 0.1, 1.0, 0.45) self.__clarabelleButton.setPos(newPos) if self.__catalogNotifyDialog == None or self.__catalogNotifyDialog.frame == None: return notifyPos = self.__catalogNotifyDialog.frame.getPos() notifyPos[0] = notifyXPos self.__catalogNotifyDialog.frame.setPos(notifyPos) return def loadClarabelleGui(self): if self.__clarabelleButton: return guiItems = loader.loadModel('phase_5.5/models/gui/catalog_gui') circle = guiItems.find('**/cover/blue_circle') icon = guiItems.find('**/cover/clarabelle') icon.reparentTo(circle) rgba = VBase4(0.71589, 0.784547, 0.974, 1.0) white = VBase4(1.0, 1.0, 1.0, 1.0) icon.setColor(white) claraXPos = ClaraBaseXPos newScale = oldScale = 0.5 newPos = (claraXPos, 1.0, 0.37) if WantNewsPage: claraXPos += AdjustmentForNewsButton oldPos = ((claraXPos, 1.0, 0.37),) newScale = oldScale * ToontownGlobals.NewsPageScaleAdjust newPos = (claraXPos - 0.1, 1.0, 0.45) self.__clarabelleButton = DirectButton(relief=None, image=circle, text='', text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_scale=0.1, text_pos=(-1.06, 1.06), text_font=ToontownGlobals.getInterfaceFont(), pos=newPos, scale=newScale, command=self.__handleClarabelleButton) self.__clarabelleButton.reparentTo(aspect2d, DGG.BACKGROUND_SORT_INDEX - 1) button = self.__clarabelleButton.stateNodePath[0] self.__clarabelleFlash = Sequence(LerpColorInterval(button, 2, white, blendType='easeInOut'), LerpColorInterval(button, 2, rgba, blendType='easeInOut')) self.__clarabelleFlash.loop() self.__clarabelleFlash.pause() return def showClarabelleGui(self, mailboxItems): self.loadClarabelleGui() if mailboxItems: self.__clarabelleButton['text'] = ['', TTLocalizer.CatalogNewDeliveryButton, TTLocalizer.CatalogNewDeliveryButton] else: self.__clarabelleButton['text'] = ['', TTLocalizer.CatalogNewCatalogButton, TTLocalizer.CatalogNewCatalogButton] if not self.mailboxNotify and not self.awardNotify and self.catalogNotify == ToontownGlobals.OldItems and (self.simpleMailNotify != ToontownGlobals.NoItems or self.inviteMailNotify != ToontownGlobals.NoItems): self.__clarabelleButton['text'] = ['', TTLocalizer.MailNewMailButton, TTLocalizer.MailNewMailButton] if self.newsButtonMgr.isNewIssueButtonShown(): self.clarabelleNewsPageCollision(True) self.__clarabelleButton.show() self.__clarabelleFlash.resume() def hideClarabelleGui(self): if self.__clarabelleButton: self.__clarabelleButton.hide() self.__clarabelleFlash.pause() def __handleClarabelleButton(self): self.stopMoveFurniture() place = base.cr.playGame.getPlace() if place == None: self.notify.warning('Tried to go home, but place is None.') return if self.__catalogNotifyDialog: self.__catalogNotifyDialog.cleanup() self.__catalogNotifyDialog = None if base.config.GetBool('want-qa-regression', 0): self.notify.info('QA-REGRESSION: VISITESTATE: Visit estate') place.goHomeNow(self.lastHood) return def __startMoveFurniture(self): self.oldPos = self.getPos() if base.config.GetBool('want-qa-regression', 0): self.notify.info('QA-REGRESSION: ESTATE: Furniture Placement') if self.cr.furnitureManager != None: self.cr.furnitureManager.d_suggestDirector(self.doId) elif self.furnitureManager != None: self.furnitureManager.d_suggestDirector(self.doId) return def stopMoveFurniture(self): if self.oldPos: self.setPos(self.oldPos) if self.furnitureManager != None: self.furnitureManager.d_suggestDirector(0) return def setFurnitureDirector(self, avId, furnitureManager): if avId == 0: if self.furnitureManager == furnitureManager: messenger.send('exitFurnitureMode', [furnitureManager]) self.furnitureManager = None self.furnitureDirector = None elif avId != self.doId: if self.furnitureManager == None or self.furnitureDirector != avId: self.furnitureManager = furnitureManager self.furnitureDirector = avId messenger.send('enterFurnitureMode', [furnitureManager, 0]) else: if self.furnitureManager != None: messenger.send('exitFurnitureMode', [self.furnitureManager]) self.furnitureManager = None self.furnitureManager = furnitureManager self.furnitureDirector = avId messenger.send('enterFurnitureMode', [furnitureManager, 1]) self.refreshOnscreenButtons() return def getAvPosStr(self): pos = self.getPos() hpr = self.getHpr() serverVersion = base.cr.getServerVersion() districtName = base.cr.getShardName(base.localAvatar.defaultShard) if hasattr(base.cr.playGame.hood, 'loader') and hasattr(base.cr.playGame.hood.loader, 'place') and base.cr.playGame.getPlace() != None: zoneId = base.cr.playGame.getPlace().getZoneId() else: zoneId = '?' strPosCoordText = 'X: %.3f' % pos[0] + ', Y: %.3f' % pos[1] + '\nZ: %.3f' % pos[2] + ', H: %.3f' % hpr[0] + '\nZone: %s' % str(zoneId) + ', Ver: %s, ' % serverVersion + 'District: %s' % districtName return strPosCoordText self.refreshOnscreenButtons() return def thinkPos(self): pos = self.getPos() hpr = self.getHpr() serverVersion = base.cr.getServerVersion() districtName = base.cr.getShardName(base.localAvatar.defaultShard) if hasattr(base.cr.playGame.hood, 'loader') and hasattr(base.cr.playGame.hood.loader, 'place') and base.cr.playGame.getPlace() != None: zoneId = base.cr.playGame.getPlace().getZoneId() else: zoneId = '?' strPos = '(%.3f' % pos[0] + '\n %.3f' % pos[1] + '\n %.3f)' % pos[2] + '\nH: %.3f' % hpr[0] + '\nZone: %s' % str(zoneId) + ',\nVer: %s, ' % serverVersion + '\nDistrict: %s' % districtName print('Current position=', strPos.replace('\n', ', ')) self.setChatAbsolute(strPos, CFThought | CFTimeout) return def __placeMarker(self): pos = self.getPos() hpr = self.getHpr() chest = loader.loadModel('phase_4/models/props/coffin') chest.reparentTo(render) chest.setColor(1, 0, 0, 1) chest.setPosHpr(pos, hpr) chest.setScale(0.5) def setFriendsListButtonActive(self, active): self.friendsListButtonActive = active self.refreshOnscreenButtons() def obscureFriendsListButton(self, increment): self.friendsListButtonObscured += increment self.refreshOnscreenButtons() def obscureMoveFurnitureButton(self, increment): self.moveFurnitureButtonObscured += increment self.refreshOnscreenButtons() def obscureClarabelleButton(self, increment): self.clarabelleButtonObscured += increment self.refreshOnscreenButtons() def refreshOnscreenButtons(self): self.bFriendsList.hide() self.hideFurnitureGui() self.hideClarabelleGui() clarabelleHidden = 1 self.ignore(ToontownGlobals.FriendsListHotkey) if self.friendsListButtonActive and self.friendsListButtonObscured <= 0: self.bFriendsList.show() self.accept(ToontownGlobals.FriendsListHotkey, self.sendFriendsListEvent) if self.clarabelleButtonObscured <= 0 and self.isTeleportAllowed(): if self.catalogNotify == ToontownGlobals.NewItems or self.mailboxNotify == ToontownGlobals.NewItems or self.simpleMailNotify == ToontownGlobals.NewItems or self.inviteMailNotify == ToontownGlobals.NewItems or self.awardNotify == ToontownGlobals.NewItems: showClarabelle = not launcher or launcher.getPhaseComplete(5.5) for quest in self.quests: if quest[0] in Quests.PreClarabelleQuestIds and self.mailboxNotify != ToontownGlobals.NewItems and self.awardNotify != ToontownGlobals.NewItems: showClarabelle = 0 if base.cr.playGame.getPlace().getState() == 'stickerBook': showClarabelle = 0 if showClarabelle: newItemsInMailbox = self.mailboxNotify == ToontownGlobals.NewItems or self.awardNotify == ToontownGlobals.NewItems self.showClarabelleGui(newItemsInMailbox) clarabelleHidden = 0 if clarabelleHidden: if self.__catalogNotifyDialog: self.__catalogNotifyDialog.cleanup() self.__catalogNotifyDialog = None else: self.newCatalogNotify() if self.moveFurnitureButtonObscured <= 0: if self.furnitureManager != None and self.furnitureDirector == self.doId: self.loadFurnitureGui() self.__furnitureGui.setPos(-1.16, 0, -0.03) self.__furnitureGui.setScale(0.06) elif self.cr.furnitureManager != None: self.showFurnitureGui() taskMgr.remove('lerpFurnitureButton') self.__furnitureGui.lerpPosHprScale(pos=Point3(-1.19, 0.0, 0.33), hpr=Vec3(0.0, 0.0, 0.0), scale=Vec3(0.04, 0.04, 0.04), time=1.0, blendType='easeInOut', task='lerpFurnitureButton') if hasattr(self, 'inEstate') and self.inEstate: self.loadGardeningGui() self.hideGardeningGui() else: self.hideGardeningGui() return def setGhostMode(self, flag): if flag == 2: self.seeGhosts = 1 DistributedToon.DistributedToon.setGhostMode(self, flag) def newCatalogNotify(self): if not self.gotCatalogNotify: return hasPhase = not launcher or launcher.getPhaseComplete(5.5) if not hasPhase: return if not self.friendsListButtonActive or self.friendsListButtonObscured > 0: return self.gotCatalogNotify = 0 currentWeek = self.catalogScheduleCurrentWeek - 1 if currentWeek < 57: seriesNumber = currentWeek / ToontownGlobals.CatalogNumWeeksPerSeries + 1 weekNumber = currentWeek % ToontownGlobals.CatalogNumWeeksPerSeries + 1 elif currentWeek < 65: seriesNumber = 6 weekNumber = currentWeek - 56 else: seriesNumber = currentWeek / ToontownGlobals.CatalogNumWeeksPerSeries + 2 weekNumber = currentWeek % ToontownGlobals.CatalogNumWeeksPerSeries + 1 message = None if self.mailboxNotify == ToontownGlobals.NoItems: if self.catalogNotify == ToontownGlobals.NewItems: if self.catalogScheduleCurrentWeek == 1: message = (TTLocalizer.CatalogNotifyFirstCatalog, TTLocalizer.CatalogNotifyInstructions) else: message = (TTLocalizer.CatalogNotifyNewCatalog % weekNumber,) elif self.mailboxNotify == ToontownGlobals.NewItems: if self.catalogNotify == ToontownGlobals.NewItems: message = (TTLocalizer.CatalogNotifyNewCatalogNewDelivery % weekNumber,) else: message = (TTLocalizer.CatalogNotifyNewDelivery,) elif self.mailboxNotify == ToontownGlobals.OldItems: if self.catalogNotify == ToontownGlobals.NewItems: message = (TTLocalizer.CatalogNotifyNewCatalogOldDelivery % weekNumber,) else: message = (TTLocalizer.CatalogNotifyOldDelivery,) if self.awardNotify == ToontownGlobals.NoItems: pass elif self.awardNotify == ToontownGlobals.NewItems: oldStr = '' if message: oldStr = message[0] + ' ' oldStr += TTLocalizer.AwardNotifyNewItems message = (oldStr,) elif self.awardNotify == ToontownGlobals.OldItems: oldStr = '' if message: oldStr = message[0] + ' ' oldStr += TTLocalizer.AwardNotifyOldItems message = (oldStr,) if self.simpleMailNotify == ToontownGlobals.NewItems or self.inviteMailNotify == ToontownGlobals.NewItems: oldStr = '' if message: oldStr = message[0] + ' ' oldStr += TTLocalizer.MailNotifyNewItems message = (oldStr,) if message == None: return if self.__catalogNotifyDialog: self.__catalogNotifyDialog.cleanup() self.__catalogNotifyDialog = CatalogNotifyDialog.CatalogNotifyDialog(message) base.playSfx(self.soundPhoneRing) return def allowHardLand(self): retval = LocalAvatar.LocalAvatar.allowHardLand(self) return retval and not self.isDisguised def setShovelGuiLevel(self, level = 0): pass def setWateringCanGuiLevel(self, level = 0): pass def loadGardeningGui(self): if self.__gardeningGui: return gardenGuiCard = loader.loadModel('phase_5.5/models/gui/planting_gui') self.__gardeningGui = DirectFrame(relief=None, geom=gardenGuiCard, geom_color=GlobalDialogColor, geom_scale=(0.17, 1.0, 0.3), pos=(-1.2, 0, 0.5), scale=1.0) self.__gardeningGui.setName('gardeningFrame') self.__gardeningGuiFake = DirectFrame(relief=None, geom=None, geom_color=GlobalDialogColor, geom_scale=(0.17, 1.0, 0.3), pos=(-1.2, 0, 0.5), scale=1.0) self.__gardeningGuiFake.setName('gardeningFrameFake') iconScale = 1 iconColorWhite = Vec4(1.0, 1.0, 1.0, 1.0) iconColorGrey = Vec4(0.7, 0.7, 0.7, 1.0) iconColorBrown = Vec4(0.7, 0.4, 0.3, 1.0) iconColorBlue = Vec4(0.2, 0.3, 1.0, 1.0) shovelCardP = loader.loadModel('phase_5.5/models/gui/planting_but_shovel_P') shovelCardY = loader.loadModel('phase_5.5/models/gui/planting_but_shovel_Y') wateringCanCardP = loader.loadModel('phase_5.5/models/gui/planting_but_can_P') wateringCanCardY = loader.loadModel('phase_5.5/models/gui/planting_but_can_Y') backCard = loader.loadModel('phase_5.5/models/gui/planting_gui') iconImage = None iconModels = loader.loadModel('phase_3.5/models/gui/sos_textures') iconGeom = iconModels.find('**/fish') buttonText = TTLocalizer.GardeningPlant self.shovelText = ('', '', buttonText, '') self.__shovelButtonFake = DirectLabel(parent=self.__gardeningGuiFake, relief=None, text=self.shovelText, text_align=TextNode.ALeft, text_pos=(0.0, -0.0), text_scale=0.07, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), image_scale=(0.18, 1.0, 0.36), geom=None, geom_scale=iconScale, geom_color=iconColorWhite, pos=(0.15, 0, 0.2), scale=0.775) self.shovelButtonFake = self.__shovelButtonFake self.shovelText = ('', '', buttonText, '') self.__shovelButton = DirectButton(parent=self.__gardeningGui, relief=None, text=self.shovelText, text_align=TextNode.ACenter, text_pos=(0.0, -0.0), text_scale=0.1, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), image=(shovelCardP, shovelCardY, shovelCardY, shovelCardY), image_scale=(0.18, 1.0, 0.36), geom=None, geom_scale=iconScale, geom_color=iconColorWhite, pos=(0, 0, 0.2), scale=0.775, command=self.__shovelButtonClicked) self.shovelButton = self.__shovelButton iconGeom = iconModels.find('**/teleportIcon') buttonText = TTLocalizer.GardeningWater self.waterText = (buttonText, buttonText, buttonText, '') self.__wateringCanButtonFake = DirectLabel(parent=self.__gardeningGuiFake, relief=None, text=self.waterText, text_align=TextNode.ALeft, text_pos=(0.0, -0.0), text_scale=0.07, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), image_scale=(0.18, 1.0, 0.36), geom=None, geom_scale=iconScale, geom_color=iconColorWhite, pos=(0.15, 0, 0.01), scale=0.775) self.wateringCanButtonFake = self.__wateringCanButtonFake self.__wateringCanButton = DirectButton(parent=self.__gardeningGui, relief=None, text=self.waterText, text_align=TextNode.ACenter, text_pos=(0.0, -0.0), text_scale=0.1, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), image=(wateringCanCardP, wateringCanCardY, wateringCanCardY, wateringCanCardY), image_scale=(0.18, 1.0, 0.36), geom=None, geom_scale=iconScale, geom_color=iconColorWhite, pos=(0, 0, 0.01), scale=0.775, command=self.__wateringCanButtonClicked) self.wateringCanButton = self.__wateringCanButton self.basketText = '%s / %s' % (self.numFlowers, self.maxFlowerBasket) self.basketButton = DirectLabel(parent=self.__gardeningGui, relief=None, text=self.basketText, text_align=TextNode.ALeft, text_pos=(0.82, -1.4), text_scale=0.2, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), image=None, image_scale=iconScale, geom=None, geom_scale=iconScale, geom_color=iconColorWhite, pos=(-0.34, 0, 0.16), scale=0.3, textMayChange=1) if hasattr(self, 'shovel'): self.setShovelGuiLevel(self.shovel) if hasattr(self, 'wateringCan'): self.setWateringCanGuiLevel(self.wateringCan) self.__shovelButton.hide() self.__wateringCanButton.hide() self.__shovelButtonFake.hide() self.__wateringCanButtonFake.hide() return def changeButtonText(self, button, text): button['text'] = text def resetWaterText(self): self.wateringCanButton['text'] = self.waterText def resetShovelText(self): self.shovelButton['text'] = self.holdShovelText def showGardeningGui(self): self.loadGardeningGui() self.__gardeningGui.show() base.setCellsAvailable([base.leftCells[2]], 0) def hideGardeningGui(self): if self.__gardeningGui: self.__gardeningGui.hide() base.setCellsAvailable([base.leftCells[2]], 1) def showShovelButton(self, add = 0): if add: self.shovelButtonActiveCount += add else: self.showingShovel = 1 self.notify.debug('showing shovel %s' % self.shovelButtonActiveCount) self.__gardeningGui.show() self.__shovelButton.show() def hideShovelButton(self, deduct = 0): self.shovelButtonActiveCount -= deduct if deduct == 0: self.showingShovel = 0 if self.shovelButtonActiveCount < 1: self.shovelButtonActiveCount = 0 if self.showingShovel == 0: self.__shovelButton.hide() self.handleAllGardeningButtonsHidden() self.notify.debug('hiding shovel %s' % self.shovelButtonActiveCount) def showWateringCanButton(self, add = 0): if add: self.wateringCanButtonActiveCount += add else: self.showingWateringCan = 1 self.__gardeningGui.show() self.__wateringCanButton.show() self.basketButton.show() def hideWateringCanButton(self, deduct = 0): self.wateringCanButtonActiveCount -= deduct if deduct == 0: self.showingWateringCan = 0 if self.wateringCanButtonActiveCount < 1: wateringCanButtonActiveCount = 0 if self.showingWateringCan == 0: self.__wateringCanButton.hide() self.handleAllGardeningButtonsHidden() def showWateringCanButtonFake(self, add = 0): self.__wateringCanButtonFake.show() def hideWateringCanButtonFake(self, deduct = 0): self.__wateringCanButtonFake.hide() def showShovelButtonFake(self, add = 0): self.__shovelButtonFake.show() def hideShovelButtonFake(self, deduct = 0): self.__shovelButtonFake.hide() def levelWater(self, change = 1): if change < 0: return self.showWateringCanButtonFake(1) if change < 1: changeString = TTLocalizer.GardeningNoSkill else: changeString = '+%s %s' % (change, TTLocalizer.GardeningWaterSkill) self.waterTrack = Sequence(Wait(0.0), Func(self.changeButtonText, self.wateringCanButtonFake, changeString), SoundInterval(globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node=self), Wait(1.0), Func(self.hideWateringCanButtonFake, 1)) self.waterTrack.start() def levelShovel(self, change = 1): if change < 1: return self.showShovelButtonFake(1) if change < 1: changeString = TTLocalizer.GardeningNoSkill else: changeString = '+%s %s' % (change, TTLocalizer.GardeningShovelSkill) plant = base.cr.doId2do.get(self.shovelRelatedDoId) if plant: self.holdShovelText = plant.getShovelAction() self.shovelTrack = Sequence(Wait(0.0), Func(self.changeButtonText, self.shovelButtonFake, changeString), SoundInterval(globalBattleSoundCache.getSound('GUI_balloon_popup.mp3'), node=self), Wait(1.0), Func(self.hideShovelButtonFake, 1)) self.shovelTrack.start() def setGuiConflict(self, con): self.guiConflict = con def getGuiConflict(self, con): return self.guiConflict def verboseState(self): self.lastPlaceState = 'None' taskMgr.add(self.__expressState, 'expressState', extraArgs=[]) def __expressState(self, task = None): place = base.cr.playGame.getPlace() if place: state = place.fsm.getCurrentState() if state.getName() != self.lastPlaceState: print('Place State Change From %s to %s' % (self.lastPlaceState, state.getName())) self.lastPlaceState = state.getName() return Task.cont def addShovelRelatedDoId(self, doId): if hasattr(base.cr.playGame.getPlace(), 'detectedGardenPlotDone'): place = base.cr.playGame.getPlace() state = place.fsm.getCurrentState() if state.getName() == 'stopped': return self.touchingPlantList.append(doId) self.autoSetActivePlot() def removeShovelRelatedDoId(self, doId): if doId in self.touchingPlantList: self.touchingPlantList.remove(doId) self.autoSetActivePlot() def autoSetActivePlot(self): if self.guiConflict: return if len(self.touchingPlantList) > 0: minDist = 10000 minDistPlot = 0 for plot in self.touchingPlantList: plant = base.cr.doId2do.get(plot) if plant: if self.getDistance(plant) < minDist: minDist = self.getDistance(plant) minDistPlot = plot else: self.touchingPlantList.remove(plot) if len(self.touchingPlantList) == 0: self.setActivePlot(None) else: self.setActivePlot(minDistPlot) else: self.setActivePlot(None) return def setActivePlot(self, doId): if not self.gardenStarted: return self.shovelRelatedDoId = doId plant = base.cr.doId2do.get(doId) if plant: self.startStareAt(plant, Point3(0, 0, 1)) self.__shovelButton['state'] = DGG.NORMAL if not plant.canBePicked(): self.hideShovelButton() else: self.showShovelButton() self.setShovelAbility(TTLocalizer.GardeningPlant) if plant.getShovelAction(): self.setShovelAbility(plant.getShovelAction()) if plant.getShovelAction() == TTLocalizer.GardeningPick: if not plant.unlockPick(): self.__shovelButton['state'] = DGG.DISABLED self.setShovelAbility(TTLocalizer.GardeningFull) self.notify.debug('self.shovelRelatedDoId = %d' % self.shovelRelatedDoId) if plant.getShovelCommand(): self.extraShovelCommand = plant.getShovelCommand() self.__shovelButton['command'] = self.__shovelButtonClicked if plant.canBeWatered(): self.showWateringCanButton() else: self.hideWateringCanButton() else: self.stopStareAt() self.shovelRelatedDoId = 0 if self.__shovelButton: self.__shovelButton['command'] = None self.hideShovelButton() self.hideWateringCanButton() self.handleAllGardeningButtonsHidden() if not self.inGardenAction: if hasattr(base.cr.playGame.getPlace(), 'detectedGardenPlotDone'): place = base.cr.playGame.getPlace() if place: place.detectedGardenPlotDone() return def setPlantToWater(self, plantId): import pdb pdb.set_trace() if self.plantToWater == None: self.plantToWater = plantId self.notify.debug('setting plant to water %s' % plantId) return def clearPlantToWater(self, plantId): if not hasattr(self, 'secondaryPlant'): self.secondaryWaterPlant = None if self.plantToWater == plantId: self.plantToWater = None self.hideWateringCanButton() return def hasPlant(self): if self.plantToWater != None: return 1 else: return 0 return def handleAllGardeningButtonsHidden(self): somethingVisible = False if not self.__shovelButton.isHidden(): somethingVisible = True if not self.__wateringCanButton.isHidden(): somethingVisible = True if not somethingVisible: self.hideGardeningGui() def setShovelAbility(self, ability): self.shovelAbility = ability if self.__shovelButton: self.__shovelButton['text'] = ability def setFlowerBasket(self, speciesList, varietyList): DistributedToon.DistributedToon.setFlowerBasket(self, speciesList, varietyList) self.numFlowers = len(self.flowerBasket.flowerList) self.maxFlowerBasket if hasattr(self, 'basketButton'): self.basketText = '%s / %s' % (self.numFlowers, self.maxFlowerBasket) self.basketButton['text'] = self.basketText def setShovelSkill(self, skillLevel): if hasattr(self, 'shovelSkill') and hasattr(self, 'shovelButton'): if self.shovelSkill != None: self.levelShovel(skillLevel - self.shovelSkill) oldShovelSkill = self.shovelSkill DistributedToon.DistributedToon.setShovelSkill(self, skillLevel) if hasattr(self, 'shovel'): oldShovelPower = GardenGlobals.getShovelPower(self.shovel, oldShovelSkill) newShovelPower = GardenGlobals.getShovelPower(self.shovel, self.shovelSkill) almostMaxedSkill = GardenGlobals.ShovelAttributes[GardenGlobals.MAX_SHOVELS - 1]['skillPts'] - 2 if skillLevel >= GardenGlobals.ShovelAttributes[self.shovel]['skillPts']: self.promoteShovel() elif oldShovelSkill and oldShovelPower < newShovelPower: self.promoteShovelSkill(self.shovel, self.shovelSkill) elif oldShovelSkill == almostMaxedSkill and newShovelPower == GardenGlobals.getNumberOfShovelBoxes(): self.promoteShovelSkill(self.shovel, self.shovelSkill) return def setWateringCanSkill(self, skillLevel): skillDelta = skillLevel - self.wateringCanSkill if skillDelta or 1: if hasattr(self, 'wateringCanSkill') and hasattr(self, 'wateringCanButton'): if self.wateringCanSkill != None: self.levelWater(skillDelta) DistributedToon.DistributedToon.setWateringCanSkill(self, skillLevel) if hasattr(self, 'wateringCan'): if skillLevel >= GardenGlobals.WateringCanAttributes[self.wateringCan]['skillPts']: self.promoteWateringCan() return def unlockGardeningButtons(self, task = None): if hasattr(self, '_LocalToon__shovelButton'): try: self.__shovelButton['state'] = DGG.NORMAL except TypeError: self.notify.warning('Could not unlock the shovel button- Type Error') if hasattr(self, '_LocalToon__wateringCanButton'): try: self.__wateringCanButton['state'] = DGG.NORMAL except TypeError: self.notify.warning('Could not unlock the watering can button - Type Error') taskMgr.remove('unlockGardenButtons') return None def lockGardeningButtons(self, task = None): if hasattr(self, '_LocalToon__shovelButton'): try: self.__shovelButton['state'] = DGG.DISABLED except TypeError: self.notify.warning('Could not lock the shovel button- Type Error') if hasattr(self, '_LocalToon__wateringCanButton'): try: self.__wateringCanButton['state'] = DGG.DISABLED except TypeError: self.notify.warning('Could not lock the watering can button - Type Error') self.accept('endPlantInteraction', self.__handleEndPlantInteraction) return None def reactivateShovel(self, task = None): if hasattr(self, '_LocalToon__shovelButton'): self.__shovelButton['state'] = DGG.NORMAL taskMgr.remove('reactShovel') return None def reactivateWater(self, task = None): if hasattr(self, '_LocalToon__wateringCanButton'): self.__wateringCanButton['state'] = DGG.NORMAL taskMgr.remove('reactWater') return None def handleEndPlantInteraction(self, object = None, replacement = 0): if not replacement: self.setInGardenAction(None, object) self.autoSetActivePlot() return def __handleEndPlantInteraction(self, task = None): self.setInGardenAction(None) self.autoSetActivePlot() return def promoteShovelSkill(self, shovelLevel, shovelSkill): shovelName = GardenGlobals.ShovelAttributes[shovelLevel]['name'] shovelBeans = GardenGlobals.getShovelPower(shovelLevel, shovelSkill) oldShovelBeans = GardenGlobals.getShovelPower(shovelLevel, shovelSkill - 1) doPartyBall = False message = TTLocalizer.GardenShovelSkillLevelUp % {'shovel': shovelName, 'oldbeans': oldShovelBeans, 'newbeans': shovelBeans} if shovelBeans == GardenGlobals.getNumberOfShovelBoxes(): if shovelSkill == GardenGlobals.ShovelAttributes[shovelLevel]['skillPts'] - 1: doPartyBall = True message = TTLocalizer.GardenShovelSkillMaxed % {'shovel': shovelName, 'oldbeans': oldShovelBeans, 'newbeans': shovelBeans} messagePos = Vec2(0, 0.2) messageScale = 0.07 image = loader.loadModel('phase_5.5/models/gui/planting_but_shovel_P') imagePos = Vec3(0, 0, -0.13) imageScale = Vec3(0.28, 0, 0.56) if doPartyBall: go = Fanfare.makeFanfareWithMessageImage(0, base.localAvatar, 1, message, Vec2(0, 0.2), 0.08, image, Vec3(0, 0, -0.1), Vec3(0.35, 0, 0.7), wordwrap=23) Sequence(go[0], Func(go[1].show), LerpColorScaleInterval(go[1], duration=0.5, startColorScale=Vec4(1, 1, 1, 0), colorScale=Vec4(1, 1, 1, 1)), Wait(10), LerpColorScaleInterval(go[1], duration=0.5, startColorScale=Vec4(1, 1, 1, 1), colorScale=Vec4(1, 1, 1, 0)), Func(go[1].remove)).start() else: go = Fanfare.makePanel(base.localAvatar, 1) Fanfare.makeMessageBox(go, message, messagePos, messageScale, wordwrap=24) Fanfare.makeImageBox(go.itemFrame, image, imagePos, imageScale) Sequence(Func(go.show), LerpColorScaleInterval(go, duration=0.5, startColorScale=Vec4(1, 1, 1, 0), colorScale=Vec4(1, 1, 1, 1)), Wait(10), LerpColorScaleInterval(go, duration=0.5, startColorScale=Vec4(1, 1, 1, 1), colorScale=Vec4(1, 1, 1, 0)), Func(go.remove)).start() def promoteShovel(self, shovelLevel = 0): shovelName = GardenGlobals.ShovelAttributes[shovelLevel]['name'] shovelBeans = GardenGlobals.getShovelPower(shovelLevel, 0) message = TTLocalizer.GardenShovelLevelUp % {'shovel': shovelName, 'oldbeans': shovelBeans - 1, 'newbeans': shovelBeans} messagePos = Vec2(0, 0.2) messageScale = 0.07 image = loader.loadModel('phase_5.5/models/gui/planting_but_shovel_P') imagePos = Vec3(0, 0, -0.13) imageScale = Vec3(0.28, 0, 0.56) go = Fanfare.makePanel(base.localAvatar, 1) Fanfare.makeMessageBox(go, message, messagePos, messageScale, wordwrap=24) Fanfare.makeImageBox(go.itemFrame, image, imagePos, imageScale) Sequence(Func(go.show), LerpColorScaleInterval(go, duration=0.5, startColorScale=Vec4(1, 1, 1, 0), colorScale=Vec4(1, 1, 1, 1)), Wait(10), LerpColorScaleInterval(go, duration=0.5, startColorScale=Vec4(1, 1, 1, 1), colorScale=Vec4(1, 1, 1, 0)), Func(go.remove)).start() def promoteWateringCan(self, wateringCanlevel = 0): message = TTLocalizer.GardenWateringCanLevelUp + ' \n' + GardenGlobals.WateringCanAttributes[wateringCanlevel]['name'] messagePos = Vec2(0, 0.2) messageScale = 0.08 image = loader.loadModel('phase_5.5/models/gui/planting_but_can_P') imagePos = Vec3(0, 0, -0.1) imageScale = Vec3(0.35, 0, 0.7) if wateringCanlevel >= GardenGlobals.MAX_WATERING_CANS - 1: go = Fanfare.makeFanfareWithMessageImage(0, base.localAvatar, 1, message, Vec2(0, 0.2), 0.08, image, Vec3(0, 0, -0.1), Vec3(0.35, 0, 0.7)) Sequence(go[0], Func(go[1].show), LerpColorScaleInterval(go[1], duration=0.5, startColorScale=Vec4(1, 1, 1, 0), colorScale=Vec4(1, 1, 1, 1)), Wait(5), LerpColorScaleInterval(go[1], duration=0.5, startColorScale=Vec4(1, 1, 1, 1), colorScale=Vec4(1, 1, 1, 0)), Func(go[1].remove)).start() else: go = Fanfare.makePanel(base.localAvatar, 1) Fanfare.makeMessageBox(go, message, messagePos, messageScale) Fanfare.makeImageBox(go.itemFrame, image, imagePos, imageScale) Sequence(Func(go.show), LerpColorScaleInterval(go, duration=0.5, startColorScale=Vec4(1, 1, 1, 0), colorScale=Vec4(1, 1, 1, 1)), Wait(5), LerpColorScaleInterval(go, duration=0.5, startColorScale=Vec4(1, 1, 1, 1), colorScale=Vec4(1, 1, 1, 0)), Func(go.remove)).start() def setInGardenAction(self, actionObject, fromObject = None): if actionObject: self.lockGardeningButtons() elif fromObject: self.unlockGardeningButtons() else: self.unlockGardeningButtons() self.inGardenAction = actionObject def __wateringCanButtonClicked(self): self.notify.debug('wateringCanButtonClicked') if self.inGardenAction: return plant = base.cr.doId2do.get(self.shovelRelatedDoId) if plant: if hasattr(plant, 'handleWatering'): plant.handleWatering() messenger.send('wakeup') def __shovelButtonClicked(self): if self.inGardenAction: return self.notify.debug('shovelButtonClicked') messenger.send('wakeup') thingId = self.shovelRelatedDoId thing = base.cr.doId2do.get(thingId) if hasattr(self, 'extraShovelCommand'): self.extraShovelCommand() self.setActivePlot(thingId) def setShovel(self, shovelId): DistributedToon.DistributedToon.setShovel(self, shovelId) if self.__gardeningGui: self.setShovelGuiLevel(shovelId) def setWateringCan(self, wateringCanId): DistributedToon.DistributedToon.setWateringCan(self, wateringCanId) if self.__gardeningGui: self.setWateringCanGuiLevel(wateringCanId) def setGardenStarted(self, bStarted): self.gardenStarted = bStarted if self.gardenStarted and not self.gardenPage and hasattr(self, 'book'): self.loadGardenPages() def b_setAnimState(self, animName, animMultiplier = 1.0, callback = None, extraArgs = []): if self.wantStatePrint: print('Local Toon Anim State %s' % animName) DistributedToon.DistributedToon.b_setAnimState(self, animName, animMultiplier, callback, extraArgs) def swimTimeoutAction(self): self.ignore('wakeup') self.takeOffSuit() base.cr.playGame.getPlace().fsm.request('final') self.b_setAnimState('TeleportOut', 1, self.__handleSwimExitTeleport, [0]) return Task.done def __handleSwimExitTeleport(self, requestStatus): self.notify.info('closing shard...') base.cr.gameFSM.request('closeShard', ['afkTimeout']) def sbFriendAdd(self, id, info): print('sbFriendAdd') def sbFriendUpdate(self, id, info): print('sbFriendUpdate') def sbFriendRemove(self, id): print('sbFriendRemove') def addGolfPage(self): if self.hasPlayedGolf(): if hasattr(self, 'golfPage') and self.golfPage != None: return if not launcher.getPhaseComplete(6): self.acceptOnce('phaseComplete-6', self.addGolfPage) return self.golfPage = GolfPage.GolfPage() self.golfPage.setAvatar(self) self.golfPage.load() self.book.addPage(self.golfPage, pageName=TTLocalizer.GolfPageTitle) return def addEventsPage(self): if hasattr(self, 'eventsPage') and self.eventsPage != None: return if not launcher.getPhaseComplete(4): self.acceptOnce('phaseComplete-4', self.addEventsPage) return self.eventsPage = EventsPage.EventsPage() self.eventsPage.load() self.book.addPage(self.eventsPage, pageName=TTLocalizer.EventsPageName) return def addNewsPage(self): self.newsPage = NewsPage.NewsPage() self.newsPage.load() self.book.addPage(self.newsPage, pageName=TTLocalizer.NewsPageName) def addTIPPage(self): self.tipPage = TIPPage.TIPPage() self.tipPage.load() self.book.addPage(self.tipPage, pageName=TTLocalizer.TIPPageTitle) def setPinkSlips(self, pinkSlips): DistributedToon.DistributedToon.setPinkSlips(self, pinkSlips) self.inventory.updateTotalPropsText() def getAccountDays(self): days = 0 defaultDays = base.cr.config.GetInt('account-days', -1) if defaultDays >= 0: days = defaultDays elif hasattr(base.cr, 'accountDays'): days = base.cr.accountDays return days def hasActiveBoardingGroup(self): if hasattr(localAvatar, 'boardingParty') and localAvatar.boardingParty: return localAvatar.boardingParty.hasActiveGroup(localAvatar.doId) else: return False def getZoneId(self): return self._zoneId def setZoneId(self, value): if value == -1: self.notify.error('zoneId should not be set to -1, tell Redmond') self._zoneId = value zoneId = property(getZoneId, setZoneId) def systemWarning(self, warningText = 'Acknowledge this system message.'): self.createSystemMsgAckGui() self.systemMsgAckGui['text'] = warningText self.systemMsgAckGui.show() def createSystemMsgAckGui(self): if self.systemMsgAckGui == None or self.systemMsgAckGui.isEmpty(): message = 'o' * 100 self.systemMsgAckGui = TTDialog.TTGlobalDialog(doneEvent=self.systemMsgAckGuiDoneEvent, message=message, style=TTDialog.Acknowledge) self.systemMsgAckGui.hide() return def hideSystemMsgAckGui(self): if self.systemMsgAckGui != None and not self.systemMsgAckGui.isEmpty(): self.systemMsgAckGui.hide() return def setSleepAutoReply(self, fromId): av = base.cr.identifyAvatar(fromId) if isinstance(av, DistributedToon.DistributedToon): base.localAvatar.setSystemMessage(0, TTLocalizer.sleep_auto_reply % av.getName(), WhisperPopup.WTToontownBoardingGroup) elif av is not None: self.notify.warning('setSleepAutoReply from non-toon %s' % fromId) return def setLastTimeReadNews(self, newTime): self.lastTimeReadNews = newTime def getLastTimeReadNews(self): return self.lastTimeReadNews def cheatCogdoMazeGame(self, kindOfCheat = 0): if base.config.GetBool('allow-cogdo-maze-suit-hit-cheat'): maze = base.cr.doFind('DistCogdoMazeGame') if maze: if kindOfCheat == 0: for suitNum in list(maze.game.suitsById.keys()): suit = maze.game.suitsById[suitNum] maze.sendUpdate('requestSuitHitByGag', [suit.type, suitNum]) elif kindOfCheat == 1: for joke in maze.game.pickups: maze.sendUpdate('requestPickUp', [joke.serialNum]) else: self.sendUpdate('logSuspiciousEvent', ['cheatCogdoMazeGame']) def isReadingNews(self): result = False if base.cr and base.cr.playGame and base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(), 'fsm') and base.cr.playGame.getPlace().fsm: fsm = base.cr.playGame.getPlace().fsm curState = fsm.getCurrentState().getName() if curState == 'stickerBook' and WantNewsPage: if hasattr(self, 'newsPage'): if self.book.isOnPage(self.newsPage): result = True return result def doTeleportResponse(self, fromAvatar, toAvatar, avId, available, shardId, hoodId, zoneId, sendToId): localAvatar.d_teleportResponse(avId, available, shardId, hoodId, zoneId, sendToId) def d_teleportResponse(self, avId, available, shardId, hoodId, zoneId, sendToId = None): if base.config.GetBool('want-tptrack', False): if available == 1: self.notify.debug('sending teleportResponseToAI') self.sendUpdate('teleportResponseToAI', [avId, available, shardId, hoodId, zoneId, sendToId]) else: self.sendUpdate('teleportResponse', [avId, available, shardId, hoodId, zoneId], sendToId) else: DistributedPlayer.DistributedPlayer.d_teleportResponse(self, avId, available, shardId, hoodId, zoneId, sendToId) def startQuestMap(self): if self.questMap: self.questMap.start() def stopQuestMap(self): if self.questMap: self.questMap.stop() def _startZombieCheck(self): pass def _stopZombieCheck(self): pass