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

agentDialogueWindow.py (19751B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\station\agents\agentDialogueWindow.py
      2 import logging
      3 import blue
      4 import telemetry
      5 import carbonui.const as uiconst
      6 import localization
      7 from carbon.common.script.util.format import FmtTimeInterval
      8 from carbonui.control.window import Window
      9 from carbonui.primitives.container import Container
     10 from eve.client.script.ui.control import eveEdit
     11 from carbonui.button.group import ButtonGroup
     12 from eve.client.script.ui.control.eveLoadingWheel import LoadingWheel
     13 from eve.client.script.ui.eveColor import SUCCESS_GREEN_HEX
     14 from eve.client.script.ui.station.agents import agentDialogueUtil
     15 from eve.client.script.ui.station.agents.agentConst import LABEL_BY_BUTTON_TYPE
     16 from eve.client.script.ui.station.agents.agentDialogueUtil import GetAgentNameAndLevel
     17 from eve.common.lib import appConst
     18 from gametime import MIN
     19 from random import choice
     20 from jobboard.client import get_agent_mission_job
     21 from jobboard.client.ui.track_button import TrackJobButton
     22 from localization import GetByLabel
     23 SINGLE_PANE_VIEW = 'SinglePaneView'
     24 DOUBLE_PANE_VIEW = 'DoublePaneView'
     25 MIN_HEIGHT = 545
     26 MIN_WIDTH = 835
     27 logger = logging.getLogger(__name__)
     28 
     29 class AgentDialogueWindow(Window):
     30     __guid__ = 'form.AgentDialogueWindow'
     31     __notifyevents__ = ['OnSessionChanged', 'OnAgentMissionChange']
     32     default_width = 900
     33     default_height = 650
     34     default_minSize = (MIN_WIDTH, MIN_HEIGHT)
     35     default_windowID = 'AgentDialogueWindow'
     36     default_iconNum = 'res:/ui/Texture/WindowIcons/agent.png'
     37 
     38     def ApplyAttributes(self, attributes):
     39         Window.ApplyAttributes(self, attributes)
     40         self.isLoading = False
     41         self.objectiveHtml = None
     42         self.briefingHtml = None
     43         self.viewMode = None
     44         self.leftPane = None
     45         self.rightPane = None
     46         self.agentID = None
     47         self.agentDivisionID = None
     48         self.SetAgentID(attributes.agentID)
     49         self.buttonGroup = ButtonGroup(parent=self.content, align=uiconst.TOBOTTOM)
     50         self.mainCont = Container(name='mainCont', parent=self.content, padBottom=16)
     51         self.loadingWheel = LoadingWheel(parent=self, align=uiconst.CENTER, state=uiconst.UI_HIDDEN, idx=0)
     52 
     53     def ConstructBrowsers(self):
     54         self.briefingBrowser = eveEdit.Edit(name='briefing_browser', parent=self.leftPane, readonly=1)
     55         self.briefingBrowser.sr.window = self
     56         self.objectiveBrowser = eveEdit.Edit(name='objective_browser', parent=self.rightPane, readonly=1)
     57         self.objectiveBrowser.sr.window = self
     58 
     59     def SetAgentID(self, agentID):
     60         if agentID is not None:
     61             agentInfo = sm.GetService('agents').GetAgentByID(agentID)
     62             agentNameAndLevel = GetAgentNameAndLevel(agentID, agentInfo.level)
     63             self.SetCaption(localization.GetByLabel('UI/Agents/Dialogue/AgentConversationWith', agentNameAndLevel=agentNameAndLevel))
     64             self.agentDivisionID = agentInfo.divisionID
     65         self.agentID = agentID
     66 
     67     def GetAgentID(self):
     68         return self.agentID
     69 
     70     def GetAgentMoniker(self):
     71         return sm.GetService('agents').GetAgentMoniker(self.GetAgentID())
     72 
     73     def OnSessionChanged(self, isRemote, sess, change):
     74         if not self.destroyed:
     75             self.briefingBrowser.SessionChanged()
     76             self.objectiveBrowser.SessionChanged()
     77         if 'stationid' in change:
     78             self.InteractWithAgent()
     79 
     80     def OnAgentMissionChange(self, action, agentID):
     81         if not self.destroyed:
     82             if action == appConst.agentMissionModified and self.agentID == agentID:
     83                 self.InteractWithAgent()
     84 
     85     def DisableButtons(self):
     86         for button in self.buttonGroup.buttons:
     87             button.Disable()
     88 
     89     def SetBriefingHTML(self, html):
     90         self.briefingHtml = html
     91 
     92     def SetObjectiveHTML(self, html):
     93         self.objectiveHtml = html
     94 
     95     def LoadBriefingBrowserHTML(self, html, hideBackground = 0, newThread = 1):
     96         if self.destroyed:
     97             return
     98         if not self.viewMode:
     99             self.SetSinglePaneView()
    100         if not self.briefingBrowser:
    101             return
    102         self.ShowLoad()
    103         self.briefingHtml = html
    104         self.briefingBrowser.sr.hideBackground = hideBackground
    105         while self.briefingBrowser.IsLoading():
    106             blue.pyos.synchro.Yield()
    107 
    108         self.briefingBrowser.LoadHTML(html, newThread=newThread)
    109 
    110     def LoadObjectiveBrowserHTML(self, html, hideBackground = 0, newThread = 1):
    111         if self.destroyed:
    112             return
    113         if not self.viewMode:
    114             self.SetDoublePaneView()
    115         if not self.objectiveBrowser:
    116             return
    117         self.ShowLoad()
    118         self.objectiveHtml = html
    119         self.objectiveBrowser.sr.hideBackground = hideBackground
    120         while self.objectiveBrowser.IsLoading():
    121             blue.pyos.synchro.Yield()
    122 
    123         self.objectiveBrowser.LoadHTML(html, newThread=newThread)
    124 
    125     @telemetry.ZONE_METHOD
    126     def SetSinglePaneView(self, briefingHtml = None):
    127         if self.viewMode != SINGLE_PANE_VIEW:
    128             self._ReconstructSinglePane()
    129         if briefingHtml:
    130             self.SetBriefingHTML(briefingHtml)
    131             self.LoadBriefingBrowserHTML(self.briefingHtml)
    132 
    133     def _ReconstructSinglePane(self):
    134         self.viewMode = SINGLE_PANE_VIEW
    135         self.LockWidth(MIN_WIDTH / 2)
    136         self.mainCont.Flush()
    137         self.leftPane = Container(name='leftPane', parent=self.mainCont, align=uiconst.TOALL)
    138         self.ConstructBrowsers()
    139 
    140     @telemetry.ZONE_METHOD
    141     def SetDoublePaneView(self, briefingHtml = None, objectiveHtml = None):
    142         if self.viewMode != DOUBLE_PANE_VIEW:
    143             self._ReconstructDoublePane()
    144         if briefingHtml:
    145             self.SetBriefingHTML(briefingHtml)
    146             self.LoadBriefingBrowserHTML(briefingHtml)
    147         if objectiveHtml:
    148             self.SetObjectiveHTML(objectiveHtml)
    149             self.LoadObjectiveBrowserHTML(objectiveHtml)
    150 
    151     def _ReconstructDoublePane(self):
    152         self.viewMode = DOUBLE_PANE_VIEW
    153         self.SetFixedWidth(None)
    154         self.SetMinSize((MIN_WIDTH, MIN_HEIGHT))
    155         self.mainCont.Flush()
    156         self.leftPane = Container(name='leftPane', parent=self.mainCont, align=uiconst.TOLEFT_PROP, width=0.5, padRight=8)
    157         self.rightPane = Container(name='rightPane', parent=self.mainCont, align=uiconst.TOALL, padLeft=8)
    158         self.ConstructBrowsers()
    159 
    160     def RefreshBrowsers(self):
    161         self.briefingBrowser.UpdatePosition(fromWhere='AgentDialogueWindow.RefreshBrowsers')
    162         self.objectiveBrowser.UpdatePosition(fromWhere='AgentDialogueWindow.RefreshBrowsers')
    163 
    164     @telemetry.ZONE_METHOD
    165     def InteractWithAgent(self, actionID = None):
    166         if self.isLoading:
    167             return
    168         self.isLoading = True
    169         try:
    170             self._StartLoading(actionID)
    171             agentSaysText, actions, lastActionInfo = self._GetConversation(actionID)
    172             if self.destroyed or agentSaysText is None:
    173                 return
    174             self.ReconstructLayout(actions, agentSaysText, lastActionInfo)
    175         finally:
    176             self._StopLoading()
    177 
    178     def _StartLoading(self, actionID):
    179         if actionID:
    180             self.DisableButtons()
    181         self.loadingWheel.Show()
    182 
    183     def _StopLoading(self):
    184         self.isLoading = False
    185         self.loadingWheel.Hide()
    186 
    187     def ReconstructLayout(self, actions, agentSaysText, lastActionInfo):
    188         actions = actions or []
    189         briefingHTML = self.GetBriefingHTML(actions, agentSaysText, lastActionInfo)
    190         objectiveHtml = self.GetObjectiveHTML(lastActionInfo)
    191         if objectiveHtml or lastActionInfo.get('missionCompleted'):
    192             self.SetDoublePaneView(briefingHtml=briefingHTML, objectiveHtml=objectiveHtml)
    193         else:
    194             self.SetSinglePaneView(briefingHtml=briefingHTML)
    195         self.ReconstructButtons(actions, lastActionInfo)
    196 
    197     def GetObjectiveHTML(self, lastActionInfo):
    198         objectiveData = self.GetAgentMoniker().GetMissionObjectiveInfo()
    199         if objectiveData and not (lastActionInfo['missionCompleted'] or lastActionInfo['missionDeclined'] or lastActionInfo['missionQuit'] or lastActionInfo['missionCantReplay']):
    200             return self._GetObjectiveHTML(objectiveData)
    201         else:
    202             return None
    203 
    204     def _GetObjectiveHTML(self, objectiveData):
    205         return '\n                <html>\n                <head>\n                    <link rel="stylesheet" type="text/css" href="res:/ui/css/missionobjectives.css">\n                </head>\n                <body>\n                %s\n                </body>\n                </html>\n            ' % agentDialogueUtil.GetMissionObjectiveHTML(self.GetAgentID(), objectiveData)
    206 
    207     def GetBriefingHTML(self, actions, agentSaysText, lastActionInfo):
    208         agentHeader = self.GetAgentHeader(lastActionInfo)
    209         briefingData = sm.GetService('agents').GetMissionBriefingInfo(self.GetAgentID())
    210         missionTitle = self._GetMissionTitleHTML(briefingData) if briefingData else ''
    211         replayTimer = ''
    212         timeLeft = lastActionInfo.get('missionCantReplay', None)
    213         if timeLeft:
    214             agentSaysText = self._GetNoMissionMessage(timeLeft)
    215             replayTimer = localization.GetByLabel('UI/Agents/DefaultMessages/MissionCantReplay', timeLeft=FmtTimeInterval(timeLeft, breakAt='min' if timeLeft > MIN else 'sec'), timerColor=SUCCESS_GREEN_HEX)
    216             replayTimer = '<br>' + replayTimer
    217             replayTimer = replayTimer.replace('<color=', '<font color=')
    218             replayTimer = replayTimer.replace('</color>', '</font>')
    219             extraMissionInfoHTML = None
    220         else:
    221             specialInteractionActions = [ (actionID, actionData) for actionID, actionData in actions if type(actionData) == dict ]
    222             extraMissionInfoHTML = self.GetExtraMissionInfoHTML(specialInteractionActions, briefingData)
    223         adminHTML = self.GetAdminHTML(actions)
    224         return self._GetBriefingHTML(agentHeader, missionTitle, agentSaysText, replayTimer, extraMissionInfoHTML, adminHTML)
    225 
    226     def _GetNoMissionMessage(self, timeLeft):
    227         if self.agentDivisionID and self.agentDivisionID == appConst.corpDivisionHeraldry:
    228             if timeLeft:
    229                 label = 'UI/Agents/DefaultMessages/NoMissionHeraldryTimer'
    230             else:
    231                 label = 'UI/Agents/DefaultMessages/NoMissionHeraldry'
    232         else:
    233             label = choice(['UI/Agents/DefaultMessages/NoMission1', 'UI/Agents/DefaultMessages/NoMission2'])
    234         return localization.GetByLabel(label)
    235 
    236     def _GetBriefingHTML(self, agentHeader, missionTitle, agentSaysText, replayTimer, extraMissionInfoHTML, adminHTML):
    237         body = ''
    238         for item in [agentHeader,
    239          missionTitle,
    240          agentSaysText,
    241          replayTimer,
    242          extraMissionInfoHTML,
    243          adminHTML]:
    244             if item:
    245                 if body:
    246                     body += '<br>'
    247                 body += unicode(item)
    248 
    249         return '\n                <html>\n                <head>\n                    <link rel="stylesheet" type="text/css" href="res:/ui/css/agentconvo.css">\n                </head>\n                    <body background-color=#00000000 link=#ffa800>\n                        %s\n                    </body>\n                </html>\n            ' % body
    250 
    251     def GetAgentHeader(self, lastActionInfo):
    252         lp = lastActionInfo.get('loyaltyPoints', 0)
    253         agentLocationWrap = self.GetAgentMoniker().GetAgentLocationWrap()
    254         agent = sm.GetService('agents').GetAgentByID(self.GetAgentID())
    255         agentHeader = agentDialogueUtil.GetAgentLocationHeader(agent, agentLocationWrap, lp)
    256         return agentHeader
    257 
    258     def GetExtraMissionInfoHTML(self, specialInteractionActions, briefingInformation):
    259         extraMissionInfo = ''
    260         if specialInteractionActions:
    261             extraMissionInfo += self.GetSpecialInteractionHTML(specialInteractionActions)
    262         elif briefingInformation:
    263             extraMissionInfo += self.GetMissionTimeHTML(briefingInformation)
    264             extraMissionInfo += '<br><center>%s</center>' % briefingInformation[appConst.agentMissionBriefingImage]
    265         return extraMissionInfo
    266 
    267     def GetMissionTimeHTML(self, briefingInformation):
    268         missionTimeText = self.GetMissionTimeText(briefingInformation)
    269         if missionTimeText:
    270             return '<br>%s' % missionTimeText
    271         else:
    272             return ''
    273 
    274     def GetSpecialInteractionHTML(self, specialInteractionActions):
    275         specialInteractionHTML = ''
    276         for actionID, briefingData in specialInteractionActions:
    277             sm.GetService('agents').PrimeMessageArguments(self.GetAgentID(), briefingData[appConst.agentMissionBriefingMissionID], briefingData[appConst.agentMissionBriefingKeywords])
    278             message = (briefingData[appConst.agentMissionBriefingTitleID], briefingData[appConst.agentMissionBriefingMissionID])
    279             missionTitle = self.GetMessageText(message)
    280             specialInteractionHTML += '\n                    <span id=subheader><a href="localsvc:method=AgentDoAction&agentID=%d&actionID=%d">%s</a> &gt;&gt;</span><br>\n                ' % (self.GetAgentID(), actionID, missionTitle)
    281             if briefingData[appConst.agentMissionBriefingBriefingID] is not None:
    282                 if isinstance(briefingData[appConst.agentMissionBriefingBriefingID], basestring) or briefingData[appConst.agentMissionBriefingBriefingID] > 0:
    283                     message = (briefingData[appConst.agentMissionBriefingBriefingID], briefingData[appConst.agentMissionBriefingMissionID])
    284                     briefingText = self.GetMessageText(message)
    285                 else:
    286                     briefingText = localization.GetByLabel('UI/Agents/Dialogue/StandardMission/CorruptBriefing')
    287                 specialInteractionHTML += '\n                        <div id=basetext>%s</div>\n                        <br>\n                    ' % briefingText
    288 
    289         return specialInteractionHTML
    290 
    291     def _GetMissionTitleHTML(self, briefingData):
    292         message = (briefingData[appConst.agentMissionBriefingTitleID], briefingData[appConst.agentMissionBriefingMissionID])
    293         missionTitle = self.GetMessageText(message)
    294         return '<br><span id=subheader>%s</span><br>' % missionTitle
    295 
    296     def GetMessageText(self, message):
    297         return sm.GetService('agents').ProcessMessage(message, self.GetAgentID())
    298 
    299     def GetMissionTimeText(self, briefingInformation):
    300         if briefingInformation[appConst.agentMissionBriefingDeclineTime] is not None:
    301             if briefingInformation[appConst.agentMissionBriefingDeclineTime] == -1:
    302                 return localization.GetByLabel('UI/Agents/StandardMission/DeclineMessageGeneric')
    303             else:
    304                 timeRemaining = briefingInformation[appConst.agentMissionBriefingDeclineTime]
    305                 timeBreakAt = 'min' if timeRemaining > appConst.MIN else 'sec'
    306                 return localization.GetByLabel('UI/Agents/StandardMission/DeclineMessageTimeLeft', timeRemaining=FmtTimeInterval(timeRemaining, breakAt=timeBreakAt))
    307         elif briefingInformation[appConst.agentMissionBriefingExpirationTime] is not None:
    308             return localization.GetByLabel('UI/Agents/Dialogue/ThisMissionExpiresAt', expireTime=briefingInformation[appConst.agentMissionBriefingExpirationTime])
    309 
    310     def ReconstructButtons(self, actions, lastActionInfo):
    311         self.buttonGroup.FlushButtons()
    312         cantReplay = lastActionInfo.get('missionCantReplay', None)
    313         if not cantReplay:
    314             for actionID, actionData in actions:
    315                 if type(actionData) is int:
    316                     label, func, kwargs = self._GetActionButtonData(actionData, actionID)
    317                     self.buttonGroup.AddButton(label, func, **kwargs)
    318 
    319         appendCloseButton = not self.buttonGroup.buttons or any((self._IsCloseButtonAction(actionData) for actionID, actionData in actions))
    320         if appendCloseButton and len(self.buttonGroup.buttons) < 3:
    321             self.buttonGroup.AddButton(localization.GetByLabel('UI/Common/Buttons/Close'), self.CloseByUser, uiName='CloseAgentConversation_Button')
    322         job = get_agent_mission_job(self.agentID, wait=False)
    323         if job:
    324             TrackJobButton(parent=self.buttonGroup, job=job)
    325         self.buttonGroup.state = uiconst.UI_PICKCHILDREN
    326 
    327     def GetAdminHTML(self, actions):
    328         adminHTML = ''
    329         adminOptions = self._GetAdminOptions(actions)
    330         if adminOptions:
    331             if len(adminOptions) == 1:
    332                 adminHTML = '<br>'
    333                 adminHTML += adminOptions[0]
    334             else:
    335                 adminHTML = '<ol>'
    336                 adminHTML += ''.join([ '<br><li>%s</li>' % x for x in adminOptions ])
    337                 adminHTML += '</ol>'
    338         return adminHTML
    339 
    340     def _GetAdminOptions(self, actions):
    341         adminOptions = []
    342         for actionID, actionData in actions:
    343             if type(actionData) in (str, unicode):
    344                 adminOptions.append('<a href="localsvc:method=AgentDoAction&agentID=%d&actionID=%d">%s</a>' % (self.GetAgentID(), actionID, actionData))
    345 
    346         return adminOptions
    347 
    348     def _GetActionButtonData(self, actionData, actionID):
    349         labelPath = LABEL_BY_BUTTON_TYPE.get(actionData, None)
    350         if labelPath:
    351             label = localization.GetByLabel(labelPath)
    352         else:
    353             logger.error('Unknown button ID for agent action, id =', actionData)
    354             label = 'Unknown ID ' + str(actionData)
    355         btnData = (label, sm.GetService('agents').DoAction, {'args': (self.GetAgentID(), actionID),
    356           'uiName': u'{}_Button'.format(labelPath.split('/')[-1])})
    357         return btnData
    358 
    359     def _IsCloseButtonAction(self, actionData):
    360         return actionData in (appConst.agentDialogueButtonRequestMission,
    361          appConst.agentDialogueButtonContinue,
    362          appConst.agentDialogueButtonQuit,
    363          appConst.agentDialogueButtonCancelResearch)
    364 
    365     def _GetConversation(self, actionID):
    366         (agentSaysMsg, availableActions), lastActionInfo = self.ExecuteAgentAction(actionID)
    367         if actionID is None and len(availableActions):
    368             firstAction = availableActions[0]
    369             firstActionID, firstActionMsg = firstAction
    370             if firstActionMsg in (appConst.agentDialogueButtonRequestMission, appConst.agentDialogueButtonViewMission) and (len(availableActions) == 1 or not self._IsLocatorAgent(availableActions) and not self._IsResearchAgent()):
    371                 (agentSaysMsg, availableActions), lastActionInfo = self.ExecuteAgentAction(firstActionID)
    372         agentSaysText = self.GetMessageText(agentSaysMsg)
    373         return (agentSaysText, availableActions, lastActionInfo)
    374 
    375     def _IsResearchAgent(self):
    376         isResearchAgent = False
    377         if sm.GetService('agents').GetAgentByID(self.GetAgentID()).agentTypeID == appConst.agentTypeResearchAgent:
    378             isResearchAgent = True
    379         return isResearchAgent
    380 
    381     def _IsLocatorAgent(self, availableActions):
    382         agentHasLocatorService = False
    383         for id, dlg in availableActions:
    384             if dlg == appConst.agentDialogueButtonLocateCharacter:
    385                 agentHasLocatorService = True
    386 
    387         return agentHasLocatorService
    388 
    389     def ExecuteAgentAction(self, actionID):
    390         return self.GetAgentMoniker().DoAction(actionID)
    391 
    392     def ShowMissionObjectives(self, contentID):
    393         objectiveData = self.GetAgentMoniker().GetMissionObjectiveInfo(session.charid, contentID)
    394         if not self.destroyed:
    395             if objectiveData:
    396                 objectiveHtml = self._GetObjectiveHTML(objectiveData)
    397                 self.SetDoublePaneView(objectiveHtml=objectiveHtml)
    398             else:
    399                 self.SetSinglePaneView()