282 lines
12 KiB
Python
282 lines
12 KiB
Python
import math
|
|
from pandac.PandaModules import CardMaker, TextNode, Point3
|
|
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.wantToggle = False
|
|
if config.GetBool('want-toggle-quest-map', True):
|
|
self.wantToggle = True
|
|
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
|
|
|
|
return
|
|
|
|
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()
|
|
|
|
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]
|
|
|
|
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):
|
|
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()
|
|
|
|
def updateQuestInfo(self):
|
|
for marker in self.buildingMarkers:
|
|
marker.destroy()
|
|
|
|
self.buildingMarkers = []
|
|
dnaData = base.cr.playGame.dnaData
|
|
for questIndex in self.av.questPage.quests.keys():
|
|
questDesc = self.av.questPage.quests.get(questIndex)
|
|
if questDesc is None:
|
|
continue
|
|
mapIndex = questIndex + 1
|
|
questId, fromNpcId, toNpcId, rewardId, toonProgress = questDesc
|
|
quest = Quests.getQuest(questId)
|
|
fComplete = quest.getCompletionStatus(self.av, questDesc) == Quests.COMPLETE
|
|
if not fComplete:
|
|
if quest.getType() == Quests.RecoverItemQuest:
|
|
if quest.getHolder() == Quests.AnyFish:
|
|
self.putBuildingMarker(self.fishingSpotInfo, mapIndex=mapIndex)
|
|
continue
|
|
elif quest.getType() != Quests.DeliverGagQuest and quest.getType() != Quests.DeliverItemQuest and quest.getType() != Quests.VisitQuest and quest.getType() != Quests.TrackChoiceQuest:
|
|
continue
|
|
if toNpcId == Quests.ToonHQ:
|
|
self.putBuildingMarker(self.hqPosInfo, mapIndex=mapIndex)
|
|
else:
|
|
npcZone = NPCToons.getNPCZone(toNpcId)
|
|
hoodId = ZoneUtil.getCanonicalHoodId(npcZone)
|
|
branchId = ZoneUtil.getCanonicalBranchZone(npcZone)
|
|
if self.hoodId == hoodId and self.zoneId == branchId:
|
|
for blockId, block in dnaData.getBlocks():
|
|
zone = block.zone
|
|
branchZone = zone - zone % 100
|
|
finalZone = branchZone + 500 + blockId
|
|
if npcZone == finalZone:
|
|
building = block.node
|
|
self.putBuildingMarker(Point3(building.getPos()), building.getHpr(), mapIndex=mapIndex)
|
|
|
|
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:
|
|
if not buildingMarker.isEmpty():
|
|
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:
|
|
try:
|
|
hoodId = ZoneUtil.getCanonicalHoodId(self.av.getLocation()[1])
|
|
zoneId = ZoneUtil.getCanonicalBranchZone(self.av.getLocation()[1])
|
|
mapsGeom = loader.loadModel('phase_4/models/questmap/%s_maps' % ToontownGlobals.dnaMap[hoodId])
|
|
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()
|
|
except:
|
|
self.stop()
|
|
|
|
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):
|
|
if self.wantToggle:
|
|
self.accept(ToontownGlobals.MapHotkey, self.toggle)
|
|
else:
|
|
self.accept(ToontownGlobals.MapHotkeyOn, self.show)
|
|
self.accept(ToontownGlobals.MapHotkeyOff, self.hide)
|
|
self.updateMap()
|
|
|
|
def ignoreOnscreenHooks(self):
|
|
self.ignore(ToontownGlobals.MapHotkey)
|
|
self.ignore(ToontownGlobals.MapHotkeyOn)
|
|
self.ignore(ToontownGlobals.MapHotkeyOff)
|
|
self.obscureButton()
|