tactical.py (37500B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\parklife\tactical.py 2 from __future__ import print_function 3 import sys 4 from collections import defaultdict 5 import blue 6 import log 7 import telemetry 8 import dogma.effects 9 import evecamera 10 import evetypes 11 import localization 12 import uthread 13 from caching.memoize import Memoize 14 from carbon.common.script.sys.service import Service 15 from carbon.common.script.sys.serviceConst import SERVICE_RUNNING 16 from carbonui import uiconst 17 from carbonui.control.window import Window 18 from carbonui.uicore import uicore 19 from carbonui.util.bunch import Bunch 20 from dogma.const import falloffEffectivnessModuleGroups 21 from eve.client.script.parklife import states as state 22 from eve.client.script.parklife import tacticalOverlay 23 from eve.client.script.ui.inflight.activeitem import ActiveItem 24 from eve.client.script.ui.inflight.drone import DroneView 25 from eve.client.script.ui.inflight.drones.dronesWindow import DronesWindow 26 from eve.client.script.ui.inflight.overview.overviewWindow import OverviewWindow 27 from eve.client.script.ui.inflight.overview.overviewWindowUtil import OpenOverview 28 from eve.client.script.ui.inflight.selectedItemWnd import SelectedItemWnd 29 from eve.client.script.ui.shared.export import ExportOverviewWindow, ImportOverviewWindow 30 from eve.client.script.ui.util import uix 31 from eve.client.script.ui.view.viewStateConst import ViewState 32 from eve.common.lib import appConst as const 33 from eve.common.script.sys import eveCfg, idCheckers 34 from eveDrones.droneDamageTracker import InBayDroneDamageTracker 35 from inventorycommon.const import categoryEntity 36 from overviewPresets import overviewSettingsConst 37 BRACKETBORDER = 17 38 OVERVIEW_CONFIGNAME = 0 39 OVERVIEW_GROUPDATA = 1 40 BRACKETS_CONFIGNAME = 2 41 BRACKETS_GROUPDATA = 3 42 INVISIBLE_TYPES = [const.typeUnlitModularEffectBeacon] 43 WARP_SCRAMBLE_MESSAGE_ATTACKER = 'OnWarpScrambleAttacker' 44 WARP_SCRAMBLE_MESSAGE_DEFENDER = 'OnWarpScrambleDefender' 45 WARP_SCRAMBLE_MESSAGE_OTHER = 'OnWarpScrambleOther' 46 WARP_DISRUPT_MESSAGE_ATTACKER = 'OnWarpDisruptAttacker' 47 WARP_DISRUPT_MESSAGE_DEFENDER = 'OnWarpDisruptDefender' 48 WARP_DISRUPT_MESSAGE_OTHER = 'OnWarpDisruptOther' 49 TACTICAL_OVERLAY_DISALLOWED_CAMERAS = (evecamera.CAM_SHIPPOV, evecamera.CAM_SHIPORBIT_RESTRICTED, evecamera.CAM_JUMP) 50 51 @Memoize 52 def GetCacheByLabel(key): 53 return localization.GetByLabel(key) 54 55 56 def _SendWarpScrambleMessages(shipID, targetID): 57 _SendWarpMessages(shipID, targetID, WARP_SCRAMBLE_MESSAGE_ATTACKER, WARP_SCRAMBLE_MESSAGE_DEFENDER, WARP_SCRAMBLE_MESSAGE_OTHER) 58 59 60 def _SendWarpDisruptionMessages(shipID, targetID): 61 _SendWarpMessages(shipID, targetID, WARP_DISRUPT_MESSAGE_ATTACKER, WARP_DISRUPT_MESSAGE_DEFENDER, WARP_DISRUPT_MESSAGE_OTHER) 62 63 64 def _SendWarpMessages(shipID, targetID, attackerMessageID, defenderMessageID, otherMessageID): 65 attackerName = sm.GetService('bracket').GetBracketName2(shipID) 66 defenderName = sm.GetService('bracket').GetBracketName2(targetID) 67 if attackerName and defenderName: 68 if session.shipid == targetID: 69 sm.GetService('logger').AddCombatMessage(defenderMessageID, {'attacker': attackerName}) 70 elif session.shipid == shipID: 71 sm.GetService('logger').AddCombatMessage(attackerMessageID, {'defender': defenderName}) 72 else: 73 sm.GetService('logger').AddCombatMessage(otherMessageID, {'attacker': attackerName, 74 'defender': defenderName}) 75 76 77 class TacticalSvc(Service): 78 __guid__ = 'svc.tactical' 79 __update_on_reload__ = 0 80 __notifyevents__ = ['DoBallsAdded', 81 'DoBallRemove', 82 'OnOverviewPresetLoaded', 83 'OnStateChange', 84 'OnStateSetupChange', 85 'ProcessSessionChange', 86 'OnSessionChanged', 87 'OnSessionReset', 88 'OnClientEvent_JumpStarted', 89 'OnClientEvent_JumpExecuted', 90 'OnSpecialFX', 91 'ProcessOnUIAllianceRelationshipChanged', 92 'OnSetCorpStanding', 93 'OnSetAllianceStanding', 94 'OnSuspectsAndCriminalsUpdate', 95 'OnDisapprovalUpdate', 96 'OnSlimItemChange', 97 'OnDroneStateChange2', 98 'OnDroneControlLost', 99 'OnItemChange', 100 'OnBallparkCall', 101 'OnEwarStart', 102 'OnEwarEnd', 103 'OnEwarOnConnect', 104 'OnContactChange', 105 'OnCrimewatchEngagementUpdated', 106 'DoBallsRemove', 107 'OnHideUI', 108 'OnShowUI', 109 'OnCombatMessage', 110 'OnOverviewTabsChanged'] 111 __startupdependencies__ = ['settings', 'tacticalNavigation', 'viewState'] 112 __dependencies__ = ['clientDogmaStaticSvc', 113 'stateSvc', 114 'bracket', 115 'overviewPresetSvc', 116 'godma'] 117 118 def __init__(self): 119 Service.__init__(self) 120 self._clearModuleTasklet = None 121 122 def Run(self, *etc): 123 Service.Run(self, *etc) 124 self.tacticalOverlay = tacticalOverlay.TacticalOverlay(self, self.tacticalNavigation) 125 self.logme = 0 126 self.jammers = {} 127 self.jammersByJammingType = {} 128 self.filterFuncs = None 129 self.CleanUp() 130 self.Setup() 131 self.hideUI = False 132 self.flagsAreDirty = False 133 self.dirtyFlags = set() 134 self.flagCheckingThread = uthread.new(self.FlagsDirtyCheckingLoop) 135 self.inBayDroneDamageTracker = None 136 137 def Setup(self): 138 self.CleanUp() 139 self.AssureSetup() 140 if eveCfg.InSpace(): 141 if self.IsTacticalOverlayActive(): 142 self.tacticalOverlay.Initialize() 143 self.Open() 144 145 def Stop(self, *etc): 146 Service.Stop(self, *etc) 147 self.CleanUp() 148 149 def OnCombatMessage(self, messageName, messageArgs): 150 if 'specialObject' in messageArgs: 151 objectName = sm.GetService('bracket').GetBracketName2(messageArgs['specialObject']) 152 messageArgs['specialObject'] = objectName 153 sm.GetService('logger').AddCombatMessage(messageName, messageArgs) 154 155 @telemetry.ZONE_METHOD 156 def OnBallparkCall(self, eventName, argTuple): 157 if self.sr is None: 158 return 159 if eventName == 'SetBallInteractive' and argTuple[1] == 1: 160 bp = sm.GetService('michelle').GetBallpark() 161 if not bp: 162 return 163 slimItem = bp.GetInvItem(argTuple[0]) 164 if not slimItem: 165 return 166 self.MarkFlagsForSpecificItemsAsDirty({slimItem.itemID}) 167 168 @telemetry.ZONE_METHOD 169 def OnItemChange(self, item, change, location): 170 if (const.ixFlag in change or const.ixLocationID in change) and item.flagID == const.flagDroneBay: 171 droneview = self.GetPanel('droneview') 172 if droneview: 173 droneview.CheckReloadDronesScroll() 174 else: 175 self.CheckInitDrones() 176 177 @telemetry.ZONE_METHOD 178 def ProcessSessionChange(self, isRemote, session, change): 179 doResetJammers = False 180 if self.logme: 181 self.LogInfo('Tactical::ProcessSessionChange', isRemote, session, change) 182 if 'stationid' in change: 183 doResetJammers = True 184 if 'solarsystemid' in change: 185 self.TearDownOverlay() 186 doResetJammers = True 187 if 'shipid' in change: 188 for itemID in self.attackers: 189 self.stateSvc.SetState(itemID, state.threatAttackingMe, 0) 190 191 self.attackers = {} 192 doResetJammers = True 193 droneview = self.GetPanel('droneview') 194 if droneview: 195 if getattr(self, '_initingDrones', False): 196 self.LogInfo('Tactical: ProcessSessionChange: busy initing drones, cannot close the window') 197 else: 198 droneview.Close() 199 if doResetJammers: 200 self.ResetJammers() 201 202 def ResetJammers(self): 203 self.jammers = {} 204 self.jammersByJammingType = {} 205 sm.ScatterEvent('OnRefreshBuffBar') 206 207 def RemoveBallFromJammers(self, ball, *args): 208 ballID = ball.id 209 effectsFromBall = self.jammers.get(ballID) 210 if getattr(self, 'fighterService', None) is None: 211 setattr(self, 'fighterService', sm.GetService('fighters')) 212 self.fighterService.shipFighterState.KillEffectsFromBall(ballID) 213 if effectsFromBall is None: 214 return 215 doUpdate = False 216 for effectName, effectSet in self.jammersByJammingType.iteritems(): 217 if effectName not in effectsFromBall: 218 continue 219 tuplesToRemove = set() 220 for effectTuple in effectSet: 221 effectBallID, moduleID = effectTuple 222 if effectBallID == ballID: 223 tuplesToRemove.add(effectTuple) 224 225 if tuplesToRemove: 226 effectSet.difference_update(tuplesToRemove) 227 doUpdate = True 228 229 self.jammers.pop(ballID, None) 230 if doUpdate: 231 sm.ScatterEvent('OnEwarEndFromTactical') 232 233 def OnSessionChanged(self, isRemote, session, change): 234 if eveCfg.InSpace(): 235 if sm.GetService('subway').InJump(): 236 return 237 self.AssureSetup() 238 self.Open() 239 if self.IsTacticalOverlayActive() and not self.hideUI: 240 self.tacticalOverlay.Initialize() 241 self.CheckInitDrones() 242 self.MarkFlagsAsDirty() 243 if 'shipid' in change: 244 self.tacticalOverlay.OnShipChange() 245 else: 246 self.CleanUp() 247 248 def OnSessionReset(self): 249 self.inBayDroneDamageTracker = None 250 251 def OnClientEvent_JumpStarted(self, *args): 252 if self.IsTacticalOverlayActive(): 253 self.TearDownOverlay() 254 self.ResetJammers() 255 256 def OnClientEvent_JumpExecuted(self, itemID): 257 self.AssureSetup() 258 self.Open() 259 if self.IsTacticalOverlayActive() and not self.hideUI: 260 self.tacticalOverlay.Initialize() 261 self.CheckInitDrones() 262 self.MarkFlagsAsDirty() 263 264 @telemetry.ZONE_METHOD 265 def OnSlimItemChange(self, oldSlim, newSlim): 266 if not eveCfg.InSpace(): 267 return 268 update = 0 269 if getattr(newSlim, 'allianceID', None) and newSlim.allianceID != getattr(oldSlim, 'allianceID', None): 270 update = 1 271 elif newSlim.corpID and newSlim.corpID != oldSlim.corpID: 272 update = 2 273 elif newSlim.charID != oldSlim.charID: 274 update = 3 275 elif newSlim.ownerID != oldSlim.ownerID: 276 update = 4 277 elif getattr(newSlim, 'lootRights', None) != getattr(oldSlim, 'lootRights', None): 278 update = 5 279 elif getattr(newSlim, 'isEmpty', None) != getattr(oldSlim, 'isEmpty', None): 280 update = 6 281 if update: 282 if session.charid in (newSlim.charID, oldSlim.charID): 283 self.MarkFlagsAsDirty() 284 else: 285 self.MarkFlagsForSpecificItemsAsDirty({oldSlim.itemID, newSlim.itemID}) 286 287 def ProcessOnUIAllianceRelationshipChanged(self, *args): 288 if self.InSpace(): 289 self.MarkFlagsAsDirty() 290 291 def OnContactChange(self, contactIDs, contactType = None): 292 if eveCfg.InSpace(): 293 self.MarkFlagsAsDirty() 294 295 def OnSetCorpStanding(self, *args): 296 if eveCfg.InSpace(): 297 self.MarkFlagsAsDirty() 298 299 def OnSetAllianceStanding(self, *args): 300 if eveCfg.InSpace(): 301 self.MarkFlagsAsDirty() 302 303 def OnCrimewatchEngagementUpdated(self, otherCharId, timeout): 304 if eveCfg.InSpace(): 305 uthread.new(self.DelayedFlagStateUpdate) 306 307 def OnSuspectsAndCriminalsUpdate(self, criminalizedCharIDs, decriminalizedCharIDs): 308 if eveCfg.InSpace(): 309 uthread.new(self.DelayedFlagStateUpdate) 310 311 def OnDisapprovalUpdate(self, newCharID, removedCharIDs): 312 if eveCfg.InSpace(): 313 uthread.new(self.DelayedFlagStateUpdate) 314 315 def DelayedFlagStateUpdate(self): 316 if getattr(self, 'delayedFlagStateUpdate', False): 317 return 318 setattr(self, 'delayedFlagStateUpdate', True) 319 blue.pyos.synchro.SleepWallclock(1000) 320 self.MarkFlagsAsDirty() 321 setattr(self, 'delayedFlagStateUpdate', False) 322 323 def OnHideUI(self): 324 self.hideUI = True 325 if self.IsTacticalOverlayActive(): 326 self.tacticalOverlay.TearDown() 327 328 def OnShowUI(self): 329 self.hideUI = False 330 if eveCfg.InSpace() and self.IsTacticalOverlayActive(): 331 self.tacticalOverlay.Initialize() 332 333 @telemetry.ZONE_METHOD 334 def OnSpecialFX(self, shipID, moduleID, moduleTypeID, targetID, otherTypeID, guid, isOffensive, start, active, duration = -1, repeat = None, startTime = None, timeFromStart = 0, graphicInfo = None): 335 if targetID == session.shipid and isOffensive: 336 attackerID = shipID 337 attackTime = startTime 338 attackRepeat = repeat 339 shipItem = sm.StartService('michelle').GetItem(shipID) 340 if shipItem and shipItem.categoryID == const.categoryStarbase: 341 attackerID = moduleID 342 attackTime = 0 343 attackRepeat = 0 344 data = self.attackers.get(attackerID, []) 345 key = (moduleID, 346 guid, 347 attackTime, 348 duration, 349 attackRepeat) 350 if start and shipID != session.shipid: 351 if key not in data: 352 data.append(key) 353 self.stateSvc.SetState(attackerID, state.threatAttackingMe, 1) 354 else: 355 toRemove = None 356 for signature in data: 357 if signature[0] == key[0] and signature[1] == key[1] and signature[2] == key[2] and signature[3] == key[3]: 358 toRemove = signature 359 break 360 361 if toRemove is not None: 362 data.remove(toRemove) 363 if not data: 364 self.stateSvc.SetState(attackerID, state.threatAttackingMe, 0) 365 self.attackers[attackerID] = data 366 if start: 367 if settings.user.ui.Get('notifyMessagesEnabled', 1) or session.shipid in (shipID, targetID): 368 if guid == 'effects.WarpDisrupt': 369 _SendWarpDisruptionMessages(shipID, targetID) 370 elif guid == 'effects.WarpScramble': 371 _SendWarpScrambleMessages(shipID, targetID) 372 373 def CheckInitDrones(self): 374 mySlim = uix.GetBallparkRecord(session.shipid) 375 if not mySlim: 376 return 377 if mySlim.groupID == const.groupCapsule: 378 return 379 dronesInBay = sm.GetService('invCache').GetInventoryFromId(session.shipid).ListDroneBay() 380 if dronesInBay: 381 self.InitDrones() 382 else: 383 myDrones = sm.GetService('michelle').GetDrones() 384 if myDrones: 385 self.InitDrones() 386 387 @telemetry.ZONE_METHOD 388 def Open(self): 389 self.InitSelectedItem() 390 OpenOverview() 391 self.CheckInitDrones() 392 393 def GetMain(self): 394 if self and getattr(self.sr, 'mainParent', None): 395 return self.sr.mainParent 396 397 def OnStateChange(self, itemID, flag, true, *args): 398 uthread.new(self._OnStateChange, itemID, flag, true, *args) 399 400 def _OnStateChange(self, itemID, flag, true, *args): 401 if not eveCfg.InSpace(): 402 return 403 if not self or getattr(self, 'sr', None) is None: 404 return 405 if self.logme: 406 self.LogInfo('Tactical::OnStateChange', itemID, flag, true, *args) 407 self.tacticalOverlay.CheckState(itemID, flag, true) 408 409 def OnOverviewPresetLoaded(self, label, set): 410 uthread.new(self.InitConnectors).context = 'tactical::OnOverviewPresetLoaded-->InitConnectors' 411 412 def OnStateSetupChange(self, what): 413 self.MarkFlagsAsDirty() 414 self.InitConnectors() 415 416 def Toggle(self): 417 pass 418 419 def BlinkHeader(self, key): 420 if not self or self.sr is None: 421 return 422 panel = getattr(self.sr, key.lower(), None) 423 if panel: 424 panel.Blink() 425 426 def IsExpanded(self, key): 427 panel = getattr(self.sr, key.lower(), None) 428 if panel: 429 return panel.sr.main.state == uiconst.UI_PICKCHILDREN 430 431 def AssureSetup(self): 432 if self.logme: 433 self.LogInfo('Tactical::AssureSetup') 434 if getattr(self, 'setupAssured', None): 435 return 436 if getattr(self, 'sr', None) is None: 437 self.sr = Bunch() 438 self.setupAssured = 1 439 440 def CleanUp(self): 441 if self.logme: 442 self.LogInfo('Tactical::CleanUp') 443 self.sr = None 444 self.targetingRanges = None 445 self.toggling = 0 446 self.setupAssured = 0 447 self.lastFactor = None 448 self.groupList = None 449 self.groupIDs = [] 450 self.intersections = [] 451 self.threats = {} 452 self.attackers = {} 453 self.TearDownOverlay() 454 uicore.layer.tactical.Flush() 455 self.dronesInited = 0 456 self.busy = 0 457 458 def GetFilterFuncs(self): 459 if self.filterFuncs is None: 460 stateSvc = sm.GetService('stateSvc') 461 self.filterFuncs = {'Criminal': stateSvc.CheckCriminal, 462 'Suspect': stateSvc.CheckSuspect, 463 'Outlaw': stateSvc.CheckOutlaw, 464 'Dangerous': stateSvc.CheckDangerous, 465 'StandingHigh': stateSvc.CheckStandingHigh, 466 'StandingGood': stateSvc.CheckStandingGood, 467 'StandingNeutral': stateSvc.CheckStandingNeutral, 468 'StandingBad': stateSvc.CheckStandingBad, 469 'StandingHorrible': stateSvc.CheckStandingHorrible, 470 'NoStanding': stateSvc.CheckNoStanding, 471 'SameFleet': stateSvc.CheckSameFleet, 472 'SamePlayerCorp': stateSvc.CheckSamePlayerCorp, 473 'SameNpcCorp': stateSvc.CheckSameNpcCorp, 474 'SameAlliance': stateSvc.CheckSameAlliance, 475 'SameMilitia': stateSvc.CheckSameMilitia, 476 'AtWarCanFight': stateSvc.CheckAtWarCanFight, 477 'AtWarMilitia': stateSvc.CheckAtWarMilitia, 478 'IsWanted': stateSvc.CheckIsWanted, 479 'HasKillRight': stateSvc.CheckHasKillRight, 480 'WreckViewed': stateSvc.CheckWreckViewed, 481 'WreckEmpty': stateSvc.CheckWreckEmpty, 482 'LimitedEngagement': stateSvc.CheckLimitedEngagement, 483 'AlliesAtWar': stateSvc.CheckAlliesAtWar, 484 'AgentInteractable': stateSvc.CheckAgentInteractable} 485 return self.filterFuncs 486 487 def CheckFiltered(self, slimItem, filtered, alwaysShow): 488 stateSvc = sm.GetService('stateSvc') 489 if len(filtered) + len(alwaysShow) > 3: 490 ownerID = slimItem.ownerID 491 if ownerID is None or ownerID == const.ownerSystem or idCheckers.IsNPC(ownerID): 492 checkArgs = (slimItem, None) 493 else: 494 checkArgs = (slimItem, stateSvc._GetRelationship(slimItem)) 495 else: 496 checkArgs = (slimItem,) 497 functionDict = self.GetFilterFuncs() 498 for functionName in alwaysShow: 499 f = functionDict.get(functionName, None) 500 if f is None: 501 self.LogError('CheckFiltered got bad functionName: %r' % functionName) 502 continue 503 if f(*checkArgs): 504 return False 505 506 for functionName in filtered: 507 f = functionDict.get(functionName, None) 508 if f is None: 509 self.LogError('CheckFiltered got bad functionName: %r' % functionName) 510 continue 511 if f(*checkArgs): 512 return True 513 514 return False 515 516 def UpdateStates(self, slimItem, uiwindow): 517 print('Deprecated, TacticalSvc.UpdateStates, call UpdateFlagAndBackground on the uiwindow instead') 518 519 def UpdateBackground(self, slimItem, uiwindow): 520 print('Deprecated, TacticalSvc.UpdateBackground, call on the uiwindow instead') 521 522 def UpdateIcon(self, slimItem, uiwindow): 523 print('Deprecated, TacticalSvc.UpdateIcon, call UpdateIconColor on the uiwindow instead') 524 525 def UpdateFlag(self, slimItem, uiwindow): 526 print('Deprecated, TacticalSvc.UpdateFlag, call on the uiwindow instead') 527 528 def GetFlagUI(self, parent): 529 print('Deprecated, TacticalSvc.GetFlagUI, make the icon yourself') 530 531 def UpdateFlagPositions(self, uiwindow, icon = None): 532 print('Deprecated, TacticalSvc.UpdateFlagPositions, call on the uiwindow instead') 533 534 def MarkFlagsAsDirty(self): 535 self.dirtyFlags.clear() 536 self.flagsAreDirty = True 537 538 def MarkFlagsForSpecificItemsAsDirty(self, itemIDs): 539 self.dirtyFlags.update(itemIDs) 540 541 @telemetry.ZONE_METHOD 542 def FlagsDirtyCheckingLoop(self): 543 while self.state == SERVICE_RUNNING: 544 try: 545 if self.flagsAreDirty: 546 self.flagsAreDirty = False 547 self.InvalidateFlags() 548 elif self.dirtyFlags: 549 itemIDs = self.dirtyFlags 550 self.dirtyFlags = set() 551 self.InvalidateFlagsForSpecificItems(itemIDs) 552 except Exception: 553 log.LogException(extraText='Error invalidating tactical flags') 554 sys.exc_clear() 555 556 blue.pyos.synchro.SleepWallclock(500) 557 558 def InvalidateFlags(self): 559 if not eveCfg.InSpace(): 560 return 561 sm.ScatterEvent('OnFlagsInvalidated', None) 562 sm.GetService('bracket').RenewFlags() 563 564 def InvalidateFlagsForSpecificItems(self, itemIDs): 565 if not eveCfg.InSpace(): 566 return 567 sm.ScatterEvent('OnFlagsInvalidated', itemIDs) 568 sm.GetService('bracket').RenewFlagForItemIDs(itemIDs) 569 570 def InvalidateFlagsExtraLimited(self, charID): 571 if eveCfg.InSpace(): 572 sm.GetService('bracket').RenewSingleFlagForCharID(charID) 573 574 def GetFilteredStatesFunctionNames(self, isBracket = False, presetName = None): 575 return [ self.stateSvc.GetStateProps(flag).label for flag in self.overviewPresetSvc.GetFilteredStates(isBracket=isBracket, presetName=presetName) ] 576 577 def GetAlwaysShownStatesFunctionNames(self, isBracket = False, presetName = None): 578 return [ self.stateSvc.GetStateProps(flag).label for flag in self.overviewPresetSvc.GetAlwaysShownStates(isBracket=isBracket, presetName=presetName) ] 579 580 def Get(self, what, default): 581 if self.logme: 582 self.LogInfo('Tactical::Get', what, default) 583 return getattr(self, what, default) 584 585 def OpenSettings(self, *args): 586 uicore.cmd.OpenOverviewSettings() 587 588 def ToggleOnOff(self): 589 current = self.IsTacticalOverlayActive() 590 if not current: 591 self.ShowTacticalOverlay() 592 elif self.tacticalOverlay.IsInitialized(): 593 self.HideTacticalOverlay() 594 595 def HideTacticalOverlay(self): 596 self._SetTacticalOverlayActive(False) 597 self.TearDownOverlay() 598 sm.ScatterEvent('OnTacticalOverlayChange') 599 600 def _SetTacticalOverlayActive(self, isActive): 601 cam = sm.GetService('sceneManager').GetActiveSpaceCamera() 602 if cam.cameraID == evecamera.CAM_TACTICAL: 603 settings.user.overview.Set('viewTactical_camTactical', isActive) 604 elif cam.cameraID in (evecamera.CAM_SHIPORBIT, evecamera.CAM_SHIPORBIT_ABYSSAL_SPACE, evecamera.CAM_SHIPORBIT_HAZARD): 605 settings.user.overview.Set('viewTactical', isActive) 606 607 def ShowTacticalOverlay(self): 608 if not self.IsTacticalOverlayAllowed(): 609 return 610 self._SetTacticalOverlayActive(True) 611 if not self.hideUI: 612 self.tacticalOverlay.Initialize() 613 sm.ScatterEvent('OnTacticalOverlayChange') 614 615 def IsTacticalOverlayAllowed(self): 616 cam = sm.GetService('sceneManager').GetActiveSpaceCamera() 617 return cam.cameraID not in TACTICAL_OVERLAY_DISALLOWED_CAMERAS 618 619 def IsTacticalOverlayActive(self): 620 cameraID = self.viewState.GetView(ViewState.Space).GetRegisteredCameraID() 621 if cameraID == evecamera.CAM_TACTICAL: 622 return settings.user.overview.Get('viewTactical_camTactical', True) 623 elif cameraID in TACTICAL_OVERLAY_DISALLOWED_CAMERAS: 624 return False 625 else: 626 return settings.user.overview.Get('viewTactical', False) 627 628 def CheckInit(self): 629 if eveCfg.InSpace() and self.IsTacticalOverlayActive() and not self.hideUI: 630 self.tacticalOverlay.Initialize() 631 632 def TearDownOverlay(self): 633 if self.targetingRanges: 634 self.targetingRanges.KillTimer() 635 self.tacticalOverlay.TearDown() 636 637 def GetOverlay(self): 638 return self.tacticalOverlay 639 640 def ShowModuleRange(self, module, charge = None): 641 if self._clearModuleTasklet is not None: 642 self._clearModuleTasklet.kill() 643 self._clearModuleTasklet = None 644 self.tacticalOverlay.UpdateModuleRange(module, charge) 645 646 def ClearModuleRange(self): 647 648 def _task(): 649 blue.synchro.SleepSim(500) 650 if self._clearModuleTasklet is not None: 651 self._clearModuleTasklet = None 652 self.tacticalOverlay.UpdateModuleRange() 653 654 self._clearModuleTasklet = uthread.new(_task) 655 656 def FindMaxRange(self, module, charge, dogmaLocation = None, *args): 657 maxRange = 0 658 falloffDist = 0 659 bombRadius = 0 660 cynoRadius = 0 661 if not dogmaLocation: 662 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 663 try: 664 effectID = self.clientDogmaStaticSvc.GetDefaultEffect(module.typeID) 665 except KeyError: 666 pass 667 else: 668 effect = self.clientDogmaStaticSvc.GetEffect(effectID) 669 if effect.rangeAttributeID is not None: 670 maxRange = dogmaLocation.GetAccurateAttributeValue(module.itemID, effect.rangeAttributeID) 671 if module.groupID in falloffEffectivnessModuleGroups: 672 falloffDist = dogmaLocation.GetAccurateAttributeValue(module.itemID, const.attributeFalloffEffectiveness) 673 else: 674 falloffDist = dogmaLocation.GetAccurateAttributeValue(module.itemID, const.attributeFalloff) 675 676 if module.groupID == const.groupCynosuralField: 677 isCovert = dogmaLocation.GetAttributeValue(module.itemID, const.attributeIsCovert) 678 beaconRadius = 0.0 679 if isCovert: 680 beaconRadius = evetypes.GetRadius(const.typeCovertCynosuralFieldI) 681 else: 682 beaconRadius = evetypes.GetRadius(const.typeCynosuralFieldI) 683 cynoRadius = dogmaLocation.GetAccurateAttributeValue(module.itemID, const.attributeCynosuralFieldSpawnRadius) 684 cynoRadius += 2.0 * beaconRadius 685 excludedChargeGroups = [const.groupScannerProbe, const.groupSurveyProbe] 686 if not maxRange and charge and charge.groupID not in excludedChargeGroups: 687 flightTime = dogmaLocation.GetAccurateAttributeValue(charge.itemID, const.attributeExplosionDelay) 688 velocity = dogmaLocation.GetAccurateAttributeValue(charge.itemID, const.attributeMaxVelocity) 689 bombRadius = dogmaLocation.GetAccurateAttributeValue(charge.itemID, const.attributeEmpFieldRange) 690 maxRange = flightTime * velocity / 1000.0 691 if dogmaLocation.dogmaStaticMgr.TypeHasAttribute(charge.typeID, const.attributeMaxFOFTargetRange): 692 maxFofRange = dogmaLocation.GetAccurateAttributeValue(charge.itemID, dogma.const.attributeMaxFOFTargetRange) 693 maxRange = min(maxRange, maxFofRange) 694 return (maxRange, 695 falloffDist, 696 bombRadius, 697 cynoRadius) 698 699 def GetPanelForUpdate(self, what): 700 panel = self.GetPanel(what) 701 if panel and not panel.IsCollapsed() and not panel.IsMinimized(): 702 return panel 703 704 def GetPanel(self, what): 705 wnd = Window.GetIfOpen(what) 706 if wnd and not wnd.destroyed: 707 return wnd 708 709 def InitDrones(self): 710 if getattr(self, '_initingDrones', False): 711 return 712 self._initingDrones = True 713 try: 714 if not DronesWindow.GetIfOpen(): 715 DronesWindow.OpenBehindFullscreenViews(showActions=False, panelName=localization.GetByLabel('UI/Drones/Drones')) 716 finally: 717 self._initingDrones = False 718 719 def OnOverviewTabsChanged(self): 720 windowInstanceIDs = self.overviewPresetSvc.GetWindowInstanceIDs() 721 self._CloseOverviewWindowsWithNoTabs(windowInstanceIDs) 722 OpenOverview() 723 724 def _CloseOverviewWindowsWithNoTabs(self, windowInstanceIDs): 725 openWindows = uicore.registry.GetWindowsByClass(OverviewWindow) 726 for wnd in openWindows: 727 if wnd.windowInstanceID not in windowInstanceIDs: 728 wnd.Close() 729 730 def InitSelectedItem(self): 731 if not SelectedItemWnd.GetIfOpen(): 732 SelectedItemWnd.OpenBehindFullscreenViews(panelname=localization.GetByLabel('UI/Inflight/ActiveItem/SelectedItem')) 733 734 def InitConnectors(self): 735 if self.logme: 736 self.LogInfo('Tactical::InitConnectors') 737 if not self.tacticalOverlay.IsInitialized(): 738 return 739 self.tacticalOverlay.InitConnectors() 740 741 def WantIt(self, slimItem, filtered = None, alwaysShown = None, isBracket = False): 742 if not slimItem: 743 return False 744 if slimItem.typeID in INVISIBLE_TYPES: 745 return False 746 overviewOverride = self.overviewPresetSvc.GetOverrideState(slimItem) 747 if overviewOverride is not None: 748 return overviewOverride 749 if isBracket and self.overviewPresetSvc.GetActiveBracketPresetName() in (None, overviewSettingsConst.BRACKET_FILTER_SHOWALL): 750 return True 751 if self.logme: 752 self.LogInfo('Tactical::WantIt', slimItem) 753 if slimItem.itemID == session.shipid: 754 return isBracket 755 filterGroups = self.overviewPresetSvc.GetValidGroups(isBracket=isBracket) 756 if slimItem.groupID in filterGroups: 757 if self.stateSvc.CheckIfFilterItem(slimItem) and self.CheckFiltered(slimItem, filtered, alwaysShown): 758 return False 759 return True 760 return False 761 762 def DoBallsAdded(self, *args, **kw): 763 import stackless 764 import blue 765 t = stackless.getcurrent() 766 timer = t.PushTimer(blue.pyos.taskletTimer.GetCurrent() + '::tactical') 767 try: 768 return self.DoBallsAdded_(*args, **kw) 769 finally: 770 t.PopTimer(timer) 771 772 def DoBallsAdded_(self, lst): 773 if not self or getattr(self, 'sr', None) is None: 774 return 775 uthread.pool('Tactical::DoBallsAdded', self._DoBallsAdded, lst) 776 777 def _DoBallsAdded(self, lst): 778 if not self or self.sr is None: 779 return 780 if self.logme: 781 self.LogInfo('Tactical::DoBallsAdded', lst) 782 self.LogInfo('Tactical - adding balls, num balls:', len(lst)) 783 inCapsule = 0 784 mySlim = uix.GetBallparkRecord(session.shipid) 785 if mySlim and mySlim.groupID == const.groupCapsule: 786 inCapsule = 1 787 checkDrones = 0 788 filtered = self.GetFilteredStatesFunctionNames() 789 alwaysShown = self.GetAlwaysShownStatesFunctionNames() 790 for each in lst: 791 if each[1].itemID == session.shipid: 792 checkDrones = 1 793 if not checkDrones and not inCapsule and each[1].categoryID == const.categoryDrone: 794 drone = sm.GetService('michelle').GetDroneState(each[1].itemID) 795 if drone and (drone.ownerID == session.charid or drone.controllerID == session.shipid): 796 checkDrones = 1 797 if not self.WantIt(each[1], filtered, alwaysShown): 798 continue 799 self.tacticalOverlay.AddConnector(each[0], each[1]) 800 801 if checkDrones: 802 droneview = self.GetPanel('droneview') 803 if droneview: 804 droneview.CheckReloadDronesScroll() 805 else: 806 self.CheckInitDrones() 807 808 def OnDroneStateChange2(self, droneID, oldState, newState): 809 self.InitDrones() 810 droneview = self.GetPanel('droneview') 811 if droneview: 812 droneview.CheckReloadDronesScroll() 813 814 def OnDroneControlLost(self, droneID): 815 droneview = self.GetPanel('droneview') 816 if droneview: 817 droneview.CheckReloadDronesScroll() 818 819 @telemetry.ZONE_METHOD 820 def DoBallsRemove(self, pythonBalls, isRelease): 821 for ball, slimItem, terminal in pythonBalls: 822 self.DoBallRemove(ball, slimItem, terminal) 823 824 def DoBallRemove(self, ball, slimItem, terminal): 825 if not self or getattr(self, 'sr', None) is None: 826 return 827 if ball is None: 828 return 829 if not eveCfg.InSpace(): 830 return 831 self.RemoveBallFromJammers(ball) 832 if not self.GetDroneViewForSlimItem(slimItem) and not self.tacticalOverlay.HasConnector(ball.id): 833 return 834 if self.logme: 835 self.LogInfo('Tactical::DoBallRemove', ball.id) 836 uthread.pool('tactical::DoBallRemoveThread', self.DoBallRemoveThread, ball, slimItem, terminal) 837 838 def GetDroneViewForSlimItem(self, slimItem): 839 if slimItem.categoryID == const.categoryDrone and slimItem.ownerID == session.charid: 840 return self.GetPanel('droneview') 841 842 def DoBallRemoveThread(self, ball, slimItem, terminal): 843 self.tacticalOverlay.RemoveConnector(ball.id) 844 droneview = self.GetDroneViewForSlimItem(slimItem) 845 if droneview: 846 droneview.CheckReloadDronesScroll() 847 848 def OnEwarStart(self, sourceBallID, moduleID, targetBallID, jammingType): 849 if not jammingType: 850 self.LogError('Tactical::OnEwarStart', sourceBallID, jammingType) 851 return 852 if not hasattr(self, 'jammers'): 853 self.jammers = {} 854 if not hasattr(self, 'jammersByJammingType'): 855 self.jammersByJammingType = {} 856 if targetBallID == session.shipid: 857 if sourceBallID not in self.jammers: 858 self.jammers[sourceBallID] = {} 859 self.jammers[sourceBallID][jammingType] = self.stateSvc.GetEwarFlag(jammingType) 860 if jammingType not in self.jammersByJammingType: 861 self.jammersByJammingType[jammingType] = set() 862 self.jammersByJammingType[jammingType].add((sourceBallID, moduleID)) 863 sm.ScatterEvent('OnEwarStartFromTactical') 864 865 def OnEwarEnd(self, sourceBallID, moduleID, targetBallID, jammingType): 866 if not jammingType: 867 self.LogError('Tactical::OnEwarEnd', sourceBallID, jammingType) 868 return 869 if not hasattr(self, 'jammers'): 870 return 871 if sourceBallID in self.jammers and jammingType in self.jammers[sourceBallID]: 872 del self.jammers[sourceBallID][jammingType] 873 if jammingType in self.jammersByJammingType and (sourceBallID, moduleID) in self.jammersByJammingType[jammingType]: 874 self.jammersByJammingType[jammingType].remove((sourceBallID, moduleID)) 875 ewarId = (sourceBallID, moduleID, targetBallID) 876 sm.ScatterEvent('OnEwarEndFromTactical', jammingType, ewarId) 877 878 def OnEwarOnConnect(self, shipID, moduleID, moduleTypeID, targetID, guid, *args): 879 if targetID != session.shipid: 880 return 881 if evetypes.GetCategoryID(moduleTypeID) == categoryEntity: 882 ewarType = self.FindEwarTypeOnNpcFromGuid(moduleTypeID, guid) 883 else: 884 ewarType = self.FindEwarTypeFromModuleTypeID(moduleTypeID) 885 if ewarType is not None: 886 self.OnEwarStart(shipID, moduleID, targetID, ewarType) 887 888 def FindEwarTypeFromModuleTypeID(self, moduleTypeID, *args): 889 try: 890 effectID = self.clientDogmaStaticSvc.GetDefaultEffect(moduleTypeID) 891 return dogma.effects.GetEwarTypeByEffectID(effectID) 892 except KeyError: 893 pass 894 895 def FindEwarTypeOnNpcFromGuid(self, entityTypeID, guid): 896 effectID = None 897 try: 898 effects = self.godma.GetStateManager().GetEffectsByTypeID(entityTypeID) 899 for effect in effects.itervalues(): 900 if effect.guid == guid: 901 if effectID is not None: 902 self.LogWarn('Entity=%s has multiple effects with same guid=%s - this will lead to dbuff icon conflict' % (entityTypeID, guid)) 903 effectID = effect.effectID 904 905 return dogma.effects.GetEwarTypeByEffectID(effectID) 906 except KeyError: 907 return effectID 908 909 def GetEffectSourcesAndCountByJammingType(self, jammingType): 910 effectSourcesSet = self.jammersByJammingType.get(jammingType, set()) 911 effectSources = defaultdict(int) 912 for effectInfo in effectSourcesSet: 913 sourceID, moduleID = effectInfo 914 effectSources[sourceID] += 1 915 916 return dict(effectSources) 917 918 def ImportOverviewSettings(self, *args): 919 ImportOverviewWindow.Open() 920 921 def ExportOverviewSettings(self, *args): 922 ExportOverviewWindow.Open() 923 924 def OnEveGetsFocus(self, *args): 925 pass 926 927 def GetInBayDroneDamageTracker(self): 928 dogmaLM = self.godma.GetDogmaLM() 929 clientDogmaLM = sm.GetService('clientDogmaIM').GetDogmaLocation() 930 if self.inBayDroneDamageTracker is None: 931 self.inBayDroneDamageTracker = InBayDroneDamageTracker(dogmaLM, clientDogmaLM) 932 else: 933 self.inBayDroneDamageTracker.SetDogmaLM(dogmaLM) 934 return self.inBayDroneDamageTracker