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

dungeonTracking.py (12129B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\parklife\dungeonTracking.py
      2 import localization
      3 import signals
      4 from carbon.common.script.sys.service import Service
      5 from eve.client.script.parklife import dungeon_signals
      6 from eve.common.script.sys.rowset import Rowset
      7 from eve.common.script.sys.eveCfg import IsDocked
      8 from evedungeons.client.anomalyTracker import CombatAnomalyTracker, FactionalWarfareSiteTracker, HomefrontOperationTracker, IceBeltTracker, OreAnomalyTracker, PirateInsurgencySiteTracker, TriglavianSiteTracker, BulwarkMiningSitesTracker
      9 from evedungeons.client.data import GetDungeon, GetDungeonObjectivesData
     10 from logging import getLogger
     11 from nodegraph.common.nodedata import is_client_graph
     12 from objectives.client.objective_chain import ObjectiveChain
     13 from objectives.common.objective_context import ObjectivesContext, get_authored_parameter_values_as_dict
     14 logger = getLogger(__name__)
     15 
     16 def GetDungeonTrackingService():
     17     return sm.GetService('dungeonTracking')
     18 
     19 
     20 class DungeonTracking(Service):
     21     __guid__ = 'svc.dungeonTracking'
     22     __notifyevents__ = ['ProcessSessionChange',
     23      'OnCharacterSessionChanged',
     24      'OnDistributionDungeonEntered',
     25      'OnEscalatingPathDungeonEntered',
     26      'OnEnteringDungeonRoom',
     27      'OnExitingDungeon',
     28      'OnDungeonMessage',
     29      'OnDungeonValues',
     30      'OnDungeonCompleted']
     31 
     32     def __init__(self):
     33         super(DungeonTracking, self).__init__()
     34         self.distributionDungeonsEntered = None
     35         self.escalatingPathDungeonsEntered = None
     36         self.trackers = {'combat_anomalies': CombatAnomalyTracker(),
     37          'factional_warfare': FactionalWarfareSiteTracker(),
     38          'homefront_operations': HomefrontOperationTracker(),
     39          'ice_belts': IceBeltTracker(),
     40          'ore_anomalies': OreAnomalyTracker(),
     41          'pirate_insurgency': PirateInsurgencySiteTracker(),
     42          'triglavian': TriglavianSiteTracker(),
     43          'bulwark_mining_sites': BulwarkMiningSitesTracker()}
     44         self.current_dungeon = None
     45 
     46     def Run(self, memStream = None):
     47         super(DungeonTracking, self).Run(memStream)
     48         for tracker in self.trackers.values():
     49             tracker.initialize()
     50 
     51     def ProcessSessionChange(self, isRemote, session, change):
     52         if 'locationid' in change:
     53             self.distributionDungeonsEntered = None
     54             self.escalatingPathDungeonsEntered = None
     55             self._clear_dungeon()
     56 
     57     def OnCharacterSessionChanged(self, oldCharacterID, newCharacterID):
     58         if not newCharacterID or IsDocked():
     59             return
     60         dungeon_info = sm.RemoteSvc('keeper').GetCurrentDungeonForCharacter()
     61         if dungeon_info:
     62             dungeon_id, room_id, instance_id, dungeon_values = dungeon_info
     63             self.OnEnteringDungeonRoom(dungeon_id=dungeon_id, room_id=room_id, room_position=None, instance_id=instance_id, dungeon_values=dungeon_values)
     64 
     65     def OnDistributionDungeonEntered(self, row):
     66         if self.distributionDungeonsEntered is None:
     67             self.distributionDungeonsEntered = Rowset(row.header)
     68         self.distributionDungeonsEntered.append(row)
     69 
     70     def OnEscalatingPathDungeonEntered(self, row):
     71         if self.escalatingPathDungeonsEntered is None:
     72             self.escalatingPathDungeonsEntered = Rowset(row.header)
     73         if getattr(row, 'dungeonNameID', None):
     74             row.name = localization.GetByMessageID(row.dungeonNameID)
     75         self.escalatingPathDungeonsEntered.append(row)
     76 
     77     def GetDistributionDungeonsEntered(self):
     78         return self.distributionDungeonsEntered
     79 
     80     def GetEscalatingPathDungeonsEntered(self):
     81         return self.escalatingPathDungeonsEntered
     82 
     83     def GetCurrentDungeonID(self):
     84         if self.current_dungeon:
     85             return self.current_dungeon.dungeon_id
     86         else:
     87             return None
     88 
     89     def get_current_dungeon(self):
     90         return self.current_dungeon
     91 
     92     def OnEnteringDungeonRoom(self, dungeon_id, room_id, room_position, instance_id, dungeon_values):
     93         if not self.current_dungeon or self.current_dungeon.dungeon_id != dungeon_id:
     94             logger.info('Dungeon Entered - dungeon_id: %s - room_id: %s - instance_id: %s - values: %s', dungeon_id, room_id, instance_id, dungeon_values)
     95             self.current_dungeon = ActiveDungeon(dungeon_id, room_id, instance_id, dungeon_values)
     96             self.current_dungeon.start()
     97             sm.ScatterEvent('OnDungeonEntered', dungeon_id, instance_id)
     98             dungeon_signals.on_dungeon_room_entered(dungeon_id, room_id, instance_id)
     99         else:
    100             self.current_dungeon.room_id = room_id
    101 
    102     def OnExitingDungeon(self, dungeon_id):
    103         self._clear_dungeon(dungeon_id)
    104 
    105     def OnDungeonMessage(self, dungeon_id, message_key, message_value):
    106         if self.current_dungeon and self.current_dungeon.dungeon_id == dungeon_id:
    107             self.current_dungeon.message(message_key, message_value)
    108 
    109     def OnDungeonValues(self, dungeon_id, values):
    110         logger.info('Dungeon Values received - current_dungeon_id: %s - dungeon_id: %s - values: %s', self.GetCurrentDungeonID(), dungeon_id, values)
    111         if self.current_dungeon and self.current_dungeon.dungeon_id == dungeon_id:
    112             self.current_dungeon.update_dungeon_values(values)
    113             for key, value in values.iteritems():
    114                 self.current_dungeon.update_context_value(key, value)
    115 
    116     def OnDungeonCompleted(self, dungeon_id):
    117         if self.current_dungeon and self.current_dungeon.dungeon_id == dungeon_id:
    118             self.current_dungeon.update_context_value('dungeon_completed', True)
    119 
    120     def _clear_dungeon(self, dungeon_id = None):
    121         if not self.current_dungeon:
    122             return
    123         if not dungeon_id or self.current_dungeon.dungeon_id == dungeon_id:
    124             instance_id = self.current_dungeon.instance_id
    125             self.current_dungeon.stop()
    126             self.current_dungeon = None
    127             sm.ScatterEvent('OnDungeonExited', dungeon_id, instance_id)
    128 
    129     def get_tracker(self, tracker_id):
    130         return self.trackers[tracker_id]
    131 
    132 
    133 class ActiveDungeon(object):
    134 
    135     def __init__(self, dungeon_id, room_id, instance_id, dungeon_values):
    136         self._context = ObjectivesContext()
    137         self._context.set_values(dungeon_id=dungeon_id, dungeon_room_id=room_id)
    138         self.update_dungeon_values(dungeon_values or {})
    139         self._mission = None
    140         self._node_graph = None
    141         self._objective_chain = None
    142         self._instance_id = instance_id
    143         self.on_room_changed = signals.Signal('on_room_changed')
    144 
    145     def message(self, key, value):
    146         if not key.startswith('dungeon_'):
    147             key = u'dungeon_{}'.format(key)
    148         self._context.send_message(key, value=value)
    149 
    150     def update_dungeon_values(self, values):
    151         for key, value in values.iteritems():
    152             keys = key.split('.')
    153             self._context.update_value(keys[0], value, object_path=keys[1:])
    154 
    155     def update_context_value(self, key, value):
    156         self._context.update_value(key, value)
    157 
    158     @property
    159     def objective_chain(self):
    160         return self._objective_chain
    161 
    162     @property
    163     def dungeon_id(self):
    164         return self._context.get_value('dungeon_id')
    165 
    166     @property
    167     def instance_id(self):
    168         return self._instance_id
    169 
    170     @property
    171     def room_id(self):
    172         return self._context.get_value('dungeon_room_id')
    173 
    174     @room_id.setter
    175     def room_id(self, value):
    176         if self.room_id == value:
    177             return
    178         self.update_context_value('dungeon_room_id', value)
    179         self.on_room_changed()
    180 
    181     @property
    182     def data(self):
    183         return GetDungeon(self.dungeon_id)
    184 
    185     @property
    186     def title(self):
    187         return localization.GetByMessageID(self.data.dungeonNameID)
    188 
    189     @property
    190     def description(self):
    191         return localization.GetByMessageID(self.data.descriptionID)
    192 
    193     @property
    194     def archetype_id(self):
    195         return self.data.archetypeID
    196 
    197     @property
    198     def faction_id(self):
    199         return self.data.factionID
    200 
    201     @property
    202     def difficulty(self):
    203         return self.data.factionID
    204 
    205     @property
    206     def mission_briefing_id(self):
    207         return self.data.missionBriefingID
    208 
    209     @property
    210     def entry_type_id(self):
    211         return self.data.entryTypeID
    212 
    213     @property
    214     def standing_restrictions(self):
    215         return self.data.standingRestrictions
    216 
    217     @property
    218     def objectives_data(self):
    219         return GetDungeonObjectivesData(self.dungeon_id)
    220 
    221     def start(self):
    222         sm.RegisterForNotifyEvent(self, 'OnExpandedMissionChanged')
    223         self.OnExpandedMissionChanged(**sm.GetService('infoPanel').GetExpandedMission())
    224         dungeon_objectives = self.objectives_data
    225         if dungeon_objectives:
    226             self._context.set_values(**get_authored_parameter_values_as_dict(dungeon_objectives.blackboardParameters))
    227             self._start_objective_chain(dungeon_objectives.objectiveChainID, dungeon_objectives.overrides)
    228             self._start_node_graph(dungeon_objectives.nodeGraphID)
    229 
    230     def stop(self):
    231         sm.UnregisterForNotifyEvent(self, 'OnExpandedMissionChanged')
    232         self.update_context_value('dungeon_room_id', None)
    233         self._stop_node_graph()
    234         if self._mission:
    235             self._mission = None
    236         if self._objective_chain:
    237             self._objective_chain.stop()
    238             self._objective_chain = None
    239         self._context.clear()
    240 
    241     def _start_objective_chain(self, objective_chain_id, overrides):
    242         if not objective_chain_id:
    243             return
    244         self._objective_chain = ObjectiveChain(content_id=objective_chain_id, context=self._context, overrides=overrides)
    245         self._objective_chain.start()
    246 
    247     def _start_node_graph(self, node_graph_id):
    248         if not node_graph_id or self._node_graph:
    249             return
    250         if is_client_graph(node_graph_id):
    251             self._node_graph = sm.GetService('node_graph').start_node_graph(node_graph_id=node_graph_id, context=self._context)
    252 
    253     def get_context_menu(self):
    254         from carbonui.control.contextMenu.menuData import MenuData
    255         from objectives.client.qa_tools import is_qa, key_value_entry
    256         data = MenuData()
    257         if not is_qa():
    258             return data
    259         result = MenuData()
    260         dungeon_objectives_id = GetDungeon(self.dungeon_id).objectivesID
    261         if dungeon_objectives_id:
    262             result.AddEntry(text='Open Dungeon Objectives in FSD Editor', func=lambda : _open_fsd_dungeon_objectives(dungeon_objectives_id))
    263         if self._node_graph:
    264             result.AddEntry(text='Open Dungeon Node Graph', func=lambda : _open_active_node_graph(self._node_graph.instance_id))
    265         result.AddSeparator()
    266         if self.objective_chain:
    267             result.entrylist.extend(self.objective_chain.get_context_menu())
    268         result.entrylist.append(key_value_entry('Blackboard Values', self._context.values, self._context))
    269         data.AddEntry('QA', subMenuData=result)
    270         return data
    271 
    272     def OnExpandedMissionChanged(self, featureID = None, missionID = None):
    273         is_focused = False
    274         if featureID == 'opportunities' and missionID and missionID != -1:
    275             provider_id, instance_id = missionID.split(':')
    276             if instance_id == str(self.instance_id) and _is_dungeon_provider(provider_id):
    277                 is_focused = True
    278         self._context.update_value('mission_focused', is_focused)
    279 
    280     def _stop_node_graph(self):
    281         if self._node_graph:
    282             sm.GetService('node_graph').stop_node_graph(self._node_graph.instance_id)
    283             self._node_graph = None
    284 
    285 
    286 def _is_dungeon_provider(provider_id):
    287     from jobboard.client.provider_type import DUNGEON_PROVIDERS
    288     return provider_id in DUNGEON_PROVIDERS
    289 
    290 
    291 def _open_fsd_dungeon_objectives(content_id):
    292     import webbrowser
    293     webbrowser.open_new('http://localhost:8000/dungeons/dungeon_objectives/{}/'.format(content_id))
    294 
    295 
    296 def _open_active_node_graph(node_graph_instance_id):
    297     from nodegraph.client.ui.window import NodeGraphEditorWindow
    298     NodeGraphEditorWindow.Open(node_graph_id=node_graph_instance_id)