missionObjectivesTracker.py (12909B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\missions\client\missionObjectivesTracker.py 2 from carbon.common.script.sys.service import Service 3 from carbonui.util.bunch import Bunch 4 from carbonui.util.sortUtil import SortListOfTuples 5 from collections import defaultdict 6 from eveexceptions.exceptionEater import ExceptionEater 7 from eve.common.lib.appConst import agentMissionStateAccepted, agentMissionAccepted, agentMissionQuit, agentMissionModified 8 from eve.common.script.sys import idCheckers 9 from gametime import GetWallclockTime 10 import inventorycommon.const as const 11 from .ui.missionObjectiveData import CreateObjective 12 from .active_agent_mission import ActiveAgentMission 13 AGENT_FOR_LAST_ACCEPTED_MISSION_SETTING = 'AgentForLastAcceptedMission' 14 DELAY_ON_DUNGEON_TRIGGER_SECS = 1.0 15 MISSION_UPDATE_DELAY_MSEC = 3000 16 17 class MissionObjectivesTracker(Service): 18 __guid__ = 'svc.missionObjectivesTracker' 19 __notifyevents__ = ['OnItemsChanged', 20 'OnMissionsUpdated', 21 'OnAgentMissionChanged', 22 'OnAgentMissionObjectivesCompleted', 23 'OnAgentMissionObjectivesFailed', 24 'OnClientEvent_WarpFinished', 25 'OnSessionChanged', 26 'OnSessionReset', 27 'OnBallparkSetState'] 28 __startupdependencies__ = ['journal'] 29 30 def Run(self, *args): 31 super(MissionObjectivesTracker, self).Run(*args) 32 self.Initialize() 33 34 def Initialize(self): 35 self.agentList = [] 36 self.agentMissions = {} 37 self.waitingForTypeIDs = defaultdict(lambda : []) 38 self.agentsWaitingForStuff = {} 39 self.destinationTriggers = defaultdict(lambda : []) 40 self.currentAgentMissionInfo = None 41 self.missionObjectives = defaultdict(lambda : None) 42 self.missionTrackerMgr = sm.RemoteSvc('missionTrackerMgr') 43 44 def GetAgentMissions(self, *args): 45 allMissionsList = [] 46 missions = self.journal.GetMyAgentJournalDetails()[0] 47 HOMEBASE = 0 48 NOTHOMEBASE = 1 49 if missions: 50 for mission in missions: 51 missionState, _, _, missionNameID, agentID, expirationTime, bookmarks, _, _, contentID = mission 52 if missionState != agentMissionStateAccepted or expirationTime and expirationTime < GetWallclockTime(): 53 continue 54 homeBaseBms = [] 55 otherBms = [] 56 foundHomeBaseBm = False 57 for bm in bookmarks: 58 if bm.locationType == 'agenthomebase': 59 homeBaseBms.append((HOMEBASE, bm)) 60 elif 'isAgentBase' in bm.__dict__ and bm.isAgentBase: 61 foundHomeBaseBm = True 62 otherBms.append((HOMEBASE, bm)) 63 else: 64 otherBms.append((NOTHOMEBASE, bm)) 65 66 bookmarksIwant = otherBms 67 if not foundHomeBaseBm: 68 bookmarksIwant.extend(homeBaseBms) 69 bookmarksIwant = SortListOfTuples(bookmarksIwant) 70 bmInfo = Bunch(missionNameID=missionNameID, contentID=contentID, bookmarks=bookmarksIwant, agentID=agentID) 71 allMissionsList.append((expirationTime, bmInfo)) 72 73 allMissionsList = SortListOfTuples(allMissionsList) 74 return allMissionsList 75 76 def OnClientEvent_WarpFinished(self, *args, **kwargs): 77 self._ResetAgentMissionInfoForAllMissions() 78 self.UpdateMissionsPanel() 79 80 def OnSessionChanged(self, isRemote, sess, change): 81 if not session.charid: 82 return 83 self.UpdateMissionStatusForSessionChange(change) 84 self.UpdateMissionsPanel() 85 86 def OnSessionReset(self): 87 self.Initialize() 88 89 def OnBallparkSetState(self, *args): 90 self.UpdateMissionsPanel() 91 92 def OnItemsChanged(self, items, change, locationData): 93 relevantDestinations = [const.flagCargo, 94 const.flagGeneralMiningHold, 95 const.flagSpecialAsteroidHold, 96 const.flagSpecializedIceHold, 97 const.flagSpecializedGasHold, 98 const.flagSpecializedMineralHold, 99 const.flagSpecializedSalvageHold, 100 const.flagSpecializedShipHold, 101 const.flagSpecializedSmallShipHold, 102 const.flagSpecializedMediumShipHold, 103 const.flagSpecializedLargeShipHold, 104 const.flagSpecializedIndustrialShipHold, 105 const.flagJunkyardTrashed] 106 if session.stationid: 107 relevantDestinations.append(const.flagHangar) 108 agentList = [] 109 for item in items: 110 if item.typeID in self.waitingForTypeIDs.keys(): 111 if item.flagID in relevantDestinations: 112 agentID = self.waitingForTypeIDs[item.typeID] 113 agentList += agentID 114 115 if agentList: 116 self.UpdateMissionStatusData(agentList) 117 118 def _WantNotificationWhenTypeIDArrives(self, info): 119 if not info: 120 return False 121 if info[0].startswith('MissionFetch'): 122 return True 123 for key in ('TransportItemsMissing', 'DropOffItemsMissing', 'AllObjectivesComplete'): 124 if key in info: 125 return True 126 127 return False 128 129 def OnMissionsUpdated(self, missions): 130 for mission in missions: 131 agentID = mission['agentID'] 132 info = mission['info'] or None 133 if self._WantNotificationWhenTypeIDArrives(info): 134 self.NotifyTrackerWhenTypeIDArrives(agentID, int(info[1])) 135 else: 136 self.StopNotifyingTrackerForTypeID(agentID) 137 isUpdateRequired = self.currentAgentMissionInfo.get(agentID, None) != info 138 self.missionObjectives[agentID] = None 139 self.SetCurrentAgentMissionInfo(agentID, info) 140 if agentID in self.agentMissions: 141 self.agentMissions[agentID].update_objective(info) 142 if isUpdateRequired: 143 sm.ScatterEvent('OnAgentMissionChange', agentMissionModified, agentID) 144 145 def OnAgentMissionChanged(self, missionEvent, agentID): 146 if missionEvent != agentMissionModified: 147 self.SetCurrentAgentMissionInfo(agentID, None) 148 self.missionObjectives[agentID] = None 149 self._UpdateAgentMissions() 150 with ExceptionEater('exception during - missiontracker remove/add agent'): 151 if missionEvent == agentMissionQuit: 152 if agentID in self.agentList: 153 self.agentList.remove(agentID) 154 self.RemoveDestinationNotificationTrigger(agentID) 155 elif missionEvent == agentMissionAccepted: 156 if agentID not in self.agentList: 157 self.agentList.append(agentID) 158 self.UpdateMissionStatusData((agentID,)) 159 self._SetAgentForLastAcceptedMission(agentID) 160 callback = sm.GetService('infoPanel').UpdateExpandedAgentMission if missionEvent == agentMissionAccepted else None 161 self.UpdateMissionsPanel(callback) 162 163 def OnAgentMissionObjectivesCompleted(self, agentID): 164 self._UpdateCurrentAgentMissionInfo(agentID) 165 166 def OnAgentMissionObjectivesFailed(self, agentID): 167 self._UpdateCurrentAgentMissionInfo(agentID) 168 169 def NotifyTrackerWhenTypeIDArrives(self, agentID, typeID): 170 if idCheckers.IsNPCCharacter(typeID): 171 activeMission = self.agentMissions.get(agentID) 172 if activeMission and activeMission.context: 173 typeID = activeMission.context.get_value('deliver_items', {}).get('type_id', typeID) 174 self.agentsWaitingForStuff[agentID] = typeID 175 if agentID not in self.waitingForTypeIDs[typeID]: 176 self.waitingForTypeIDs[typeID].append(agentID) 177 178 def StopNotifyingTrackerForTypeID(self, agentID): 179 if agentID not in self.agentsWaitingForStuff: 180 return 181 typeID = self.agentsWaitingForStuff[agentID] 182 if agentID in self.waitingForTypeIDs[typeID]: 183 self.waitingForTypeIDs[typeID].remove(agentID) 184 del self.agentsWaitingForStuff[agentID] 185 186 def UpdateMissionStatusForSessionChange(self, change): 187 if 'locationid' in change: 188 if change['locationid'][0] in self.destinationTriggers.keys(): 189 self.UpdateMissionStatusData(self.destinationTriggers[change['locationid'][0]]) 190 if change['locationid'][1] in self.destinationTriggers.keys(): 191 self.UpdateMissionStatusData(self.destinationTriggers[change['locationid'][1]]) 192 self._ResetAgentMissionInfoForAllMissions() 193 194 def UpdateMissionStatusData(self, agentList): 195 with ExceptionEater('Exception during missiontracker.UpdateAllMissions'): 196 if agentList: 197 self.missionTrackerMgr.UpdateAllMissions(agentList) 198 199 def SetDestinationNotificationTrigger(self, locationID, agentID): 200 if agentID not in self.destinationTriggers[locationID]: 201 self.destinationTriggers[locationID].append(agentID) 202 203 def RemoveDestinationNotificationTrigger(self, agentID): 204 for locationID in self.destinationTriggers.keys(): 205 if agentID in self.destinationTriggers[locationID]: 206 self.destinationTriggers[locationID].remove(agentID) 207 208 def RegisterMissionTracking(self): 209 with ExceptionEater('exception during RegisterMissionTracking'): 210 self._UpdateAgentMissions() 211 missions = self.journal.GetMyAgentJournalDetails()[0] 212 for mission in missions: 213 missionState, _, _, _, agentID, expirationTime, _, _, _, _ = mission 214 if missionState != agentMissionStateAccepted or expirationTime and expirationTime < GetWallclockTime(): 215 continue 216 if agentID not in self.agentList: 217 self.agentList.append(agentID) 218 219 self.UpdateMissionStatusData(self.agentList) 220 221 def _UpdateAgentMissions(self): 222 missions = self.journal.GetMyAgentJournalDetails()[0] 223 activeMissions = set() 224 for mission in missions: 225 missionState = mission[0] 226 agentID = mission[4] 227 expirationTime = mission[5] 228 if missionState == agentMissionStateAccepted and not (expirationTime and expirationTime < GetWallclockTime()): 229 activeMissions.add(agentID) 230 if agentID not in self.agentMissions: 231 self.agentMissions[agentID] = ActiveAgentMission(mission) 232 233 for agentID in self.agentMissions.keys(): 234 if agentID not in activeMissions: 235 self.agentMissions[agentID].stop() 236 del self.agentMissions[agentID] 237 238 def _InitializeCurrentAgentMissionInfo(self): 239 self.currentAgentMissionInfo = {} 240 for mission in self.GetAgentMissions(): 241 self._UpdateCurrentAgentMissionInfo(mission.agentID) 242 243 def _UpdateCurrentAgentMissionInfo(self, agentID): 244 missionInfo = self.missionTrackerMgr.GetMissionInfoItems(agentID) 245 self.currentAgentMissionInfo[agentID] = missionInfo or None 246 if missionInfo and agentID in self.agentMissions: 247 self.agentMissions[agentID].update_objective(missionInfo) 248 249 def SetCurrentAgentMissionInfo(self, agentID, info): 250 if self.currentAgentMissionInfo is None: 251 self._InitializeCurrentAgentMissionInfo() 252 self.currentAgentMissionInfo[agentID] = info 253 254 def GetCurrentAgentMissionInfo(self, agentID): 255 if self.currentAgentMissionInfo is None: 256 self._InitializeCurrentAgentMissionInfo() 257 return self.currentAgentMissionInfo.get(agentID, None) 258 259 def GetCurrentMissionObjective(self, agentID): 260 currentMissionInfo = self.GetCurrentAgentMissionInfo(agentID) 261 objectiveData = CreateObjective(currentMissionInfo, agentID) 262 return objectiveData 263 264 def _ResetAgentMissionInfoForAllMissions(self): 265 self._InitializeCurrentAgentMissionInfo() 266 self.missionObjectives = defaultdict(lambda : None) 267 268 def HasActiveMission(self, agentID): 269 for mission in self.GetAgentMissions(): 270 if mission.agentID == agentID: 271 return True 272 273 return False 274 275 def GetAllAgentMissionInfo(self, agentID): 276 if not self.missionObjectives[agentID]: 277 self.missionObjectives[agentID] = self.missionTrackerMgr.GetAllMissionObjectives(agentID) 278 return self.missionObjectives[agentID] 279 280 def GetAgentForLastAcceptedMission(self): 281 return settings.char.ui.Get(AGENT_FOR_LAST_ACCEPTED_MISSION_SETTING, None) 282 283 def _SetAgentForLastAcceptedMission(self, agentID): 284 settings.char.ui.Set(AGENT_FOR_LAST_ACCEPTED_MISSION_SETTING, agentID) 285 286 def IsInActiveMissionDungeon(self, agentID): 287 return self.missionTrackerMgr.IsInActiveDungeonID(agentID) 288 289 def UpdateMissionsPanel(self, callback = None): 290 sm.GetService('infoPanel').UpdateMissionsPanel(callback)