NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

infoPanelSvc.py (21573B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\infoPanels\infoPanelSvc.py
      2 import sys
      3 import eveformat.client
      4 import evelink.client
      5 import localization
      6 import log
      7 import telemetry
      8 import uthread
      9 import uthread2
     10 from achievement_system.client.api.signal import on_achievements_tracked_changed
     11 from carbon.common.script.sys import service
     12 from carbon.common.script.util import commonutils
     13 from carbon.common.script.util.timerstuff import AutoTimer
     14 from carbonui import uiconst
     15 from carbonui.primitives.container import Container
     16 from carbonui.uicore import uicore
     17 from carbonui.util import colorblind
     18 from eve.client.script.ui.crimewatch import crimewatchTimers
     19 from eve.client.script.ui.shared.careerPortal.cpSignals import on_cp_goal_tracking_removed, on_cp_goal_tracking_added
     20 from eve.client.script.ui.shared.infoPanels import sessionTimeIndicator
     21 from eve.client.script.ui.shared.infoPanels.const import infoPanelConst
     22 from eve.client.script.ui.shared.infoPanels.const import infoPanelUIConst
     23 from eve.client.script.ui.shared.infoPanels.infoPanelContainer import InfoPanelContainer
     24 from eve.client.script.ui.shared.infoPanels.milestoneTimer.milestoneTimer import MilestoneTimer
     25 from eve.common.script.sys import idCheckers
     26 from eveformat.client import solar_system_security_status
     27 from jobboard.client import job_board_signals
     28 from milestones.common.constants import MILESTONE_REWARD_MINUTES, MILESTONE_HUNDRED_AND_TWENTY_MINUTES_ID
     29 from operations.common.const import OPERATION_CATEGORY_RECOMMENDATIONS
     30 from uthread2 import StartTasklet
     31 MISSION_INFO_PANEL_UPDATE_DELAY_MSEC = 1000
     32 OPERATION_INFO_PANEL_UPDATE_DELAY_MSEC = 1000
     33 RECOMMENDATION_INFO_PANEL_UPDATE_DELAY_SEC = 0.5
     34 AIR_NPE_INFO_PANEL_UPDATE_DELAY_SEC = 0.5
     35 
     36 class InfoPanelSvc(service.Service):
     37     __update_on_reload__ = 1
     38     __guid__ = 'svc.infoPanel'
     39     __startupdependencies__ = ['missionObjectivesTracker']
     40     __notifyevents__ = ['OnSessionChanged',
     41      'OnClientEvent_WarpFinished',
     42      'OnViewStateChanged',
     43      'OnSovereigntyChanged',
     44      'OnSystemStatusChanged',
     45      'OnEntitySelectionChanged',
     46      'OnChallengeProgressUpdate',
     47      'OnChallengeCompleted',
     48      'OnRWDungeonEnteredInClient',
     49      'OnRWDungeonExitedInClient',
     50      'OnRWTimerEndedInClient',
     51      'OnOperationMadeActive',
     52      'OnOperationCompleted',
     53      'OnOperationReplayed',
     54      'OnOperationTaskTransition',
     55      'OnTutorialSkipped',
     56      'OnOperationDeactivatedUpdate',
     57      'OnRecommendationsUpdated',
     58      'OnAirNpeStateChanged',
     59      'OnAirNpeObjectiveUpdated',
     60      'OnInsurgencyCampaignStartedForLocation_Local',
     61      'OnInsurgencyCampaignEndingForLocation_Local',
     62      'OnInsurgencyCampaignUpdatedForLocation_Local']
     63 
     64     def Run(self, *args):
     65         self.sidePanel = None
     66         self.infoPanelContainer = None
     67         self.sessionTimer = None
     68         self.sessionTimerUpdatePending = False
     69         self.operationInfoPanelUpdater = None
     70         self.recommendationsInfoPanelUpdater = None
     71         self.missionInfoPanelUpdater = None
     72         self.airNpeInfoPanelUpdater = None
     73         self.combatTimerContainer = None
     74         self.milestoneTimer = None
     75         self.expandedMission = None
     76 
     77     def Reload(self):
     78         if self.sidePanel:
     79             self.sidePanel.Close()
     80             self.sidePanel = None
     81         if self.sessionTimer:
     82             self.sessionTimer.Close()
     83         if self.combatTimerContainer:
     84             self.combatTimerContainer.Release()
     85         if self.milestoneTimer:
     86             self.milestoneTimer.Close()
     87             self.milestoneTimer = None
     88         self.ReconstructAllPanels()
     89         self.DisconnectSignals()
     90 
     91     @telemetry.ZONE_FUNCTION
     92     def ConstructSidePanel(self):
     93         self.sidePanel = Container(parent=uicore.layer.sidePanels, name='sidePanel', align=uiconst.TOLEFT_NOPUSH, width=infoPanelUIConst.PANELWIDTH, padding=(0, 12, 0, 0))
     94         self.sidePanel.cacheContents = True
     95         self.combatTimerContainer = crimewatchTimers.TimerContainer(parent=self.sidePanel, left=infoPanelUIConst.LEFTPAD)
     96         self.infoPanelContainer = InfoPanelContainer(parent=self.sidePanel, align=uiconst.TOTOP)
     97         self.sessionTimer = sessionTimeIndicator.SessionTimeIndicator(parent=self.sidePanel, pos=(16, 35, 24, 24), state=uiconst.UI_HIDDEN, align=uiconst.TOPLEFT)
     98         if self.sessionTimerUpdatePending:
     99             self.UpdateSessionTimer()
    100         self.missionObjectivesTracker.RegisterMissionTracking()
    101 
    102     def ConstructMilestoneTimer(self):
    103         milestoneSvc = sm.GetService('milestoneSvc')
    104         timeLeft = milestoneSvc.GetTimeLeftInMilestone()
    105         if timeLeft is None:
    106             return
    107         self.milestoneTimer = MilestoneTimer(parent=self.sidePanel, left=10, iconPath='res:/UI/Texture/Crimewatch/iskIcon.png', timeLeft=timeLeft, totalTime=MILESTONE_REWARD_MINUTES, milestoneID=MILESTONE_HUNDRED_AND_TWENTY_MINUTES_ID)
    108 
    109     def UpdateSessionTimer(self):
    110         if self.sessionTimer:
    111             StartTasklet(self.sessionTimer.AnimSessionChange)
    112             self.sessionTimerUpdatePending = False
    113         else:
    114             self.sessionTimerUpdatePending = True
    115 
    116     def ShowHideSidePanel(self, hide = 1, *args):
    117         if self.sidePanel is not None and not self.sidePanel.destroyed:
    118             if hide:
    119                 self.sidePanel.state = uiconst.UI_HIDDEN
    120             else:
    121                 self.sidePanel.state = uiconst.UI_PICKCHILDREN
    122 
    123     def GetPanelByTypeID(self, panelTypeID):
    124         if self.infoPanelContainer:
    125             return self.infoPanelContainer.GetPanelByTypeID(panelTypeID)
    126 
    127     @telemetry.ZONE_FUNCTION
    128     def OnViewStateChanged(self, oldView, newView):
    129         self.ReconstructAllPanels(animate=True, settingsID=newView)
    130 
    131     @telemetry.ZONE_FUNCTION
    132     def ReconstructAllPanels(self, animate = False, settingsID = None):
    133         if not session.charid:
    134             return
    135         if not self.sidePanel:
    136             self.ConstructSidePanel()
    137         if not self.milestoneTimer:
    138             self.ConstructMilestoneTimer()
    139         if not settingsID:
    140             settingsID = sm.GetService('viewState').GetCurrentView().name
    141         self.infoPanelContainer.ReconstructPanels(settingsID, animate)
    142 
    143     def UpdateAllPanels(self):
    144         if not session.charid or not self.sidePanel:
    145             return
    146         sm.ChainEvent('ProcessUpdateInfoPanel', None)
    147 
    148     def ConnectSignals(self):
    149         on_cp_goal_tracking_added.connect(self.OnCareerProgramTrackingUpdated)
    150         on_cp_goal_tracking_removed.connect(self.OnCareerProgramTrackingUpdated)
    151         job_board_signals.on_job_board_feature_availability_changed.connect(self.OnJobBoardAvailabilityChanged)
    152         job_board_signals.on_tracked_jobs_changed.connect(self.OnTrackedJobsChanged)
    153         colorblind.on_colorblind_mode_changed.connect(self.OnColorBlindModeChanged)
    154         on_achievements_tracked_changed.connect(self.OnTrackedAchievementChanged)
    155 
    156     def DisconnectSignals(self):
    157         on_cp_goal_tracking_added.disconnect(self.OnCareerProgramTrackingUpdated)
    158         on_cp_goal_tracking_removed.disconnect(self.OnCareerProgramTrackingUpdated)
    159         job_board_signals.on_job_board_feature_availability_changed.disconnect(self.OnJobBoardAvailabilityChanged)
    160         job_board_signals.on_tracked_jobs_changed.disconnect(self.OnTrackedJobsChanged)
    161         colorblind.on_colorblind_mode_changed.disconnect(self.OnColorBlindModeChanged)
    162         on_achievements_tracked_changed.disconnect(self.OnTrackedAchievementChanged)
    163 
    164     @telemetry.ZONE_FUNCTION
    165     def OnSessionChanged(self, isRemote, sess, change):
    166         if not session.charid:
    167             return
    168         if 'charid' in change and change['charid'][1] is not None:
    169             self.Reload()
    170             self.ConnectSignals()
    171         self.UpdateSessionTimer()
    172         self.UpdateFactionalWarfarePanel()
    173         self.UpdateLocationInfoPanel()
    174         self.UpdateOperationsPanel()
    175         self.UpdateAirNpePanel()
    176 
    177     def OnClientEvent_WarpFinished(self, *args, **kwargs):
    178         self.UpdateOperationsPanel()
    179         self.UpdateAirNpePanel()
    180 
    181     def OnAirNpeStateChanged(self, *args, **kwargs):
    182         self.UpdateAirNpePanel(skip_wait=True)
    183 
    184     def GetActiveOperationObjective(self):
    185         if not session.charid or not self.infoPanelContainer:
    186             return None
    187         panel = self.GetPanelByTypeID(infoPanelConst.PANEL_OPERATIONS)
    188         if not panel or not panel.IsAvailable():
    189             return None
    190         return panel.GetFirstActiveObjective()
    191 
    192     def IsPanelAvailable(self, panelTypeID):
    193         if not session.charid or not self.infoPanelContainer:
    194             return False
    195         panel = self.GetPanelByTypeID(panelTypeID)
    196         if not panel or not panel.IsAvailable():
    197             return False
    198         return True
    199 
    200     def IsMissionsPanelActive(self):
    201         return self.IsPanelAvailable(infoPanelConst.PANEL_MISSIONS)
    202 
    203     def OnSovereigntyChanged(self, solarSystemID, allianceID):
    204         self.UpdateAllPanels()
    205 
    206     def OnSystemStatusChanged(self, *args):
    207         self.UpdateAllPanels()
    208 
    209     def OnEntitySelectionChanged(self, entityID):
    210         self.UpdateAllPanels()
    211 
    212     def OnColorBlindModeChanged(self):
    213         self.ReconstructAllPanels()
    214 
    215     def OnRWDungeonEnteredInClient(self):
    216         self.UpdatePanel(infoPanelConst.PANEL_RESOURCE_WARS)
    217 
    218     def OnRWDungeonExitedInClient(self):
    219         self.UpdatePanel(infoPanelConst.PANEL_RESOURCE_WARS)
    220 
    221     def OnRWTimerEndedInClient(self):
    222         self.UpdatePanel(infoPanelConst.PANEL_RESOURCE_WARS)
    223 
    224     @telemetry.ZONE_FUNCTION
    225     def UpdateMissionsPanel(self, callback = None):
    226         if self.missionInfoPanelUpdater is None:
    227             self.missionInfoPanelUpdater = AutoTimer(interval=MISSION_INFO_PANEL_UPDATE_DELAY_MSEC, method=self._UpdateMissionsPanelThread, callback=callback)
    228 
    229     def _UpdateMissionsPanelThread(self, callback):
    230         self.missionInfoPanelUpdater = None
    231         self.UpdatePanel(infoPanelConst.PANEL_MISSIONS, False)
    232         if callback:
    233             callback()
    234 
    235     def SetExpandedMission(self, featureID, missionID):
    236         if missionID == -1 and self.expandedMission.get('featureID') != featureID:
    237             return
    238         if self.expandedMission and self.expandedMission.get('featureID') == featureID and self.expandedMission.get('missionID') == missionID:
    239             return
    240         self.expandedMission = {'featureID': featureID,
    241          'missionID': missionID}
    242         settings.char.ui.Set('infoPanelExpandedMission', self.expandedMission)
    243         sm.ScatterEvent('OnExpandedMissionChanged', **self.expandedMission)
    244 
    245     def GetExpandedMission(self):
    246         if self.expandedMission is None:
    247             self.expandedMission = settings.char.ui.Get('infoPanelExpandedMission', {})
    248         return self.expandedMission
    249 
    250     def UpdateExpandedAgentMission(self):
    251         agentID = self.missionObjectivesTracker.GetAgentForLastAcceptedMission()
    252         panel = self.GetPanelByTypeID(infoPanelConst.PANEL_MISSIONS)
    253         if panel and panel.IsAvailable():
    254             panel.UpdateExpandedStateForMissionID(agentID)
    255 
    256     @telemetry.ZONE_FUNCTION
    257     def UpdateOperationsPanel(self, categoryID = None):
    258         if categoryID == OPERATION_CATEGORY_RECOMMENDATIONS or categoryID is None:
    259             self.LogInfo('UpdateOperationsPanel::Recommendations - categoryID: %s' % categoryID)
    260             if self.recommendationsInfoPanelUpdater:
    261                 return
    262             self.recommendationsInfoPanelUpdater = uthread2.call_after_wallclocktime_delay(self._UpdateRecommendationsPanelThread, RECOMMENDATION_INFO_PANEL_UPDATE_DELAY_SEC)
    263             if categoryID == OPERATION_CATEGORY_RECOMMENDATIONS:
    264                 return
    265         if self.operationInfoPanelUpdater is None:
    266             self.operationInfoPanelUpdater = AutoTimer(interval=OPERATION_INFO_PANEL_UPDATE_DELAY_MSEC, method=self._UpdateOperationsPanelThread)
    267 
    268     def _UpdateOperationsPanelThread(self):
    269         self.operationInfoPanelUpdater = None
    270         self.UpdatePanel(infoPanelConst.PANEL_OPERATIONS)
    271 
    272     def _UpdateRecommendationsPanelThread(self):
    273         self.recommendationsInfoPanelUpdater = None
    274         self.UpdatePanel(infoPanelConst.PANEL_RECOMMENDATIONS, False)
    275 
    276     @telemetry.ZONE_FUNCTION
    277     def UpdateAirNpePanel(self, skip_wait = False):
    278         if skip_wait:
    279             if self.airNpeInfoPanelUpdater:
    280                 self.airNpeInfoPanelUpdater.kill()
    281                 self.airNpeInfoPanelUpdater = None
    282             self.UpdatePanel(infoPanelConst.PANEL_AIR_NPE, False)
    283             return
    284         if self.airNpeInfoPanelUpdater:
    285             return
    286         self.airNpeInfoPanelUpdater = uthread2.call_after_wallclocktime_delay(self._UpdateAirNpePanelThread, AIR_NPE_INFO_PANEL_UPDATE_DELAY_SEC)
    287 
    288     def _UpdateAirNpePanelThread(self):
    289         self.airNpeInfoPanelUpdater = None
    290         self.UpdatePanel(infoPanelConst.PANEL_AIR_NPE, False)
    291 
    292     @telemetry.ZONE_FUNCTION
    293     def UpdateFactionalWarfarePanel(self):
    294         self.UpdatePanel(infoPanelConst.PANEL_FACTIONAL_WARFARE)
    295 
    296     @telemetry.ZONE_FUNCTION
    297     def UpdateLocationInfoPanel(self):
    298         self.UpdatePanel(infoPanelConst.PANEL_LOCATION_INFO)
    299 
    300     @telemetry.ZONE_FUNCTION
    301     def UpdateIncursionsPanel(self):
    302         self.UpdatePanel(infoPanelConst.PANEL_INCURSIONS)
    303 
    304     @telemetry.ZONE_FUNCTION
    305     def UpdateDungeonProgressionPanel(self):
    306         self.UpdatePanel(infoPanelConst.PANEL_DUNGEON_PROGRESSION)
    307 
    308     @telemetry.ZONE_FUNCTION
    309     def UpdateChallengesPanel(self):
    310         self.UpdatePanel(infoPanelConst.PANEL_SEASONS)
    311 
    312     def UpdateJobBoardPanel(self):
    313         self.UpdatePanel(infoPanelConst.PANEL_JOB_BOARD)
    314 
    315     def UpdateSkyhookTheftPanel(self):
    316         self.UpdatePanel(infoPanelConst.PANEL_SKYHOOK_THEFT)
    317 
    318     def UpdateWorldEventsPanel(self):
    319         self.UpdatePanel(infoPanelConst.PANEL_WORLD_EVENTS)
    320 
    321     def UpdateAbyssPanel(self):
    322         self.UpdatePanel(infoPanelConst.PANEL_ABYSS)
    323 
    324     def OnOperationMadeActive(self, categoryID, operationID, oldCategoryID, oldOperationID, isSilent):
    325         self.UpdateOperationsPanel(categoryID)
    326 
    327     def OnOperationCompleted(self, categoryID, operationID):
    328         if categoryID != OPERATION_CATEGORY_RECOMMENDATIONS:
    329             self.UpdateOperationsPanel(categoryID)
    330 
    331     def OnOperationReplayed(self, categoryID, operationID):
    332         self.UpdateOperationsPanel(categoryID)
    333 
    334     def OnOperationQuit(self, categoryID, operationID):
    335         self.UpdateOperationsPanel(categoryID)
    336 
    337     def OnOperationTaskTransition(self, categoryID, operationID, taskID, fromState, toState):
    338         if categoryID != OPERATION_CATEGORY_RECOMMENDATIONS:
    339             self.UpdateOperationsPanel(categoryID)
    340 
    341     def OnTutorialSkipped(self):
    342         self.UpdateOperationsPanel()
    343 
    344     def OnOperationDeactivatedUpdate(self):
    345         self.UpdateOperationsPanel()
    346 
    347     def OnChallengeProgressUpdate(self, challengeID, newProgress):
    348         self.UpdateChallengesPanel()
    349 
    350     def OnChallengeCompleted(self, *args):
    351         self.UpdateChallengesPanel()
    352 
    353     def OnInsurgencyCampaignStartedForLocation_Local(self, campaignSnapshot):
    354         self.ReconstructAllPanels()
    355 
    356     def OnInsurgencyCampaignEndingForLocation_Local(self):
    357         self.ReconstructAllPanels()
    358 
    359     def OnInsurgencyCampaignUpdatedForLocation_Local(self, campaignSnapshot):
    360         self.ReconstructAllPanels()
    361 
    362     @telemetry.ZONE_FUNCTION
    363     def UpdatePanel(self, panelTypeID, ignoreViewSettings = True):
    364         if not session.charid:
    365             return
    366         sm.ChainEvent('ProcessUpdateInfoPanel', panelTypeID)
    367         if not self.infoPanelContainer:
    368             return
    369         uthread.Lock(self.infoPanelContainer)
    370         try:
    371             self.infoPanelContainer.UpdatePanel(panelTypeID, ignoreViewSettings)
    372         finally:
    373             uthread.UnLock(self.infoPanelContainer)
    374 
    375     def EnsureSolarSystemIDOrRaise(self, itemID):
    376         if idCheckers.IsStation(itemID):
    377             solar_system_id = cfg.stations.Get(itemID).solarSystemID
    378         elif idCheckers.IsSolarSystem(itemID):
    379             solar_system_id = itemID
    380         else:
    381             structure = sm.GetService('structureDirectory').GetStructureInfo(itemID)
    382             if structure is None:
    383                 raise RuntimeError('Invalid destination')
    384             solar_system_id = structure.solarSystemID
    385         return solar_system_id
    386 
    387     def GetSolarSystemNameAndSecurityStatusDisplayString(self, solar_system_id, altText = None):
    388         if altText:
    389             altText = commonutils.StripTags(altText, stripOnly=['localized'])
    390         solar_system_text = self.GetSolarSystemText(solar_system_id, solarSystemAlt=altText)
    391         return solar_system_text
    392 
    393     def GetSolarSystemConstellationTraceDisplayString(self, solar_system_id, traceFontSize = 12):
    394         solar_system_info = cfg.mapSystemCache.Get(solar_system_id)
    395         constellation_id = solar_system_info.constellationID
    396         region_id = solar_system_info.regionID
    397         if idCheckers.IsWormholeRegion(region_id):
    398             return None
    399         else:
    400             trace = u'{sep}{constellation}'.format(constellation=evelink.location_link(constellation_id), sep=u'{space}<{space}'.format(space=eveformat.font_size(' ', size=8)))
    401             if traceFontSize:
    402                 trace = eveformat.font_size(trace, traceFontSize)
    403             return trace
    404 
    405     def GetSolarSystemRegionTraceDisplayString(self, solar_system_id, traceFontSize = 12):
    406         solar_system_info = cfg.mapSystemCache.Get(solar_system_id)
    407         region_id = solar_system_info.regionID
    408         if idCheckers.IsWormholeRegion(region_id):
    409             return None
    410         else:
    411             trace = u'{sep}{region}'.format(region=evelink.location_link(region_id), sep=u'{space}<{space}'.format(space=eveformat.font_size(' ', size=8)))
    412             if traceFontSize:
    413                 trace = eveformat.font_size(trace, traceFontSize)
    414             return trace
    415 
    416     def GetSolarSystemRegionAndConstellationTraceDisplayString(self, solar_system_id, traceFontSize = 12):
    417         solar_system_info = cfg.mapSystemCache.Get(solar_system_id)
    418         constellation_id = solar_system_info.constellationID
    419         region_id = solar_system_info.regionID
    420         if idCheckers.IsWormholeRegion(region_id):
    421             return None
    422         else:
    423             trace = u'{sep}{constellation}{sep}{region}'.format(constellation=evelink.location_link(constellation_id), region=evelink.location_link(region_id), sep=u'{space}<{space}'.format(space=eveformat.font_size(' ', size=8)))
    424             if traceFontSize:
    425                 trace = eveformat.font_size(trace, traceFontSize)
    426             return trace
    427 
    428     def GetSolarSystemTrace(self, itemID, altText = None, traceFontSize = 12):
    429         solar_system_id = self.EnsureSolarSystemIDOrRaise(itemID)
    430         solar_system_text = self.GetSolarSystemNameAndSecurityStatusDisplayString(solar_system_id, altText=altText)
    431         trace = self.GetSolarSystemRegionAndConstellationTraceDisplayString(solar_system_id, traceFontSize=traceFontSize)
    432         if trace:
    433             return u'{solar_system}{trace}'.format(solar_system=solar_system_text, trace=trace)
    434         else:
    435             return solar_system_text
    436 
    437     def GetLawlessSolarSystemTrace(self, itemID, traceFontSize = 12):
    438         solar_system_id = self.EnsureSolarSystemIDOrRaise(itemID)
    439         solar_system_text = cfg.evelocations.Get(solar_system_id).name
    440         trace = self.GetSolarSystemRegionAndConstellationTraceDisplayString(solar_system_id, traceFontSize=traceFontSize)
    441         if trace:
    442             return u'<b>{solar_system}</b> {lawlessText}<br>{trace}'.format(solar_system=solar_system_text, lawlessText=solar_system_security_status(solar_system_id, lawless=True), trace=trace)
    443         else:
    444             return solar_system_text
    445 
    446     def GetSolarSystemText(self, solarSystemID, solarSystemAlt = None):
    447         try:
    448             return u'{solar_system_name}</b> {security_status}'.format(solar_system_name=evelink.location_link(solarSystemID, hint=solarSystemAlt), security_status=self.GetSecurityStatusText(solarSystemID))
    449         except Exception:
    450             self.LogError('Solar system not found', solarSystemID)
    451             return ''
    452 
    453     def GetSecurityStatusText(self, solarSystemID):
    454         try:
    455             return eveformat.hint(hint=localization.GetByLabel('UI/Map/StarMap/SecurityStatus'), text=eveformat.solar_system_security_status(solarSystemID))
    456         except Exception:
    457             log.LogException()
    458             sys.exc_clear()
    459             return ''
    460 
    461     def OnRecommendationsUpdated(self, *args, **kwargs):
    462         self.UpdatePanel(infoPanelConst.PANEL_RECOMMENDATIONS)
    463 
    464     def OnAirNpeObjectiveUpdated(self, current_goal = None, *args, **kwargs):
    465         if current_goal:
    466             panel = self.GetPanelByTypeID(infoPanelConst.PANEL_AIR_NPE)
    467             if not panel:
    468                 self.SetExpandedMission('air_npe', 0)
    469         self.UpdateAirNpePanel(skip_wait=True)
    470 
    471     def OnCareerProgramTrackingUpdated(self, *args, **kwargs):
    472         self.UpdatePanel(infoPanelConst.PANEL_CAREER_PROGRAM)
    473 
    474     def OnTrackedAchievementChanged(self, achievement_ids):
    475         self.UpdatePanel(infoPanelConst.PANEL_ACHIEVEMENT)
    476 
    477     def OnJobBoardAvailabilityChanged(self, *args, **kwargs):
    478         self.UpdateMissionsPanel()
    479         self.UpdateJobBoardPanel()
    480 
    481     def OnTrackedJobsChanged(self, *args, **kwargs):
    482         self.UpdateJobBoardPanel()
    483 
    484     def GetVisibleJobs(self, job_ids):
    485         panel = self.GetPanelByTypeID(infoPanelConst.PANEL_JOB_BOARD)
    486         if panel:
    487             return panel.get_visible_jobs(job_ids)
    488         return []