import math from pandac.PandaModules import CardMaker, TextNode from direct.gui.DirectGui import DirectFrame, DirectLabel, DirectButton from direct.task import Task from toontown.toon import NPCToons from toontown.hood import ZoneUtil from toontown.toonbase import ToontownGlobals from toontown.quest import Quests from toontown.suit import SuitPlannerBase import QuestMapGlobals class QuestMap(DirectFrame): def __init__(self, av, **kw): DirectFrame.__init__(self, relief=None, sortOrder=50) self.initialiseoptions(QuestMap) self.container = DirectFrame(parent=self, relief=None) self.marker = DirectFrame(parent=self.container, relief=None) self.cogInfoFrame = DirectFrame(parent=self.container, relief=None) cm = CardMaker('bg') cm.setFrame(-0.5, 0.5, -0.5, 0.5) bg = self.cogInfoFrame.attachNewNode(cm.generate()) bg.setTransparency(1) bg.setColor(0.5, 0.5, 0.5, 0.5) bg.setBin('fixed', 0) self.cogInfoFrame['geom'] = bg self.cogInfoFrame['geom_pos'] = (0, 0, 0) self.cogInfoFrame['geom_scale'] = (6, 1, 2) self.cogInfoFrame.setScale(0.05) self.cogInfoFrame.setPos(0, 0, 0.6) self.buildingMarkers = [] self.av = av self.updateMarker = True self.cornerPosInfo = None self.hqPosInfo = None self.fishingSpotInfo = None self.load() self.setScale(1.5) bg.removeNode() self.hoodId = None self.zoneId = None self.suitPercentage = {} for currHoodInfo in SuitPlannerBase.SuitPlannerBase.SuitHoodInfo: tracks = currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_TRACK] self.suitPercentage[currHoodInfo[SuitPlannerBase.SuitPlannerBase.SUIT_HOOD_INFO_ZONE]] = tracks def load(self): gui = loader.loadModel('phase_4/models/questmap/questmap_gui') icon = gui.find('**/tt_t_gui_qst_arrow') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setR(90) self.marker['geom'] = iconNP self.marker['image'] = iconNP self.marker.setScale(0.05) iconNP.removeNode() self.mapOpenButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapClose'), gui.find('**/tt_t_gui_qst_mapTryToOpen')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.show) self.mapCloseButton = DirectButton(image=(gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapOpen'), gui.find('**/tt_t_gui_qst_mapTryToClose')), relief=None, pos=(-0.08, 0, 0.37), parent=base.a2dBottomRight, scale=0.205, command=self.hide) self.mapOpenButton.hide() self.mapCloseButton.hide() gui.removeNode() icons = loader.loadModel('phase_3/models/gui/cog_icons') cIcon = icons.find('**/CorpIcon') lIcon = icons.find('**/LegalIcon') mIcon = icons.find('**/MoneyIcon') sIcon = icons.find('**/SalesIcon') cogInfoTextColor = (0.2, 0.2, 0.2, 1) textPos = (1.2, -0.2) textScale = 0.8 self.cInfo = DirectLabel(parent=self.cogInfoFrame, text='', text_fg=cogInfoTextColor, text_pos=textPos, text_scale=textScale, geom=cIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.cInfo.setPos(-2.2, 0, 0.5) self.lInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=lIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.lInfo.setPos(-2.2, 0, -0.5) self.mInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=mIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.mInfo.setPos(0.8, 0, 0.5) self.sInfo = DirectLabel(parent=self.cogInfoFrame, text_fg=cogInfoTextColor, text='', text_pos=textPos, text_scale=textScale, geom=sIcon, geom_pos=(-0.2, 0, 0), geom_scale=0.8, relief=None) self.sInfo.setPos(0.8, 0, -0.5) icons.removeNode() return def updateCogInfo(self): currPercentage = self.suitPercentage.get(self.zoneId) if currPercentage is None: return self.cInfo['text'] = '%s%%' % currPercentage[0] self.lInfo['text'] = '%s%%' % currPercentage[1] self.mInfo['text'] = '%s%%' % currPercentage[2] self.sInfo['text'] = '%s%%' % currPercentage[3] return def destroy(self): self.ignore('questPageUpdated') self.mapOpenButton.destroy() self.mapCloseButton.destroy() del self.mapOpenButton del self.mapCloseButton DirectFrame.destroy(self) def putBuildingMarker(self, pos, hpr = (0, 0, 0), mapIndex = None, zoneId=None): marker = DirectLabel(parent=self.container, text='', text_pos=(-0.05, -0.15), text_fg=(1, 1, 1, 1), relief=None) gui = loader.loadModel('phase_4/models/parties/schtickerbookHostingGUI') icon = gui.find('**/startPartyButton_inactive') iconNP = aspect2d.attachNewNode('iconNP') icon.reparentTo(iconNP) icon.setX(-12.0792 / 30.48) icon.setZ(-9.7404 / 30.48) marker['text'] = '%s' % mapIndex marker['text_scale'] = 0.7 marker['image'] = iconNP marker['image_color'] = (1, 0, 0, 1) marker['image_scale'] = 6 marker.setScale(0.05) relX, relY = self.transformAvPos(pos) marker.setPos(relX, 0, relY) self.buildingMarkers.append(marker) iconNP.removeNode() gui.removeNode() if zoneId: base.cr.buildingQueryMgr.d_isSuit(zoneId, lambda isSuit: self.updateMarkerColor(marker, isSuit)) def updateMarkerColor(self, marker, isSuit): if isSuit: marker['image_color'] = (0.4, 0.4, 0.4, 1.0) def updateQuestInfo(self): for marker in self.buildingMarkers: marker.destroy() self.buildingMarkers = [] for (i, questDesc) in enumerate(self.av.quests): mapIndex = i + 1 quest = Quests.getQuest(questDesc[0]) toNpcId = questDesc[2] completed = quest.getCompletionStatus(self.av, questDesc) == Quests.COMPLETE if not completed: if quest.getType() == Quests.RecoverItemQuest: if quest.getHolder() == Quests.AnyFish: self.putBuildingMarker(self.fishingSpotInfo, mapIndex=mapIndex) continue elif quest.getType() not in ( Quests.DeliverGagQuest, Quests.DeliverItemQuest, Quests.VisitQuest, Quests.TrackChoiceQuest): continue if toNpcId == Quests.ToonHQ: self.putBuildingMarker(self.hqPosInfo, mapIndex=mapIndex) continue npcZoneId = NPCToons.getNPCZone(toNpcId) hoodId = ZoneUtil.getCanonicalHoodId(npcZoneId) branchId = ZoneUtil.getCanonicalBranchZone(npcZoneId) if (self.hoodId != hoodId) or (self.zoneId != branchId): continue for blockIndex in xrange(base.cr.playGame.dnaStore.getNumBlockNumbers()): blockNumber = base.cr.playGame.dnaStore.getBlockNumberAt(blockIndex) zoneId = base.cr.playGame.dnaStore.getZoneFromBlockNumber(blockNumber) interiorZoneId = (zoneId - (zoneId%100)) + 500 + blockNumber if npcZoneId == interiorZoneId: self.putBuildingMarker( base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getPos(render), base.cr.playGame.dnaStore.getDoorPosHprFromBlockNumber(blockNumber).getHpr(render), mapIndex=mapIndex, zoneId=zoneId) def transformAvPos(self, pos): if self.cornerPosInfo is None: return (0, 0) topRight = self.cornerPosInfo[0] bottomLeft = self.cornerPosInfo[1] relativeX = (pos.getX() - bottomLeft.getX()) / (topRight.getX() - bottomLeft.getX()) - 0.5 relativeY = (pos.getY() - bottomLeft.getY()) / (topRight.getY() - bottomLeft.getY()) - 0.5 return (relativeX, relativeY) def update(self, task): if self.av: if self.updateMarker: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) i = 0 for buildingMarker in self.buildingMarkers: buildingMarker.setScale((math.sin(task.time * 16.0 + i * math.pi / 3.0) + 1) * 0.005 + 0.04) i = i + 1 return Task.cont def updateMap(self): if self.av: hoodId = ZoneUtil.getCanonicalHoodId(self.av.getLocation()[1]) zoneId = ZoneUtil.getCanonicalBranchZone(self.av.getLocation()[1]) try: mapsGeom = loader.loadModel('phase_4/models/questmap/%s_maps' % ToontownGlobals.dnaMap[hoodId]) except: self.stop() return mapImage = mapsGeom.find('**/%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) if not mapImage.isEmpty(): self.container['image'] = mapImage self.resetFrameSize() self.cornerPosInfo = QuestMapGlobals.CornerPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.hqPosInfo = QuestMapGlobals.HQPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.fishingSpotInfo = QuestMapGlobals.FishingSpotPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoPos = QuestMapGlobals.CogInfoPosTable.get('%s_%s_english' % (ToontownGlobals.dnaMap[hoodId], zoneId)) self.cogInfoFrame.setPos(self.cogInfoPos) self.hide() self.hoodId = hoodId self.zoneId = zoneId self.updateQuestInfo() self.updateCogInfo() taskMgr.add(self.update, 'questMapUpdate') else: self.stop() mapsGeom.removeNode() def start(self): self.container.show() self.accept('questPageUpdated', self.updateMap) self.handleMarker() self.updateMap() def initMarker(self, task): if self.av: if not hasattr(base.cr.playGame.getPlace(), 'isInterior') or not base.cr.playGame.getPlace().isInterior: relX, relY = self.transformAvPos(self.av.getPos()) self.marker.setPos(relX, 0, relY) self.marker.setHpr(0, 0, -180 - self.av.getH()) self.marker['geom_scale'] = 1.4 * task.time % 0.5 * 10 + 1 self.marker['geom_color'] = (1, 1, 1, 0.8 - 1.4 * task.time % 0.5 * 2 / 0.8 + 0.2) if task.time < 1: return Task.cont else: self.marker['geom_color'] = (1, 1, 1, 0) return Task.done def show(self): taskMgr.add(self.initMarker, 'questMapInit') DirectFrame.show(self) self.mapOpenButton.hide() if self.container['image']: self.mapCloseButton.show() def hide(self): taskMgr.remove('questMapInit') DirectFrame.hide(self) if self.container['image']: self.mapOpenButton.show() self.mapCloseButton.hide() def toggle(self): if self.isHidden(): self.show() else: self.hide() def obscureButton(self): self.mapOpenButton.hide() self.mapCloseButton.hide() def stop(self): self.container['image'] = None for marker in self.buildingMarkers: marker.destroy() self.buildingMarkers = [] self.container.hide() self.hide() self.obscureButton() self.ignore('questPageUpdated') taskMgr.remove('questMapUpdate') def handleMarker(self): if hasattr(base.cr.playGame.getPlace(), 'isInterior') and base.cr.playGame.getPlace().isInterior: self.updateMarker = False else: self.updateMarker = True def acceptOnscreenHooks(self): self.accept(ToontownGlobals.MapHotkey, self.toggle) self.updateMap() def ignoreOnscreenHooks(self): self.ignore(ToontownGlobals.MapHotkey) self.obscureButton()