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

menusvc.py (199764B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\services\menusvc.py
      2 import sys
      3 import types
      4 import random
      5 import eveformat
      6 import eveicon
      7 import utillib
      8 from eve.devtools.script import devtools_util
      9 from jumpbridge.client.jumpBridge import GetJumpBridgeComponent
     10 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     11 import webbrowser
     12 from stargate.client.localGates import FindLocalStargate, FindLocalJumpGateForDestinationPath
     13 from eve.client.script.ui.comparison.comparisonSettings import use_new_comparison_tool
     14 from eve.common.script.sys.idCheckers import IsSkyhook
     15 from shipcaster.shipcasterConst import SHIPCASTER_PROXIMITY_TO_JUMP
     16 from shipcaster.client.shipcasterUtil import GetTargetForShipcaster, GetFailureTextAndDisabledOption, GetTargetForStarterShipcaster
     17 from carbon.common.script.net.moniker import Moniker
     18 from carbon.common.script.sys.serviceConst import ROLE_CONTENT, ROLE_GML, ROLE_LEGIONEER, ROLE_PROGRAMMER, ROLE_SPAWN, ROLE_WORLDMOD
     19 from carbon.common.script.sys.sessions import ThrottlePerSecond
     20 from carbonui.control.contextMenu.menuEntryData import MenuEntryData
     21 from carbonui.util.various_unsorted import SortListOfTuples
     22 from eve.client.script.ui.inflight.overview import overviewMenuUtil
     23 from eve.client.script.ui.services.menuEntries import DroneEngageTargetMenuEntryData, WarpToMenuEntryData, KeepAtRangeMenuEntryData, OrbitMenuEntryData
     24 from eve.client.script.ui.services.menuMerge import MergeMenus
     25 from eve.client.script.ui.shared.fleet.fleetBroadcastConst import iconsByBroadcastType
     26 from evefleet import BROADCAST_TRAVEL_TO, BROADCAST_JUMP_TO, BROADCAST_ALIGN_TO, BROADCAST_WARP_TO, BROADCAST_TARGET
     27 from eveclientqatools.shaderDebugger import ShaderDebugger
     28 from eveclientqatools.textureViewer import TextureWindow
     29 from itemcompression.client.ui.compression_window import DirectlyCompressInSpace, DirectlyCompressInStructure
     30 from itemcompression.client.gasDecompression import decompress_gas
     31 from itemcompression.client.ui.decompression_window import GasDecompressionWindow
     32 from itemcompression.client.itemCompression import CompressItemInSpace, CompressItemInStructure
     33 from eve.client.script.ui.inflight.capitalnavigation import CapitalNav
     34 from eve.client.script.ui.inflight.facilityTaxWindow import FacilityTaxWindow
     35 from eve.client.script.ui.shared.fittingScreen.tryFit import GhostFitShip
     36 from eve.client.script.ui.shared.inventory.invWindow import Inventory
     37 from eve.client.script.ui.shared.neocom.corporation.memberDetails import OpenMemberDetails
     38 from eve.client.script.ui.view.viewStateConst import ViewState
     39 from eve.client.script.util import eveMisc
     40 import evefleet.client
     41 from eve.devtools.script.svc_dgmattr import AttributeInspector
     42 from evefleet.client.util import GetSelectedFormationName
     43 from eveservices.xmppchat import GetChatService
     44 import inventorycommon.const as invconst
     45 from eve.client.script.parklife import states
     46 from evestations.data import get_station_services_for_operation
     47 from menu import CONTAINERGROUPS, MenuLabel, MenuList
     48 from eve.client.script.ui.shared.fitting.fittingUtil import TryFit
     49 from eve.client.script.ui.shared.industry.industryWnd import Industry
     50 from eve.client.script.ui.shared.mapView.mapViewUtil import OpenMap
     51 from eve.client.script.ui.shared.activateMultiTraining import ActivateMultiTraining
     52 from eve.client.script.ui.shared.sov.sovHub.skyhooksCleanup.cleanupSovSystemWindow import open_sov_system_cleanup
     53 from eve.common.script.util import industryCommon
     54 from eve.common.script.net import eveMoniker
     55 import carbon.common.script.util.format as fmtutil
     56 import evetypes
     57 from eveuniverse.solar_systems import GetLightYearDistance
     58 from globalConfig.getFunctions import GetMaxShipsToFit, AllowCharacterLogoff
     59 from inventorycommon.const import compareCategories
     60 from inventorycommon.util import IsShipFittable
     61 from moonmining.const import MOON_BEACONID_NAME
     62 from shipfitting.multiBuyUtil import BuyMultipleTypes
     63 from eve.client.script.ui.services.menuSvcExtras import marketMenu
     64 from eve.client.script.ui.structure.structuremenu import GetStructureMenu
     65 from eveclientqatools.stargateDebugger import StargateDebuggerViewController
     66 from eveclientqatools.modelstatedebugger import ModelStateDebuggerController
     67 from eveclientqatools.audio import AudioGmMenu
     68 from eve.client.script.ui.util import uix, utilWindows
     69 import uthread
     70 import log
     71 import blue
     72 from eve.common.script.net import eveMoniker as moniker
     73 import destiny
     74 from eve.client.script.parklife import states as state
     75 import carbonui.const as uiconst
     76 import eve.common.script.mgt.posConst as pos
     77 import localization
     78 from eve.client.script.environment import invControllers as invCtrl
     79 import telemetry
     80 import eve.client.script.ui.util.defaultRangeUtils as defaultRangeUtils
     81 from eve.common.lib import appConst as const, appConst
     82 import evegraphics.settings as gfxsettings
     83 from eveexceptions import UserError
     84 from spacecomponents.client.components import phaseStabilizer
     85 from shipprogression.boarding_moment import can_play_boarding_moment
     86 from sovereignty.mercenaryden.client.checkers import is_mercenary_den_close_enough_to_configure
     87 from spacecomponents.common.helper import HasCargoBayComponent, HasBehaviorComponent, HasDeployComponent, HasMercenaryDenComponent
     88 from spacecomponents.client.components import cargobay, behavior, microJumpDriver, linkWithShip, towGameObjective
     89 from spacecomponents.client.qa.utils import get_qa_menu as get_space_components_menu
     90 from spacecomponents.client.ui.link_with_ship import GetLinkButtonLabelPath
     91 from spacecomponents.common.componentConst import ITEM_TRADER, UNDER_CONSTRUCTION
     92 from eve.client.script.ui.services.menuSvcExtras import menuFunctions, modelDebugFunctions, movementFunctions, invItemFunctions, droneFunctions, devFunctions, openFunctions
     93 from carbon.common.script.sys.service import Service
     94 from carbonui.control.contextMenu.menuConst import DISABLED_ENTRY0
     95 from carbonui.control.contextMenu.menuUtil import CloseContextMenus
     96 import inventorycommon.typeHelpers
     97 from eve.common.script.sys.eveCfg import InShipInSpace, IsControllingStructure
     98 from eve.common.script.sys import eveCfg, idCheckers
     99 import fsdBuiltData.common.graphicIDs as fsdGraphicIDs
    100 from menucheckers import ItemChecker, SessionChecker, MapChecker, BookmarkChecker, CelestialChecker, DroneChecker, CharacterChecker, FleetMemberChecker
    101 from carbonui.uicore import uicore
    102 from eveprefs import prefs, boot
    103 from eveservices.menu import StartMenuService
    104 from itertoolsext import Bundle
    105 import homestation.client
    106 import expertSystems.client
    107 from eve.client.script.ui.control import eveMenu
    108 from journey.journey_messanger import JourneyMessenger
    109 CELESTIAL_MENU_CATEGORIES = (const.categoryCelestial,
    110  const.categoryStarbase,
    111  const.categoryStation,
    112  const.categoryShip,
    113  const.categoryEntity,
    114  const.categoryDrone,
    115  const.categoryAsteroid,
    116  const.categoryDeployable,
    117  const.categorySovereigntyStructure,
    118  const.categoryStructure,
    119  const.categoryFighter,
    120  const.categoryOrbital)
    121 DEFAULT_INTERACTION_RANGE = 2500
    122 
    123 class MenuSvc(Service):
    124     __guid__ = 'svc.menu'
    125     __update_on_reload__ = 0
    126     __dependencies__ = ['pwn',
    127      'godma',
    128      'michelle',
    129      'invCache',
    130      'crimewatchSvc',
    131      'clientPathfinderService',
    132      'securitySvc',
    133      'fighters']
    134     __startupdependencies__ = ['settings']
    135     __notifyevents__ = ['OnSessionChanged']
    136 
    137     def __init__(self):
    138         super(MenuSvc, self).__init__()
    139         self.sessionChecker = None
    140         self.expandTimer = None
    141         self.lastAlignTargetID = None
    142         self.lastAlignedToBookmark = None
    143 
    144     def Run(self, memStream = None):
    145         uicore.uilib.RegisterForTriuiEvents([uiconst.UI_MOUSEDOWN], self.OnGlobalMouseDown)
    146         self.sessionChecker = None
    147         self.expandTimer = None
    148 
    149     @staticmethod
    150     def OnGlobalMouseDown(obj, *args):
    151         if not obj.IsUnder(uicore.layer.menu):
    152             CloseContextMenus()
    153         return True
    154 
    155     def Stop(self, *args):
    156         self.expandTimer = None
    157 
    158     def OnSessionChanged(self, isremote, session, change):
    159         self.expandTimer = None
    160         self.sessionChecker = None
    161         CloseContextMenus()
    162 
    163     @staticmethod
    164     def TryExpandActionMenu(itemID, clickedObject, *args, **kwargs):
    165         sm.GetService('radialmenu').TryExpandActionMenu(itemID, clickedObject, *args, **kwargs)
    166 
    167     def MapMenu(self, itemID):
    168         if idCheckers.IsSolarSystem(itemID) or idCheckers.IsStation(itemID) or sm.GetService('structureDirectory').GetStructureInfo(itemID):
    169             return self._MapMenu(itemID)
    170         return MenuList()
    171 
    172     def _MapMenu(self, itemID):
    173         menuEntries = MenuList()
    174         starmap = sm.GetService('starmap')
    175         checker = MapChecker(itemID)
    176         if checker.OfferSetDestination():
    177             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/SetDestination'), lambda : starmap.SetWaypoint(itemID, True, origin='map_menu_set_destination')))
    178         if checker.OfferRemoveWaypoint():
    179             menuEntries += [[MenuLabel('UI/Inflight/RemoveWaypoint'), starmap.ClearWaypoints, (itemID,)]]
    180         else:
    181             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/AddWaypoint'), lambda : starmap.SetWaypoint(itemID, origin='map_menu_add_waypoint')))
    182         _, _, constellationID, _, _ = sm.StartService('map').GetParentLocationID(itemID)
    183         menuEntries += [[MenuLabel('UI/Inflight/BookmarkLocation'), self.Bookmark, (itemID, const.typeSolarSystem, constellationID)]]
    184         return menuEntries
    185 
    186     def InvItemMenu(self, invItems, viewOnly = 0, unparsed = 0):
    187         if type(invItems) == list:
    188             menus = []
    189             allInvItems = [ items[0] for items in invItems ]
    190             for invItem, viewOnly, _ in invItems:
    191                 menus.append(self._InvItemMenu(invItem, viewOnly, unparsed, allInvItems=allInvItems))
    192 
    193             return MergeMenus(menus)
    194         else:
    195             return MergeMenus([self._InvItemMenu(invItems, viewOnly, unparsed)])
    196 
    197     def _InvItemMenu(self, invItem, viewOnly, unparsed = 0, allInvItems = None):
    198         stationOperation = sm.GetService('station').stationItem.operationID if session.stationid else None
    199         stationServices = get_station_services_for_operation(stationOperation) or []
    200         checkViewOnly = bool(viewOnly)
    201         isMultiSelection = allInvItems and len(allInvItems) > 1
    202         spansMultipleLocations = isMultiSelection and any((allInvItems[0].locationID != item.locationID for item in allInvItems))
    203         if self.sessionChecker is None:
    204             self.sessionChecker = SessionChecker(session, sm)
    205         item = ItemChecker(invItem, self.sessionChecker)
    206         menuEntries = MenuList()
    207         if item.OfferSplitStack():
    208             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/SplitStack'), self.SplitStack, [invItem]]]
    209         if item.OfferRedeemCurrency():
    210             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/RedeemCurrency'), self.RedeemCurrency, (invItem, invItem.stacksize)]]
    211         if item.OfferAssembleContainer():
    212             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/AssembleContainer'), self.AssembleContainer, [invItem]]]
    213         if item.OfferLockItem():
    214             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/LockItem'), self.ALSCLock, [invItem]]]
    215         if item.OfferUnlockItem():
    216             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/UnlockItem'), self.ALSCUnlock, [invItem]]]
    217         if item.OfferProposeBlueprintLockdownVote():
    218             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/ProposeBlueprintLockdownVote'), self.LockDownBlueprint, (invItem,)]]
    219         if item.OfferProposeBlueprintUnlockVote():
    220             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/ProposeBlueprintUnlockVote'), self.UnlockBlueprint, (invItem,)]]
    221         if item.OfferRepairItems():
    222             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/GetRepairQuote'), openFunctions.RepairItems, [invItem]]]
    223         if item.OfferViewTypesMarketDetails():
    224             self._AddMarketDetailsOption(menuEntries, invItem.typeID)
    225         if item.OfferSellThisItem():
    226             if item.IsPlexVaultItem():
    227                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/SellThisItem'), self.SellPlex, texturePath=eveicon.isk))
    228             elif isMultiSelection:
    229                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/MultiSell'), lambda : self.SellItems(allInvItems), texturePath=eveicon.isk, typeID=invItem.typeID, internalName='Sell', quantity=len(allInvItems)))
    230             else:
    231                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/SellThisItem'), lambda : self.SellItems([invItem]), texturePath=eveicon.isk, typeID=invItem.typeID, internalName='Sell'))
    232         if item.OfferBuyThisType():
    233             if isMultiSelection:
    234                 menuEntries.append(MenuEntryData(MenuLabel('UI/Market/MarketQuote/BuyAll'), lambda : BuyMultipleTypes(allInvItems), quantity=len(allInvItems), internalName='BuyAll'))
    235             else:
    236                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/BuyThisType'), self.QuickBuy, (invItem.typeID,)]]
    237         if item.OfferViewContents():
    238             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/ViewContents'), self.GetContainerContents, [invItem, item.GetLocationIDOfItemInCorpOffice()]]]
    239         if item.OfferConfigureShipCloneFacility():
    240             menuEntries += [[MenuLabel('UI/Commands/ConfigureShipCloneFacility'), self.ShipCloneConfig, (invItem.itemID,)]]
    241         menuEntries.extend(openFunctions.GetOpenShipHoldMenus(item))
    242         if not spansMultipleLocations:
    243             if item.OfferCreateContract():
    244                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/CreateContract'), self.QuickContract, [invItem]]]
    245             if item.OfferDeliverTo():
    246                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/DeliverTo'), self.DeliverToStructure, [invItem]]]
    247         if item.OfferRepackage():
    248             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/Repackage'), self.RepackageItems, [invItem]]]
    249         if item.OfferUndock():
    250             label = 'UI/Commands/UndockFromStation' if self.sessionChecker.IsPilotInStation() else 'UI/Commands/UndockFromStructure'
    251             menuEntries += [[MenuLabel(label), self.ExitDockableLocation, ()]]
    252         if item.IsCompressibleType():
    253             if item.OfferCompressInSpace():
    254                 menuEntries += [[MenuLabel('UI/Commands/Compress'), DirectlyCompressInSpace, [invItem]]]
    255             elif item.OfferCompressInStructure():
    256                 menuEntries += [[MenuLabel('UI/Commands/Compress'), DirectlyCompressInStructure, [invItem]]]
    257         if item.OfferDecompressGas():
    258             menuEntries += [[MenuLabel('UI/Commands/DecompressGas'), GasDecompressionWindow.AddItemOrOpenWindow, (invItem,)]]
    259         if item.OfferDeliverToCorp():
    260             divisionNames = sm.GetService('corp').GetDivisionNames()
    261             divisions = []
    262             for flagID in const.flagCorpSAGs:
    263                 divisionID = const.corpDivisionsByFlag[flagID]
    264                 divisionName = divisionNames[divisionID + 1]
    265                 divisions.append((flagID, divisionName))
    266 
    267             deliverToCorpHangarMenu = [ (divisionName, self.DeliverToCorpHangarFolder, [[(invItem, flagID)]]) for flagID, divisionName in divisions ]
    268             deliverToMenu = [[MenuLabel('UI/Corporations/CorpHangarSubmenu'), deliverToCorpHangarMenu],
    269              [MenuLabel('UI/Corporations/CorporationWindow/Members/CorpMember'), self.DeliverToCorpMember, [invItem]],
    270              None,
    271              [MenuLabel('UI/Corporations/CorporationWindow/Members/Myself', {'char': session.charid}), self.DeliverToSelf, [invItem]]]
    272             if unparsed:
    273                 menuEntries += [None]
    274             menuEntries += [[MenuLabel('UI/Corporations/DeliverCorpStuffTo'), deliverToMenu]]
    275         if item.OfferTrashIt():
    276             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/TrashIt'), self.TrashInvItems, [invItem]]]
    277         if item.OfferConfigureOrbitalPoco() or item.OfferConfigureOrbitalSkyhook():
    278             menuEntries += [[MenuLabel('UI/DustLink/ConfigureOrbital'), self.ConfigureOrbital, (invItem,)]]
    279         if item.OfferCompareButton():
    280             if isMultiSelection:
    281                 menuEntries += [MenuEntryData(MenuLabel('UI/Compare/CompareButton'), lambda : self.CompareTypes([ i.typeID for i in allInvItems ], [ i.itemID for i in allInvItems ]), quantity=len(allInvItems))]
    282             else:
    283                 menuEntries += [(MenuLabel('UI/Compare/CompareButton'), self.CompareType, (invItem.typeID, invItem.itemID))]
    284         if item.OfferActivateShipSkinLicense():
    285             if isMultiSelection:
    286                 menuEntries += [[MenuLabel('UI/Commands/ActivateSkinLicense'), menuFunctions.ActivateShipSkinLicense, [(invItem.itemID, invItem.typeID)]]]
    287             else:
    288                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/SkinSubmenu'), ('isDynamic', self.GetSkinLicenseMenu, (invItem, item))]]
    289         if item.OfferConsumeShipSkinDesignComponent():
    290             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/ConsumeSkinDesignComponentItem'), menuFunctions.ConsumeSkinDesignComponent, [(invItem.itemID, invItem.typeID, invItem.stacksize)]]]
    291         if item.IsDecodable():
    292             menuEntries += [[MenuLabel('UI/Commands/DecodeDataStream'), menuFunctions.DecryptItem, [invItem.itemID, invItem.typeID]]]
    293         if not checkViewOnly:
    294             if item.OfferLaunchDrones():
    295                 menuEntries.append(MenuEntryData(MenuLabel('UI/Drones/LaunchDrone', {'numDrones': 1}), lambda : self.LaunchDrones([invItem])))
    296             elif item.failure_label:
    297                 menuEntries.reasonsWhyNotAvailable['UI/Drones/LaunchDrones'] = self.GetUnavailableText(item)
    298             if item.OfferTrainNowToLevel1():
    299                 menuEntries += [[MenuLabel('UI/SkillQueue/AddSkillMenu/TrainNowToLevel1'), self.TrainNow, [invItem]]]
    300             if item.OfferInjectSkill():
    301                 menuEntries.append(MenuEntryData(MenuLabel('UI/SkillQueue/InjectSkill'), lambda : self.InjectSkillIntoBrain([invItem]), texturePath=eveicon.person))
    302             if item.OfferConsumeBooster():
    303                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/ConsumeBooster'), lambda : self.ConsumeBooster([invItem]), texturePath=eveicon.person))
    304             if item.OfferConsumeExpertSystem():
    305                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/ConsumeBooster'), lambda : self.ConsumeExpertSystem(invItem), texturePath=eveicon.person))
    306             if item.OfferPlugInImplant():
    307                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/PlugInImplant'), lambda : self.PlugInImplant([invItem]), texturePath=eveicon.person))
    308             if item.OfferAssembleShip():
    309                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/AssembleShip'), lambda : self.AssembleShip([invItem]), texturePath=eveicon.assemble_ship))
    310                 if self.sessionChecker.IsPilotDocked():
    311                     menuEntries += [[MenuLabel('UI/Fitting/FittingWindow/FittingManagement/OpenMultifit'), ('isDynamic', self.GetFitMenu, [invItem, invItem.typeID])]]
    312             if not isMultiSelection and item.OfferAssembleAndBoardShip():
    313                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/BoardShip'), lambda : self.AssembleAndBoardShip(invItem), texturePath=eveicon.board))
    314             if item.OfferReprocess(stationServices):
    315                 if item.session.IsPilotDocked():
    316                     menuEntries += [[MenuLabel('UI/Inventory/ItemActions/Reprocess'), invItemFunctions.Reprocess, [invItem]]]
    317                 else:
    318                     refineryID = item.GetInSpaceLocationItem().itemID
    319                     menuEntries += [[MenuLabel('UI/Inventory/ItemActions/Reprocess'), lambda itemIDasList: self.invCache.GetInventoryFromId(refineryID).Reprocess(itemIDasList[0]), [invItem.itemID]]]
    320             if item.OfferOpenContainer():
    321                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/OpenContainer'), openFunctions.OpenCargoContainer, [invItem]]]
    322             if item.OfferBreakContract():
    323                 menuEntries += [[MenuLabel('UI/Contracts/BreakContract'), self.Break, [invItem]]]
    324             if item.OfferDeliverCourierPackage():
    325                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/ContractsDelieverCourierPackage'), self.DeliverCourierContract, [invItem]]]
    326             if item.OfferFitToActiveShip():
    327                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/FitToActiveShip'), TryFit, [invItem]]]
    328             if item.OfferMoveToDroneBay():
    329                 menuEntries += [[MenuLabel('UI/Drones/MoveToDroneBay'), self.FitDrone, [invItem]]]
    330             if item.OfferLaunchForCorp():
    331                 if HasDeployComponent(invItem.typeID):
    332                     menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/LaunchForCorp'), lambda : eveMisc.LaunchFromShip([invItem], maxQty=1)))
    333                 else:
    334                     deployFunction = self.LaunchForCorp
    335                     if item.IsStructure():
    336                         deployFunction = self.DeployStructure
    337                     menuEntries.append([MenuLabel('UI/Inventory/ItemActions/LaunchForCorp'), deployFunction, [invItem]])
    338             if item.OfferLaunchForSelf():
    339                 if HasDeployComponent(invItem.typeID):
    340                     menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/LaunchForSelf'), lambda : eveMisc.LaunchFromShip([invItem], maxQty=1)))
    341                 else:
    342                     menuEntries.append([MenuLabel('UI/Inventory/ItemActions/LaunchForSelf'), self.LaunchForSelf, [invItem]])
    343             if item.OfferJettison():
    344                 if item.session.IsPilotControllingUndockableStructure():
    345                     menuEntries += [[MenuLabel('UI/Inventory/ItemActions/Jettison'), self.JettisonFuel, [invItem]]]
    346                 else:
    347                     menuEntries += [[MenuLabel('UI/Inventory/ItemActions/Jettison'), self.Jettison, [invItem]]]
    348             if item.OfferLaunchForSelf_Container():
    349                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/LaunchForSelf'), self.Jettison, [invItem]]]
    350             if item.OfferLeaveShip():
    351                 if self.sessionChecker.IsPilotInStation():
    352                     if can_play_boarding_moment(invItem.typeID):
    353                         menuEntries += [[MenuLabel('UI/ShipProgression/TriggerBoardingMoment'), self.DoBoardingMoment]]
    354                     menuEntries += [[MenuLabel('UI/Inventory/ItemActions/LeaveShip'), self.LeaveShip, (invItem,)]]
    355                 elif self.sessionChecker.IsPilotInStructure():
    356                     if can_play_boarding_moment(invItem.typeID) and sm.GetService('viewState').IsPrimaryViewActive(ViewState.Hangar):
    357                         menuEntries += [[MenuLabel('UI/ShipProgression/TriggerBoardingMoment'), self.DoBoardingMoment]]
    358                     menuEntries += [[MenuLabel('UI/Inventory/ItemActions/LeaveShip'), sm.GetService('structureDocking').LeaveShip, (invItem.itemID,)]]
    359         if unparsed:
    360             menuEntries += [None]
    361         if not isMultiSelection:
    362             menuEntries += [[MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo, (invItem.typeID,
    363                invItem.itemID,
    364                0,
    365                invItem,
    366                None)]]
    367             if item.OfferReverseRedeem():
    368                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/ReverseRedeem'), sm.GetService('redeem').ReverseRedeem, (invItem,)]]
    369             elif item.OfferActivateCharacterReSculptToken():
    370                 menuEntries += [[MenuLabel('UI/Commands/ActivateCharacterReSculptToken'), self.ActivateCharacterReSculpt, (invItem.itemID,)]]
    371             elif item.OfferActivateMultiTraining():
    372                 menuEntries += [[MenuLabel('UI/Commands/ActivateMultiTrainingToken'), self.ActivateMultiTraining, (invItem.itemID,)]]
    373             elif item.OfferActivateSkillExtractor():
    374                 menuEntries += [[MenuLabel('UI/Commands/ActivateSkillExtractor'), self.ActivateSkillExtractor, (invItem,)]]
    375             elif item.OfferActivateSkillInjector():
    376                 menuEntries += self.GetActivateSkillInjectorMenuEntry(invItem)
    377             elif item.OfferOpenCrate():
    378                 menuEntries += [[localization.GetByLabel('UI/Crate/MenuCommandOpenCrate', typeID=invItem.typeID), self.OpenCrate, (invItem.typeID, invItem.itemID, invItem.stacksize)]]
    379             if item.OfferSplitSkillInjector():
    380                 menuEntries += [[MenuLabel('UI/Commands/SplitInjector', {'quantity': invItem.stacksize}), menuFunctions.SplitSkillInjector, (invItem.itemID, invItem.stacksize)]]
    381             if item.OfferCombineSkillInjector():
    382                 menuEntries += [[MenuLabel('UI/Commands/CombineInjector'), menuFunctions.CombineSkillInjector, (invItem.itemID, invItem.stacksize)]]
    383             if item.OfferCraftDynamicItem():
    384                 menuEntries += [[MenuLabel('UI/Commands/CraftDynamicItem', {'mutator': invItem.typeID}), self.CraftDynamicItem, (invItem,)]]
    385             if item.OfferActivateAbyssalKey():
    386                 menuEntries += [[MenuLabel('UI/Commands/ActivateAbyssalKey', {'item': invItem.typeID}), self.ActivateAbyssalKey, (invItem,)]]
    387             if item.OfferActivateVoidSpaceKey():
    388                 menuEntries += [[MenuLabel('UI/Commands/ActivateAbyssalKey', {'item': invItem.typeID}), self.ActivateVoidSpaceKey, (invItem,)]]
    389             if item.OfferRandomJumpKey():
    390                 menuEntries += [[MenuLabel('UI/Commands/ActivateRandomJumpKey', {'item': invItem.typeID}), self.ActivateRandomJumpKey, (invItem,)]]
    391             if item.OfferPVPFilamentKey():
    392                 menuEntries += [[MenuLabel('UI/Commands/ActivatePVPFilamentKey', {'item': invItem.typeID}), self.ActivatePVPfilamentKey, (invItem,)]]
    393             if item.OfferWarpVector():
    394                 menuEntries += [[MenuLabel('UI/Commands/ActivateWarpVectorItem'), self.ActivateWarpVector, (invItem,)]]
    395             if item.OfferUseFormula():
    396                 menuEntries += [[MenuLabel('UI/Industry/UseFormula'), self.ShowInIndustryWindow, [invItem]]]
    397             if item.OfferUseBlueprint():
    398                 menuEntries += [[MenuLabel('UI/Industry/UseBlueprint'), self.ShowInIndustryWindow, [invItem]]]
    399             if item.OfferTransferAmmoToCargo():
    400                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/TransferAmmoToCargo'), self.TransferToCargo, (invItem.itemID,)]]
    401             if item.OfferInsureItem(stationServices):
    402                 menuEntries += [[MenuLabel('UI/Insurance/InsuranceWindow/Commands/Insure'), sm.GetService('insurance').Insure, (invItem,)]]
    403             if item.OfferFindInContracts():
    404                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/FindInContracts'), sm.GetService('contracts').FindRelated, (invItem.typeID,
    405                    None,
    406                    None,
    407                    None,
    408                    None,
    409                    None)]]
    410             if item.OfferFindInPersonalAssets():
    411                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/FindPersonalAssets'), invItemFunctions.FindInPersonalAssets, (invItem.typeID,)]]
    412             if invItem.typeID in settings.user.ui.Get('marketquickbar', []):
    413                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/RemoveTypeFromMarketQuickbar'), self.RemoveFromQuickBar, (invItem,)]]
    414             elif item.OfferAddToMarketQuickBar():
    415                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/AddTypeToMarketQuickbar'), self.AddToQuickBar, (invItem.typeID,)]]
    416             if item.OfferLoadCharges():
    417                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/LoadCharges'), self.LoadCharges, (invItem,)]]
    418             if item.OfferSimulateShipFitting():
    419                 menuEntries += [(MenuLabel('UI/Fitting/FittingWindow/SimulateShipFitting'), GhostFitShip, (invItem,))]
    420             if item.OfferSimulateShip():
    421                 menuEntries += [(MenuLabel('UI/Fitting/FittingWindow/SimulateShip'), openFunctions.SimulateFitting, (utillib.KeyVal(shipTypeID=invItem.typeID, fitData=[]),))]
    422             if unparsed:
    423                 menuEntries += [None]
    424         if not isMultiSelection and not checkViewOnly:
    425             if item.OfferSetNewPasswordForContainer():
    426                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/SetNewPasswordForContainer'), self.AskNewContainerPwd, ([invItem], localization.GetByLabel('UI/Inventory/ItemActions/SetNewPasswordForContainer'), const.SCCPasswordTypeGeneral)]]
    427             if item.OfferSetNewConfigPasswordForContainer():
    428                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/SetNewConfigPasswordForContainer'), self.AskNewContainerPwd, ([invItem], localization.GetByLabel('UI/Inventory/ItemActions/SetNewConfigPasswordForContainer'), const.SCCPasswordTypeConfig)]]
    429             if item.OfferViewLog():
    430                 menuEntries += [MenuEntryData(MenuLabel('UI/Inventory/ItemActions/ViewLog'), lambda : openFunctions.ViewAuditLogForALSC(invItem.itemID), texturePath=eveicon.details_view)]
    431             if item.OfferConfigureALSC():
    432                 menuEntries += [MenuEntryData(MenuLabel('UI/Inventory/ItemActions/ConfigureALSContainer'), lambda : self.ConfigureALSC(invItem.itemID), texturePath=eveicon.settings)]
    433             if item.OfferRetrievePasswordALSC():
    434                 menuEntries += [[MenuLabel('UI/Commands/RetrievePassword'), self.RetrievePasswordALSC, (invItem.itemID,)]]
    435             if item.OfferSetName():
    436                 menuEntries += [[MenuLabel('UI/Commands/SetName'), self.SetName, (invItem,)]]
    437             if item.OfferMakeShipActive():
    438                 if self.sessionChecker.IsPilotInStation():
    439                     menuEntries += [[MenuLabel('UI/Inflight/BoardShip'), self.ActivateShip, (invItem,)]]
    440                 elif self.sessionChecker.IsPilotInStructure():
    441                     menuEntries += [[MenuLabel('UI/Inflight/BoardShip'), sm.GetService('structureDocking').ActivateShip, (invItem.itemID,)]]
    442             if item.OfferStripFitting():
    443                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/StripFitting'), self.StripFitting, [invItem]]]
    444             if item.OfferFindContract():
    445                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/FindContract'), self.FindCourierContract, [invItem]]]
    446             if item.OfferChangeName():
    447                 menuEntries += [[MenuLabel('UI/Commands/ChangeName'), self.SetName, (invItem,)]]
    448             if item.OfferLaunchFromContainer():
    449                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/LaunchFromContainer'), self.LaunchContainerFromContainer, (invItem,)]]
    450             if item.OfferLaunchShip():
    451                 if item.IsInShipMA():
    452                     menuEntries += [[MenuLabel('UI/Inventory/ItemActions/LaunchShip'), self.LaunchSMAContents, [invItem]]]
    453                 elif item.OfferLaunchShipFromSpaceContainer():
    454                     menuEntries += [[MenuLabel('UI/Inventory/ItemActions/LaunchShip'), self.LaunchShipFromWreck, [invItem]]]
    455             if item.OfferBoardShip_FromSMA():
    456                 menuEntries += [[MenuLabel('UI/Inflight/BoardShip'), self.BoardSMAShip, (invItem.locationID, invItem.itemID)]]
    457             if item.OfferLaunchShipFromBay():
    458                 menuEntries += [[MenuLabel('UI/Inventory/ItemActions/LaunchShipFromBay'), self.LaunchSMAContents, [invItem]]]
    459             if item.OfferBoardShipFromBay():
    460                 menuEntries += [[MenuLabel('UI/Inflight/POS/BoardShipFromBay'), self.BoardSMAShip, (invItem.locationID, invItem.itemID)]]
    461         if session.role & (ROLE_GML | ROLE_WORLDMOD):
    462             menuEntries.insert(0, ('GM / WM Extras', ('isDynamic', self.GetGMMenu, (invItem.itemID,
    463                None,
    464                None,
    465                invItem,
    466                None))))
    467         return menuEntries
    468 
    469     def DeliverToCorpHangarFolder(self, invItemAndFlagList):
    470         return invItemFunctions.DeliverToCorpHangarFolder(invItemAndFlagList, self.invCache)
    471 
    472     def DeliverToCorpMember(self, invItems):
    473         return invItemFunctions.DeliverToCorpMember(invItems, self.invCache)
    474 
    475     def DeliverToSelf(self, invItems):
    476         return invItemFunctions.DeliverToMyself(invItems, self.invCache)
    477 
    478     def SplitStack(self, invItems):
    479         return invItemFunctions.SplitStack(invItems, self.invCache)
    480 
    481     def MarketDetailMenu(self, typeID):
    482         m = MenuList()
    483         if not evetypes.IsPublished(typeID):
    484             return m
    485         if evetypes.GetMarketGroupID(typeID):
    486             self._AddMarketDetailsOption(m, typeID)
    487         if evetypes.IsPublished(typeID):
    488             m += [(MenuLabel('UI/Inventory/ItemActions/FindInContracts'), sm.GetService('contracts').FindRelated, (typeID,
    489                None,
    490                None,
    491                None,
    492                None,
    493                None))]
    494         m += [[MenuLabel('UI/Inventory/ItemActions/FindPersonalAssets'), invItemFunctions.FindInPersonalAssets, (typeID,)]]
    495         m += [(MenuLabel('UI/Compare/CompareButton'), self.CompareType, (typeID,))]
    496         return m
    497 
    498     def DroneMenu(self, data, unmerged = 0):
    499         if isinstance(data, list):
    500             menus = MenuList([ self._DroneMenu(droneID, typeID, ownerID, locationID) for droneID, typeID, ownerID, locationID in data ])
    501             if unmerged:
    502                 return menus
    503             return MergeMenus(menus)
    504         return self._DroneMenu(*data)
    505 
    506     def _DroneMenu(self, droneID, typeID, ownerID, locationID):
    507         bp = sm.StartService('michelle').GetBallpark()
    508         if not bp:
    509             return MenuList()
    510         groupID = evetypes.GetGroupID(typeID)
    511         categoryID = evetypes.GetCategoryID(typeID)
    512         droneState = sm.GetService('michelle').GetDroneState(droneID)
    513         drone = DroneChecker(Bundle(itemID=droneID, typeID=typeID, groupID=groupID, categoryID=categoryID, ownerID=ownerID, locationID=locationID, droneState=droneState))
    514         m = MenuList()
    515         if drone.OfferEngageTarget():
    516             targetID = sm.GetService('target').GetActiveTargetID()
    517             crimewatchSvc = sm.GetService('crimewatchSvc')
    518             requiredSafetyLevel = crimewatchSvc.GetRequiredSafetyLevelForEngagingDrones([droneID], targetID)
    519             menuClass = None
    520             if crimewatchSvc.CheckUnsafe(requiredSafetyLevel):
    521                 menuClass = eveMenu.CriminalMenuEntryView if requiredSafetyLevel == const.shipSafetyLevelNone else eveMenu.SuspectMenuEntryView
    522             m.append(DroneEngageTargetMenuEntryData(MenuLabel('UI/Drones/EngageTarget'), lambda : self.EngageTarget([droneID]), droneIDs=[droneID], menuEntryViewClass=menuClass))
    523         elif drone.failure_label:
    524             m.reasonsWhyNotAvailable['UI/Drones/EngageTarget'] = self.GetUnavailableText(drone)
    525         if drone.OfferMineWithDrone():
    526             m += [[MenuLabel('UI/Drones/MineWithDrone'), self.MineRepeatedly, [droneID]]]
    527         elif drone.OfferSalvage():
    528             m += [[MenuLabel('UI/Drones/Salvage'), self.Salvage, [[droneID]]]]
    529         elif drone.failure_label:
    530             m.reasonsWhyNotAvailable['UI/Drones/MineWithDrone'] = self.GetUnavailableText(drone)
    531         if drone.OfferDroneAssist():
    532             m += [[MenuLabel('UI/Drones/DroneAssist'), ('isDynamic', self.GetFleetMemberMenu, (self.Assist,)), [droneID]]]
    533         if drone.OfferDroneGuard():
    534             m += [[MenuLabel('UI/Drones/DroneGuard'), ('isDynamic', self.GetFleetMemberMenu, (self.Guard,)), [droneID]]]
    535         if drone.OfferDroneUnanchorObject():
    536             m += [[MenuLabel('UI/Inflight/UnanchorObject'), self.DroneUnanchor, [droneID]]]
    537         elif drone.failure_label:
    538             m.reasonsWhyNotAvailable['UI/Inflight/UnanchorObject'] = self.GetUnavailableText(drone)
    539         if drone.OfferReturnAndOrbit():
    540             m += [[MenuLabel('UI/Drones/ReturnDroneAndOrbit'), self.ReturnAndOrbit, [droneID]]]
    541         elif drone.failure_label:
    542             m.reasonsWhyNotAvailable['UI/Drones/ReturnDroneAndOrbit'] = self.GetUnavailableText(drone)
    543         if drone.OfferReturnToDroneBay():
    544             m += [[MenuLabel('UI/Drones/ReturnDroneToBay'), self.ReturnToDroneBay, [droneID]]]
    545         elif drone.failure_label:
    546             m.reasonsWhyNotAvailable['UI/Drones/ReturnDroneToBay'] = self.GetUnavailableText(drone)
    547         if drone.OfferScoopDroneToBay():
    548             m += [MenuEntryData(MenuLabel('UI/Drones/ScoopDroneToBay'), func=lambda : self.ScoopToDroneBay((droneID,)))]
    549         elif drone.failure_label:
    550             m.reasonsWhyNotAvailable['UI/Drones/ScoopDroneToBay'] = self.GetUnavailableText(drone)
    551         if drone.OfferAbandonDrone():
    552             m += [[MenuLabel('UI/Drones/AbandonDrone'), self.AbandonDrone, [droneID]]]
    553         return m
    554 
    555     def GetUnavailableText(self, entity):
    556         if entity.failure_label:
    557             return localization.GetByLabel(entity.failure_label, **entity.label_args)
    558 
    559     def CharacterMenu(self, charid, **kwargs):
    560         if type(charid) == list:
    561             menus = []
    562             for charID in charid:
    563                 menus.append(self._CharacterMenu(charID, (len(charid) > 1), **kwargs))
    564 
    565             return MergeMenus(menus)
    566         else:
    567             return self._CharacterMenu(charid, **kwargs)
    568 
    569     def _CharacterMenu(self, charID, multi = 0, **kwargs):
    570         if not charID:
    571             return MenuList()
    572         addressBookSvc = sm.GetService('addressbook')
    573         menuEntries = MenuList()
    574         if not self.sessionChecker:
    575             self.sessionChecker = SessionChecker(session, sm)
    576         character = CharacterChecker(charID, bool(multi), self.sessionChecker)
    577         if character.OfferShowInfo():
    578             menuEntries += [(MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo, (cfg.eveowners.Get(charID).typeID, charID))]
    579         if character.OfferStartConversation():
    580             menuEntries += [[MenuLabel('UI/Chat/StartConversation'), GetChatService().Invite, (charID, None, kwargs.get('isRecruiting', None))]]
    581         if character.OfferStartConversationAgent():
    582             menuEntries += [[MenuLabel('UI/Chat/StartConversationAgent'), sm.StartService('agents').OpenDialogueWindow, (charID,)]]
    583         if character.OfferAddToAddressBook():
    584             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/AddToAddressbook'), addressBookSvc.AddToPersonalMulti, [charID]]]
    585         if character.OfferInviteToChat():
    586             menuEntries += [[MenuLabel('UI/Chat/InviteToChat'), ('isDynamic', self.__GetInviteMenu, (charID,))]]
    587         if character.OfferSendPilotEVEMail():
    588             menuEntries += [[MenuLabel('UI/EVEMail/SendPilotEVEMail'), sm.StartService('mailSvc').SendMsgDlg, ([charID], None, None)]]
    589         if character.OfferAddContact():
    590             menuEntries.append(MenuEntryData(MenuLabel('UI/PeopleAndPlaces/AddContact'), lambda : addressBookSvc.AddToPersonalMulti([charID], 'contact'), texturePath=eveicon.add))
    591         if character.OfferEditContact():
    592             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/EditContact'), addressBookSvc.AddToPersonalMulti, [charID, 'contact', True]]]
    593         if character.OfferRemoveContact():
    594             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/RemoveContact'), addressBookSvc.DeleteEntryMulti, [[charID], 'contact']]]
    595         if character.OfferRemoveFromAddressbook():
    596             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/RemoveFromAddressbook'), addressBookSvc.DeleteEntryMulti, [charID]]]
    597         if character.OfferUnblockContact():
    598             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/UnblockContact'), addressBookSvc.UnblockOwner, ([charID],)]]
    599         if character.OfferBlockContact():
    600             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/BlockContact'), addressBookSvc.BlockOwner, (charID,)]]
    601         if character.OfferAddCorpContact():
    602             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/AddCorpContact'), addressBookSvc.AddToPersonalMulti, [charID, 'corpcontact']]]
    603         if character.OfferRemoveCorpContact():
    604             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/RemoveCorpContact'), addressBookSvc.DeleteEntryMulti, [[charID], 'corpcontact']]]
    605         if character.OfferEditCorpContact():
    606             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/EditCorpContact'), addressBookSvc.AddToPersonalMulti, [charID, 'corpcontact', True]]]
    607         if character.OfferAddAllianceContact():
    608             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/AddAllianceContact'), addressBookSvc.AddToPersonalMulti, [charID, 'alliancecontact']]]
    609         if character.OfferRemoveAllianceContact():
    610             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/RemoveAllianceContact'), addressBookSvc.DeleteEntryMulti, [[charID], 'alliancecontact']]]
    611         if character.OfferEditEditAllianceContact():
    612             menuEntries += [[MenuLabel('UI/PeopleAndPlaces/EditAllianceContact'), addressBookSvc.AddToPersonalMulti, [charID, 'alliancecontact', True]]]
    613         if character.OfferGiveMoney():
    614             menuEntries += [[MenuLabel('UI/Commands/GiveMoney'), sm.StartService('wallet').TransferMoney, (session.charid,
    615                None,
    616                charID,
    617                None)]]
    618         if character.OfferCloneInstallation():
    619             menuEntries += [[MenuLabel('UI/CloneJump/OfferCloneInstallation'), sm.StartService('clonejump').OfferShipCloneInstallation, (charID,)]]
    620         if character.OfferMapMenu():
    621             menuEntries += [None]
    622             menuEntries += self._MapMenu(character.GetAgentLocation())
    623             agentInfo = character.GetAgentInfo()
    624             if session.solarsystemid and agentInfo.solarsystemID == session.solarsystemid and agentInfo.stationID and not session.structureid:
    625                 menuEntries += [[MenuLabel('UI/Inflight/DockInStation'),
    626                   self.Dock,
    627                   (agentInfo.stationID,),
    628                   None,
    629                   None,
    630                   'DockInStation']]
    631         if character.OfferTradeWithCharacter():
    632             menuEntries += [[MenuLabel('UI/Market/TradeWithCharacter'), sm.GetService('pvptrade').StartTradeSession, (charID,)]]
    633         if character.OfferPlaceBounty():
    634             menuEntries += [[MenuLabel('UI/Station/BountyOffice/PlaceBounty'), openFunctions.OpenBountyOffice, (charID,)]]
    635         if character.OfferCapturePortrait():
    636             menuEntries += [[MenuLabel('UI/Commands/CapturePortrait'), sm.StartService('photo').SavePortraits, [charID]]]
    637         if character.OfferInvitePilotToFleet():
    638             menuEntries += [[MenuLabel('UI/Fleet/InvitePilotToFleet'), self.FleetInviteMenu(charID)]]
    639         if character.OfferInvitePilotToFleetMultiple():
    640             menuEntries += [[MenuLabel('UI/Fleet/InvitePilotToFleet'), self.InviteToFleet, [charID]]]
    641         if character.OfferFleetMenu():
    642             menuEntries += [[MenuLabel('UI/Fleet/Fleet'), ('isDynamic', self.FleetMenu, (charID, False))]]
    643         if character.OfferFormFleetWith():
    644             menuEntries += [[MenuLabel('UI/Fleet/FormFleetWith'), self.InviteToFleet, [charID]]]
    645         if character.OfferDuelMenuEntry():
    646             menuEntries += [[MenuLabel('UI/Crimewatch/Duel/DuelMenuEntry'), self.crimewatchSvc.StartDuel, (charID,)]]
    647         menuEntries += [None]
    648         if character.OfferViewCorpMemberDetails():
    649             menuEntries += [[MenuLabel('UI/Corporations/Common/ViewCorpMemberDetails'), self.ShowCorpMemberDetails, (charID,)]]
    650         if character.OfferEditCorpMember():
    651             menuEntries += [[MenuLabel('UI/Corporations/Common/EditCorpMember'), self.ShowCorpMemberDetails, (charID,)]]
    652         if character.OfferAllowCorpRoles():
    653             allowRolesMenu = [[MenuLabel('UI/Corporations/Common/ConfirmAllowCorpRoles'), sm.StartService('corp').UpdateMember, (session.charid,
    654                None,
    655                None,
    656                None,
    657                None,
    658                None,
    659                None,
    660                None,
    661                None,
    662                None,
    663                None,
    664                None,
    665                None,
    666                None,
    667                0)]]
    668             menuEntries += [[MenuLabel('UI/Corporations/Common/AllowCorpRoles'), allowRolesMenu]]
    669         if character.OfferTransferCorpCash():
    670             menuEntries += [[MenuLabel('UI/Corporations/Common/TransferCorpCash'), sm.StartService('wallet').TransferMoney, (session.corpid,
    671                None,
    672                charID,
    673                None)]]
    674         if character.OfferQuitCorp():
    675             quitCorpMenu = [[MenuLabel('UI/Corporations/Common/RemoveAllCorpRoles'), sm.StartService('corp').RemoveAllRoles, ()], [MenuLabel('UI/Corporations/Common/ConfirmQuitCorp'), sm.StartService('corp').KickOut, (charID,)]]
    676             menuEntries += [[MenuLabel('UI/Corporations/Common/QuitCorp'), quitCorpMenu]]
    677         if character.OfferExpelCorpMember():
    678             if multi:
    679                 expelMenu = [[MenuLabel('UI/Corporations/Common/ConfirmExpelMembers'), sm.StartService('corp').KickOutMultipleMembers, [charID]]]
    680                 menuEntries += [[MenuLabel('UI/Corporations/Common/ExpelCorpMembers'), expelMenu]]
    681             else:
    682                 expelMenu = [[MenuLabel('UI/Corporations/Common/ConfirmExpelMember'), sm.StartService('corp').KickOut, (charID,)]]
    683                 menuEntries += [[MenuLabel('UI/Corporations/Common/ExpelCorpMember'), expelMenu]]
    684         if character.OfferResignAsCEO():
    685             resignMenu = [[MenuLabel('UI/Corporations/Common/ConfirmResignAsCEO'), sm.StartService('corp').ResignFromCEO, ()]]
    686             menuEntries += [[MenuLabel('UI/Corporations/Common/ResignAsCEO'), resignMenu]]
    687         if character.OfferAwardCorpMemberDecoration():
    688             menuEntries += [[MenuLabel('UI/Corporations/Common/AwardCorpMemberDecoration'), self.AwardDecoration, [charID]]]
    689         if character.OfferSendCorpInvite():
    690             menuEntries += [[MenuLabel('UI/Corporations/Common/SendCorpInvite'), sm.StartService('corp').InviteToJoinCorp, (charID,)]]
    691         if boot.region == 'optic':
    692             if character.OfferReportMenuEntry():
    693                 menuEntries += [[MenuLabel('UI/Kiring/Report/ReportMenuEntry'), sm.GetService('reportClientSvc').Report, (charID,)]]
    694         if session.role & (ROLE_GML | ROLE_WORLDMOD | ROLE_LEGIONEER):
    695             menuEntries.insert(0, ('GM / WM Extras', ('isDynamic', self.GetGMMenu, (None,
    696                None,
    697                charID,
    698                None,
    699                None,
    700                None,
    701                kwargs.get('channelID', None)))))
    702         return menuEntries
    703 
    704     def FleetMenu(self, charID, unparsed = True):
    705         menuEntries = MenuList()
    706         if not self.sessionChecker:
    707             self.sessionChecker = SessionChecker(session, sm)
    708         member = FleetMemberChecker(charID, self.sessionChecker, cfg)
    709         if member.OfferShowInfo():
    710             menuEntries += [[MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo, (member.typeID,
    711                charID,
    712                0,
    713                None,
    714                None)]]
    715         if not member.IsFleetMember():
    716             return menuEntries
    717         fleetSvc = sm.GetService('fleet')
    718         defaultWarpDist = self.GetDefaultActionDistance('WarpTo')
    719         formationName = {'fleetFormation': GetSelectedFormationName()}
    720         if unparsed:
    721             menuEntries += [None]
    722         if member.OfferKickFleetMember():
    723             menuEntries += [[MenuLabel('UI/Fleet/KickFleetMember'), self.ConfirmMenu(lambda *x: fleetSvc.KickMember(charID))]]
    724         if member.OfferMakeFleetLeader():
    725             menuEntries += [[MenuLabel('UI/Fleet/MakeFleetLeader'), fleetSvc.MakeLeader, (charID,)]]
    726         if member.OfferAddPilotToWatchlist():
    727             menuEntries += [[MenuLabel('UI/Fleet/AddPilotToWatchlist'), fleetSvc.AddFavorite, ([charID],)]]
    728         if member.OfferRemovePilotFromWatchlist():
    729             menuEntries += [[MenuLabel('UI/Fleet/RemovePilotFromWatchlist'), fleetSvc.RemoveFavorite, (charID,)]]
    730         if member.OfferBroadcastTravelToMe():
    731             menuEntries += [MenuEntryData(MenuLabel('UI/Fleet/FleetBroadcast/Commands/BroadcastTravelToMe'), lambda : sm.GetService('fleet').SendBroadcast_TravelTo(session.solarsystemid2), texturePath=iconsByBroadcastType[BROADCAST_TRAVEL_TO])]
    732         if member.OfferWarpToMember():
    733             menuEntries += [[MenuLabel('UI/Fleet/WarpToMember'), self.WarpToMember, (charID, float(defaultWarpDist))]]
    734             menuEntries += [[MenuLabel('UI/Fleet/WarpToMemberSubmenuOption'), self.WarpToMenu(self.WarpToMember, charID)]]
    735         if member.OfferWarpFleetToMember():
    736             menuEntries += [[MenuLabel('UI/Fleet/WarpFleetToMember', formationName), self.WarpFleetToMember, (charID, float(defaultWarpDist))]]
    737             menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/WarpFleetToMember', formationName), self.WarpToMenu(self.WarpFleetToMember, charID)]]
    738         if member.OfferWarpWingToMember():
    739             menuEntries += [[MenuLabel('UI/Fleet/WarpWingToMember', formationName), self.WarpFleetToMember, (charID, float(defaultWarpDist))]]
    740             menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/WarpWingToMember', formationName), self.WarpToMenu(self.WarpFleetToMember, charID)]]
    741         if member.OfferWarpSquadToMember():
    742             menuEntries += [[MenuLabel('UI/Fleet/WarpSquadToMember', formationName), self.WarpFleetToMember, (charID, float(defaultWarpDist))]]
    743             menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/WarpSquadToMember', formationName), self.WarpToMenu(self.WarpFleetToMember, charID)]]
    744         if member.OfferJumpToFleetMember():
    745             menuEntries += [[MenuLabel('UI/Inflight/JumpToFleetMember'), self.JumpToMember, (charID,)]]
    746         if member.OfferBridgeToMember():
    747             menuEntries += [[MenuLabel('UI/Fleet/BridgeToMember'), self.BridgeToMember, (charID,)]]
    748         if member.OfferGroupJumpToFleetMember():
    749             menuEntries += [[MenuLabel('UI/Fleet/ConduitJumpToFleetMember'), self.GroupJumpToMember, (charID,)]]
    750         if member.IsMe():
    751             menuEntries += [[MenuLabel('UI/Fleet/LeaveMyFleet'), self.ConfirmMenu(fleetSvc.LeaveFleet)]]
    752         moveMenu = self.GetFleetMemberMenu2(charID, fleetSvc.MoveMember, True)
    753         if moveMenu:
    754             menuEntries.extend([[MenuLabel('UI/Fleet/FleetSubmenus/MoveFleetMember'), moveMenu]])
    755         return menuEntries
    756 
    757     def FleetInviteMenu(self, charID):
    758         return self.GetFleetMemberMenu2(charID, lambda *args: self.DoInviteToFleet(*args))
    759 
    760     @staticmethod
    761     def GetFleetMemberMenu2(charID, callback, isMove = False):
    762         wings = sm.GetService('fleet').GetWings()
    763         members = sm.GetService('fleet').GetMembers()
    764         ret = evefleet.client.MemberMenu(charID, wings, members, callback, sm.GetService('fleet').GetOptions().isFreeMove, isMove, MenuLabel, localization.GetByLabel).Get()
    765         return ret
    766 
    767     @staticmethod
    768     def DoInviteToFleet(charID, wingID, squadID, role):
    769         sm.GetService('fleet').Invite(charID, wingID, squadID, role)
    770 
    771     @staticmethod
    772     def AwardDecoration(charIDs):
    773         return menuFunctions.AwardDecoration(charIDs)
    774 
    775     @staticmethod
    776     def ShowCorpMemberDetails(charID):
    777         OpenMemberDetails(charID)
    778 
    779     @staticmethod
    780     def __GetInviteMenu(charID):
    781 
    782         def Invite(characterID, channelID):
    783             GetChatService().Invite(characterID, channelID)
    784 
    785         channels = GetChatService().GetChannelsAvailableForInvite(charID)
    786         inviteMenu = []
    787         for channel in channels:
    788             inviteMenu += [[GetChatService().GetDisplayName(channel), Invite, (charID, channel)]]
    789 
    790         inviteMenu.sort()
    791         inviteMenu = [[MenuLabel('UI/Chat/StartConversation'), Invite, (charID, None)]] + inviteMenu
    792         return MenuList(inviteMenu)
    793 
    794     @staticmethod
    795     def SlashCmd(cmd):
    796         return devFunctions.SlashCmd(cmd)
    797 
    798     @staticmethod
    799     def SlashCmdTr(cmd):
    800         return devFunctions.SlashCmdTr(cmd)
    801 
    802     def GetGMTypeMenu(self, typeID, itemID = None, divs = False, unload = False):
    803         if not session.role & (ROLE_GML | ROLE_WORLDMOD):
    804             return []
    805 
    806         def _wrapMulti(command, what = None, maxValue = 2147483647):
    807             if uicore.uilib.Key(uiconst.VK_SHIFT):
    808                 if not what:
    809                     what = command.split(' ', 1)[0]
    810                 result = uix.QtyPopup(maxvalue=maxValue, minvalue=1, caption=what, label=localization.GetByLabel('UI/Common/Quantity'), hint='')
    811                 if result:
    812                     qty = result['qty']
    813                 else:
    814                     return
    815             else:
    816                 qty = 1
    817             return sm.GetService('slash').SlashCmd(command % qty)
    818 
    819         cat = evetypes.GetCategoryID(typeID)
    820         if unload:
    821             if type(itemID) is tuple:
    822                 for row in self.invCache.GetInventoryFromId(itemID[0]).ListHardwareModules():
    823                     if row.flagID == itemID[1]:
    824                         itemID = row.itemID
    825                         break
    826                 else:
    827                     itemID = None
    828 
    829             else:
    830                 charge = self.godma.GetItem(itemID)
    831                 if charge and charge.categoryID == const.categoryCharge:
    832                     for row in self.invCache.GetInventoryFromId(charge.locationID).ListHardwareModules():
    833                         if row.flagID == charge.flagID and row.itemID != itemID:
    834                             itemID = row.itemID
    835                             break
    836                     else:
    837                         itemID = None
    838 
    839         gm = MenuList()
    840         if divs:
    841             gm.append(None)
    842         if session.role & (ROLE_WORLDMOD | ROLE_SPAWN):
    843             if not session.stationid:
    844                 if cat in (const.categoryShip, const.categoryStructure):
    845                     gm.append(('WM: /Spawn this type', lambda *x: _wrapMulti('/spawnN %%d 4000 %d' % typeID, '/Spawn', 50)))
    846                     if itemID:
    847                         gm.append(('WM: /Unspawn this item', lambda *x: sm.RemoteSvc('slash').SlashCmd('/unspawn %d' % itemID)))
    848                 if cat == const.categoryEntity:
    849                     gm.append(('WM: /Entity deploy this type', lambda *x: _wrapMulti('/entity deploy %%d %d' % typeID, '/Entity', 100)))
    850         gm.append(None)
    851         gm.append(('typeID: ' + str(typeID) + ' (%s)' % evetypes.GetName(typeID), blue.pyos.SetClipboardData, (str(typeID),)))
    852         group = evetypes.GetGroupID(typeID)
    853         gm.append(('groupID: ' + str(group) + ' (%s)' % evetypes.GetGroupName(typeID), blue.pyos.SetClipboardData, (str(group),)))
    854         category = evetypes.GetCategoryID(typeID)
    855         categoryName = evetypes.GetCategoryNameByCategory(category)
    856         gm.append(('categID: ' + str(category) + ' (%s)' % categoryName, blue.pyos.SetClipboardData, (str(category),)))
    857         graphic = inventorycommon.typeHelpers.GetGraphic(typeID)
    858         if graphic is not None:
    859             gm.append(('graphicID: ' + str(evetypes.GetGraphicID(typeID)), blue.pyos.SetClipboardData, (str(evetypes.GetGraphicID(typeID)),)))
    860             if hasattr(graphic, 'graphicFile'):
    861                 gm.append(('graphicFile: ' + str(graphic.graphicFile), blue.pyos.SetClipboardData, (str(graphic.graphicFile),)))
    862         gm.append(None)
    863         if typeID != const.typeSolarSystem and cat not in [const.categoryStation, const.categoryOwner]:
    864             if session.role & ROLE_WORLDMOD:
    865                 gm.append(('WM: /create this type', lambda *x: _wrapMulti('/create %d %%d' % typeID)))
    866             gm.append(('GM: /load me this type', lambda *x: _wrapMulti('/load me %d %%d' % typeID)))
    867             graphicID = evetypes.GetGraphicID(typeID)
    868             graphic = fsdGraphicIDs.GetGraphic(graphicID)
    869             graphicFile = fsdGraphicIDs.GetGraphicFile(graphic)
    870             sofHull = fsdGraphicIDs.GetSofHullName(graphic)
    871             if session.stationid is not None:
    872                 graphicsItems = [('typeID: ' + str(typeID), blue.pyos.SetClipboardData, (str(typeID),)),
    873                  ('graphicID: ' + str(graphicID), blue.pyos.SetClipboardData, (str(graphicID),)),
    874                  ('graphicFile: ' + str(graphicFile), blue.pyos.SetClipboardData, (str(graphicFile),)),
    875                  ('SOF hull: ' + str(sofHull), blue.pyos.SetClipboardData, (str(sofHull),))]
    876                 if itemID is not None and self.godma.GetItem(itemID) is not None:
    877                     dirtTimeStamp = eveMoniker.GetShipAccess().GetDirtTimestamp(itemID)
    878                     dirtTimeStampStr = fmtutil.FmtDateEng(dirtTimeStamp)
    879                     dirtTimeDiff = blue.os.TimeDiffInMs(dirtTimeStamp, blue.os.GetWallclockTime())
    880                     killCounter = sm.RemoteSvc('shipKillCounter').GetItemKillCountPlayer(itemID)
    881                     graphicsItems += [None,
    882                      ('Last cleaning: ' + str(dirtTimeStampStr), blue.pyos.SetClipboardData, (str(dirtTimeStampStr),)),
    883                      ('msecs since last cleaning: ' + str(dirtTimeDiff), blue.pyos.SetClipboardData, (str(dirtTimeDiff),)),
    884                      None,
    885                      ('kill counter: ' + str(killCounter), blue.pyos.SetClipboardData, (str(killCounter),))]
    886                 gm.append(('graphics', graphicsItems))
    887         if IsShipFittable(cat):
    888             gm.append(('GM: /fit me this type', lambda *x: _wrapMulti('/loop %%d /fit me %d' % typeID, '/Fit', 8)))
    889             if unload:
    890                 if itemID:
    891                     gm.append(('GM: /unload me this item', lambda *x: sm.RemoteSvc('slash').SlashCmd('/unload me %d' % itemID)))
    892                 gm.append(('GM: /unload me this type', lambda *x: sm.RemoteSvc('slash').SlashCmd('/unload me %d' % typeID)))
    893                 if itemID:
    894                     module = self.godma.GetItem(itemID)
    895                     if module and module.damage:
    896                         gm.append(('GM: Repair this module', lambda *x: sm.RemoteSvc('slash').SlashCmd('/heal %d' % itemID)))
    897         if itemID:
    898             gm.append(get_space_components_menu(itemID, typeID))
    899             gm.append(('GM: Inspect Attributes', self.InspectAttributes, (itemID, typeID)))
    900         if session.role & ROLE_PROGRAMMER:
    901             gm.append(('PROG: Modify Attributes', ('isDynamic', self.AttributeMenu, (itemID, typeID))))
    902         import webbrowser
    903         gm.append(MenuEntryData('Show in FSD editor', lambda : webbrowser.open_new('http://localhost:8000/specializedtypes/categories/{category_id}/groups/{group_id}/types/{type_id}/'.format(category_id=evetypes.GetCategoryID(typeID), group_id=evetypes.GetGroupID(typeID), type_id=typeID))))
    904         gm.append(None)
    905         gm.extend(expertSystems.get_gm_menu_options(typeID))
    906         if divs:
    907             gm.append(None)
    908         return gm
    909 
    910     @staticmethod
    911     def InspectAttributes(itemID, typeID):
    912         AttributeInspector.Open(itemID=itemID, typeID=typeID)
    913 
    914     @staticmethod
    915     def InspectSlimItem(itemID):
    916         from eve.devtools.script.slimItemInspector import SlimItemInspector
    917         windowID = 'slimItemInspector_%s' % itemID
    918         SlimItemInspector.Open(itemID=itemID, windowID=windowID)
    919 
    920     @staticmethod
    921     def NPCInfoMenu(item):
    922         return devFunctions.NPCInfoMenu(item)
    923 
    924     @staticmethod
    925     def AttributeMenu(itemID, typeID):
    926         return devFunctions.AttributeMenu(itemID, typeID)
    927 
    928     @staticmethod
    929     def SetDogmaAttribute(itemID, attrName, actualValue):
    930         return devFunctions.SetDogmaAttribute(itemID, attrName, actualValue)
    931 
    932     @staticmethod
    933     def GagPopup(charID, channelID, numMinutes):
    934         return devFunctions.GagPopup(charID, channelID, numMinutes)
    935 
    936     @staticmethod
    937     def Ungag(charID, channelID):
    938         return devFunctions.Ungag(charID, channelID)
    939 
    940     @staticmethod
    941     def ReportISKSpammer(charID, channelID):
    942         sm.GetService('chat').report_isk_spammer(charID, channelID)
    943 
    944     @staticmethod
    945     def BanIskSpammer(charID):
    946         return devFunctions.BanIskSpammer(charID)
    947 
    948     @staticmethod
    949     def GagIskSpammer(charID):
    950         return devFunctions.GagIskSpammer(charID)
    951 
    952     @staticmethod
    953     def GetFromESP(action):
    954         return devFunctions.GetFromESP(action)
    955 
    956     def GetFitMenu(self, item, typeID):
    957         from shipfitting.multiFitMenu import GetMultiFitMenu
    958         return GetMultiFitMenu(item, typeID)
    959 
    960     @staticmethod
    961     def FitStack(item, fit):
    962         from eve.client.script.ui.shared.fitting.multiFitWnd import MultiFitWnd
    963         maxShipsAllowed = GetMaxShipsToFit(sm.GetService('machoNet'))
    964         wnd = MultiFitWnd.GetIfOpen()
    965         if wnd:
    966             wnd.LoadWindow(fit, min(item.stacksize, maxShipsAllowed))
    967         else:
    968             MultiFitWnd.Open(fitting=fit, qty=min(item.stacksize, maxShipsAllowed))
    969 
    970     def GetSkinLicenseMenu(self, invItem, itemChecker):
    971         submenu = MenuList()
    972         submenu.append([MenuLabel('UI/Commands/ActivateSkinLicense'), menuFunctions.ActivateShipSkinLicense, [[(invItem.itemID, invItem.typeID)]]])
    973         if itemChecker.IsSkinForCurrentShip():
    974             submenu.append([MenuLabel('UI/Commands/ActivateAndApplySkinLicense'), menuFunctions.ActivateShipSkinLicenseAndApply, (invItem.itemID, invItem.typeID)])
    975         else:
    976             submenu.append([MenuLabel('UI/Commands/ActivateAndApplySkinLicenseDisabled'), DISABLED_ENTRY0])
    977             submenu.reasonsWhyNotAvailable['UI/Commands/ActivateAndApplySkinLicense'] = localization.GetByLabel('UI/Menusvc/MenuHints/SkinNotForCurrentShip')
    978         return submenu
    979 
    980     def GetGMMenu(self, itemID = None, slimItem = None, charID = None, invItem = None, mapItem = None, typeID = None, channelID = None):
    981         if not session.role & (ROLE_GML | ROLE_WORLDMOD):
    982             if charID and session.role & ROLE_LEGIONEER:
    983                 return [('Gag ISK Spammer', self.GagIskSpammer, (charID,))]
    984             return MenuList()
    985         gm = MenuList()
    986         gm += [(str(itemID or charID), blue.pyos.SetClipboardData, (str(itemID or charID),))]
    987         if mapItem and not slimItem:
    988             gm.append(('TR me here!', self.SlashCmdTr, ('/tr me ' + str(mapItem.itemID),)))
    989             gm.append(None)
    990         elif charID:
    991             gm.append(('TR me to %s' % cfg.eveowners.Get(charID).name, self.SlashCmdTr, ('/tr me ' + str(charID),)))
    992             if not devtools_util.is_built_client() and idCheckers.IsNPC(charID):
    993                 gm.append(None)
    994                 gm.append(MenuEntryData('Show in FSD Editor', lambda : webbrowser.open('http://localhost:8000/npccharacters/{}'.format(charID))))
    995                 from eve.devtools.script.npc_paperdoll_randomizer.paperdoll_randomizer_window import NPCPaperdollRandomizerWindow
    996                 gm.append(MenuEntryData('Edit with Paperdoll Randomizer Tool', lambda : NPCPaperdollRandomizerWindow.OpenOrShow(npc_id=charID), texturePath=eveicon.randomize))
    997             gm.append(None)
    998         elif slimItem:
    999             gm.append(('TR me here!', self.SlashCmdTr, ('/tr me ' + str(itemID),)))
   1000             gm.append(None)
   1001         elif itemID:
   1002             gm.append(('TR me here!', self.SlashCmdTr, ('/tr me ' + str(itemID),)))
   1003             gm.append(None)
   1004         if invItem:
   1005             gm += [('Copy ID/Qty', self.CopyItemIDAndMaybeQuantityToClipboard, (invItem,))]
   1006             typeText = 'copy typeID (%s)' % invItem.typeID
   1007             gm += [(typeText, blue.pyos.SetClipboardData, (str(invItem.typeID),))]
   1008             gm.append(None)
   1009             typeID = invItem.typeID
   1010             if invItem.locationID and not idCheckers.IsSolarSystem(invItem.locationID):
   1011                 try:
   1012                     inv = self.invCache.GetInventoryFromId(invItem.locationID)
   1013                     gm.append(('QA LOCK ITEM', inv.QALockItem, (invItem.itemID,)))
   1014                     gm.append(('QA UNLOCK ITEM', inv.QAUnlockItem, (invItem.itemID,)))
   1015                 except Exception:
   1016                     pass
   1017 
   1018         if charID and not idCheckers.IsNPC(charID):
   1019             action = 'gm/character.py?action=Character&characterID=' + str(charID)
   1020             gm.append(('Show in ESP', self.GetFromESP, (action,)))
   1021             gm.append(None)
   1022             gm.append(('Gag ISK Spammer', self.GagIskSpammer, (charID,)))
   1023             gm.append(('Ban ISK Spammer', self.BanIskSpammer, (charID,)))
   1024             action = 'gm/users.py?action=BanUserByCharacterID&characterID=' + str(charID)
   1025             gm.append(('Ban User (ESP)', self.GetFromESP, (action,)))
   1026             gm += [('Gag User', [('30 minutes', self.GagPopup, (charID, channelID, 30)),
   1027                ('1 hour', self.GagPopup, (charID, channelID, 60)),
   1028                ('6 hours', self.GagPopup, (charID, channelID, 360)),
   1029                ('24 hours', self.GagPopup, (charID, channelID, 1440)),
   1030                None,
   1031                ('Ungag', self.Ungag, (charID, channelID))])]
   1032         gm.append(None)
   1033         item = slimItem or invItem
   1034         if item:
   1035             if item.categoryID == const.categoryShip and (item.singleton or not session.stationid):
   1036                 from eve.devtools.script import dna
   1037                 if item.ownerID in [session.corpid, session.charid] or session.role & ROLE_WORLDMOD:
   1038                     try:
   1039                         menu = dna.Ship().ImportFromShip(shipID=item.itemID, ownerID=item.ownerID, deferred=True).GetMenuInline(spiffy=False, fit=item.itemID != session.shipid)
   1040                         gm.append(('Copycat', menu))
   1041                     except RuntimeError:
   1042                         pass
   1043 
   1044                 gm += [('/Online modules', lambda shipID = item.itemID: self.SlashCmd('/online %d' % shipID))]
   1045             gm += self.GetGMTypeMenu(item.typeID, itemID=item.itemID)
   1046             if getattr(slimItem, 'categoryID', None) == const.categoryEntity or getattr(slimItem, 'groupID', None) == const.groupWreck:
   1047                 gm.append(('NPC Info', ('isDynamic', self.NPCInfoMenu, (item,))))
   1048             gm.append(None)
   1049         elif typeID:
   1050             gm += self.GetGMTypeMenu(typeID)
   1051         if session.role & ROLE_CONTENT:
   1052             if slimItem:
   1053                 if getattr(slimItem, 'dunObjectID', None) is not None:
   1054                     if not sm.StartService('scenario').IsSelected(itemID):
   1055                         gm.append(('Add to Selection', sm.StartService('scenario').AddSelected, (itemID,)))
   1056                     else:
   1057                         gm.append(('Remove from Selection', sm.StartService('scenario').RemoveSelected, (itemID,)))
   1058         if slimItem:
   1059             itemID = slimItem.itemID
   1060             graphicID = evetypes.GetGraphicID(item.typeID)
   1061             if slimItem.categoryID == const.categoryStation and slimItem.itemID:
   1062                 npcStation = cfg.mapSolarSystemContentCache.npcStations.get(itemID, None)
   1063                 if npcStation:
   1064                     graphicID = npcStation.graphicID
   1065             graphic = fsdGraphicIDs.GetGraphic(graphicID)
   1066             graphicFile = fsdGraphicIDs.GetGraphicFile(graphic)
   1067             raceName = fsdGraphicIDs.GetSofRaceName(graphic)
   1068             sofDNA = None
   1069             ball = sm.StartService('michelle').GetBallpark().GetBall(slimItem.itemID)
   1070             subMenu = self.GetGMStructureStateMenu(itemID, slimItem)
   1071             if len(subMenu) > 0:
   1072                 gm += [('Change State', subMenu)]
   1073             gm += self.GetGMBallsAndBoxesMenu(itemID, slimItem, charID, invItem, mapItem)
   1074             slimItemAttributes = []
   1075             for k, v in slimItem.__dict__.items():
   1076                 if k.startswith('__'):
   1077                     continue
   1078                 txt = '%s = %s' % (k, v)
   1079                 if len(txt) > 80:
   1080                     label = eveformat.simple_html_escape(txt[:60]) + ' ...'
   1081                 else:
   1082                     label = eveformat.simple_html_escape(txt)
   1083                 slimItemAttributes.append((label, blue.pyos.SetClipboardData, (txt,)))
   1084 
   1085             slimItemAttributes.sort()
   1086             if len(slimItemAttributes) > 0:
   1087                 gm += [('Slim attributes', slimItemAttributes)]
   1088                 gm += [('Slim attributes inspector', self.InspectSlimItem, (itemID,))]
   1089             dirtLastClean = None
   1090             dirtCurrentValue = None
   1091             if ball is not None:
   1092                 if hasattr(ball, 'GetDirtTimeStampAsStr'):
   1093                     dirtLastClean = ball.GetDirtTimeStampAsStr()
   1094                 if hasattr(ball, 'model'):
   1095                     if ball.model is not None:
   1096                         dirtCurrentValue = getattr(ball.model, 'dirtLevel', None)
   1097             currentKillCount = None
   1098             if ball is not None:
   1099                 if hasattr(ball, 'model'):
   1100                     if ball.model is not None:
   1101                         currentKillCount = getattr(ball.model, 'displayKillCounterValue', None)
   1102             currentGeoLODstr = 'INVALID'
   1103             currentGeoLOD = ''
   1104             currentTexLODmenu = []
   1105             impostorMode = None
   1106             if ball is not None:
   1107                 if hasattr(ball, 'model'):
   1108                     if ball.model is not None:
   1109                         if hasattr(ball.model, 'mesh'):
   1110                             if ball.model.mesh is not None:
   1111                                 currentGeoLODstr = ball.model.mesh.GetGeometryResPath()
   1112                                 try:
   1113                                     currentGeoLOD = ball.model.GetLastUsedMeshLod() + 1
   1114                                 except AttributeError:
   1115                                     pass
   1116 
   1117                                 paramLst = ball.model.mesh.Find('trinity.TriTextureParameter')
   1118                                 currentTexLODstr = {}
   1119                                 for param in paramLst:
   1120                                     mip = str(getattr(param.resource, 'gpuMip', ''))
   1121                                     currentTexLODstr[param.resourcePath.lower()] = mip
   1122 
   1123                                 for param, mip in currentTexLODstr.iteritems():
   1124                                     currentTexLODmenu.append(('%s: %s' % (param, mip), blue.pyos.SetClipboardData, (str(param),)))
   1125 
   1126                         if hasattr(ball.model, 'dna'):
   1127                             sofDNA = ball.model.dna
   1128                         if hasattr(ball.model, 'IsImpostor'):
   1129                             impostorMode = ball.model.IsImpostor()
   1130             gm.append(None)
   1131             gm.append(('charID: ' + self.GetOwnerLabel(slimItem.charID), blue.pyos.SetClipboardData, (str(slimItem.charID),)))
   1132             gm.append(('ownerID: ' + self.GetOwnerLabel(slimItem.ownerID), blue.pyos.SetClipboardData, (str(slimItem.ownerID),)))
   1133             gm.append(('corpID: ' + self.GetOwnerLabel(slimItem.corpID), blue.pyos.SetClipboardData, (str(slimItem.corpID),)))
   1134             gm.append(('allianceID: ' + self.GetOwnerLabel(slimItem.allianceID), blue.pyos.SetClipboardData, (str(slimItem.allianceID),)))
   1135             if hasattr(slimItem, 'districtID'):
   1136                 gm.append(('districtID: ' + str(slimItem.districtID), blue.pyos.SetClipboardData, (str(slimItem.districtID),)))
   1137             gm.append(None)
   1138             gm.append(('typeID: ' + str(slimItem.typeID) + ' (%s)' % evetypes.GetName(slimItem.typeID), blue.pyos.SetClipboardData, (str(slimItem.typeID),)))
   1139             gm.append(('groupID: ' + str(slimItem.groupID) + ' (%s)' % evetypes.GetGroupNameByGroup(slimItem.groupID), blue.pyos.SetClipboardData, (str(slimItem.groupID),)))
   1140             gm.append(('categID: ' + str(slimItem.categoryID) + ' (%s)' % evetypes.GetCategoryNameByCategory(slimItem.categoryID), blue.pyos.SetClipboardData, (str(slimItem.categoryID),)))
   1141             graphics_items = [('graphicID: ' + str(graphicID), blue.pyos.SetClipboardData, (str(graphicID),)),
   1142              ('graphicFile: ' + str(graphicFile), blue.pyos.SetClipboardData, (str(graphicFile),)),
   1143              ('SOF DNA: ' + str(sofDNA), blue.pyos.SetClipboardData, (str(sofDNA),)),
   1144              ('materialSetID: ' + str(slimItem.skinMaterialSetID), blue.pyos.SetClipboardData, (str(slimItem.skinMaterialSetID),)),
   1145              ('race: ' + str(raceName), blue.pyos.SetClipboardData, (str(raceName),)),
   1146              None,
   1147              ('current geo LOD: %s %s' % (currentGeoLODstr, currentGeoLOD), blue.pyos.SetClipboardData, (currentGeoLODstr,)),
   1148              ('current tex LODs', currentTexLODmenu),
   1149              ('current impostor mode: ' + str(impostorMode), blue.pyos.SetClipboardData, (str(impostorMode),)),
   1150              None,
   1151              ('Last cleaning: ' + str(dirtLastClean), blue.pyos.SetClipboardData, (str(dirtLastClean),)),
   1152              ('Current dirt value: ' + str(dirtCurrentValue), blue.pyos.SetClipboardData, (str(dirtCurrentValue),)),
   1153              None,
   1154              ('Current kill count: ' + str(currentKillCount), blue.pyos.SetClipboardData, (str(currentKillCount),)),
   1155              ('Randomize kill counter', self.RandomizeKillCounter, (ball,)),
   1156              ('Set kill counter', devFunctions.SetKillCounter, (ball,)),
   1157              None]
   1158             if evetypes.GetGroupID(typeID) == const.groupStargate:
   1159                 graphics_items.append(('Debug Stargate', lambda *x: StargateDebuggerViewController(itemID).ShowUI()))
   1160             graphics_items.append(('Debug model state', lambda *x: ModelStateDebuggerController(itemID).ShowUI()))
   1161             graphics_items.append(('Trinity Debug Items', modelDebugFunctions.GetTrinityDebugItems(itemID)))
   1162             graphics_items.append(('Textures', self.OpenTextureViewer, (ball,)))
   1163             graphics_items += [None,
   1164              ('Toggle Shield Ellipsoid', modelDebugFunctions.ShowShieldEllipsoid, (itemID,)),
   1165              ('Undocking Locators', modelDebugFunctions.ShowUndockLocations, (itemID,)),
   1166              None,
   1167              ('Save red file', self.SaveRedFile, (ball, graphicFile)),
   1168              ('Toggle display', self.ToggleDisplay, (ball,)),
   1169              ('Open Shader Debugger', self.ToggleShaderDebugger, (ball, graphicID)),
   1170              modelDebugFunctions.GetGMModelInfoMenuItem(itemID)]
   1171             if hasattr(ball, 'ForceAuroraNow'):
   1172                 graphics_items += [None, ('Next Aurora in %s' % self._FormatAuroraTime(ball.GetTimeUntilNextAurora()), lambda : None, ()), ('Force Aurora Now', ball.ForceAuroraNow, ())]
   1173             gm.append(('graphics', graphics_items))
   1174             try:
   1175                 from carbon.tools.jessica import jessica
   1176                 gm.append(('Select in Jessica', lambda *x: jessica.SetCurrentSelection([ball.model])))
   1177             except ImportError:
   1178                 pass
   1179 
   1180             try:
   1181                 from platformtools.compatibility.exposure.graphite.graphiteutils import IsGraphiteAttached, setCurrentSelection
   1182                 if IsGraphiteAttached():
   1183                     gm.append(('Select in Graphite', lambda *x: setCurrentSelection([ball.model], userDirected=True)))
   1184             except ImportError:
   1185                 pass
   1186 
   1187             if ball is not None:
   1188                 if hasattr(ball, 'model'):
   1189                     if ball.model is not None:
   1190                         gm.append(None)
   1191                         gm.append(('audio', [('audio emitters', AudioGmMenu(itemID).GetEmitterMenu())]))
   1192                         gm.append(None)
   1193             gm.append(None)
   1194             gm.append(('Copy Coordinates', self.CopyCoordinates, (itemID,)))
   1195             gm.append(None)
   1196             if HasBehaviorComponent(slimItem.typeID):
   1197                 gm.extend(behavior.GetBehaviorGMMenu(slimItem))
   1198             if IsSkyhook(slimItem.typeID):
   1199 
   1200                 def GMSetSkyhookState(skyhookID, skyhookState):
   1201                     sm.RemoteSvc('slash').SlashCmd('/skyhook state %d %d' % (skyhookID, skyhookState))
   1202 
   1203                 import orbitalSkyhook.const as reinforceConst
   1204                 states = [ [name, GMSetSkyhookState, [itemID, value]] for value, name in reinforceConst.STATES.iteritems() ]
   1205                 gm.append(['GM: Set Skyhook State', states])
   1206         gm.append(None)
   1207         try:
   1208             if typeID in (const.typeConstellation, const.typeRegion):
   1209                 from eve.devtools.script.mapEditor.menuOptions import GetMapEditorMenuOptions
   1210                 mapEditorOptions = GetMapEditorMenuOptions(itemID, typeID)
   1211                 if mapEditorOptions:
   1212                     gm.append(MenuEntryData('Map Editor', subMenuData=mapEditorOptions))
   1213                     gm.append(None)
   1214         except Exception:
   1215             self.LogException('Failed to get map editor menu')
   1216 
   1217         d = {'CHARID': charID,
   1218          'ITEMID': itemID,
   1219          'ID': charID or itemID}
   1220         for i in range(20):
   1221             item = prefs.GetValue('gmmenuslash%d' % i, None)
   1222             if item:
   1223                 for k, v in d.iteritems():
   1224                     if ' %s ' % k in item and v:
   1225                         item = item.replace(k, str(v))
   1226                         break
   1227                 else:
   1228                     continue
   1229 
   1230                 gm.append((item, sm.RemoteSvc('slash').SlashCmd, (item,)))
   1231 
   1232         return gm
   1233 
   1234     @staticmethod
   1235     def _FormatAuroraTime(time):
   1236         time = int(time)
   1237         result = ''
   1238         day = 86400
   1239         if time > day:
   1240             result = '%s days ' % (time / day)
   1241             time = time % day
   1242         hour = 3600
   1243         if time > hour:
   1244             result += '%s hours ' % (time / hour)
   1245             time = time % hour
   1246         minute = 60
   1247         if time > minute:
   1248             result += '%s min ' % (time / minute)
   1249             time = time % minute
   1250         result += '%s sec' % time
   1251         return result
   1252 
   1253     @staticmethod
   1254     def SaveRedFile(ball, graphicFile):
   1255         return modelDebugFunctions.SaveRedFile(ball, graphicFile)
   1256 
   1257     @staticmethod
   1258     def RandomizeKillCounter(ball):
   1259         if ball is not None:
   1260             if hasattr(ball, 'model'):
   1261                 if ball.model is not None:
   1262                     if hasattr(ball.model, 'displayKillCounterValue'):
   1263                         ball.model.displayKillCounterValue = random.randint(0, 999)
   1264 
   1265     @staticmethod
   1266     def ToggleDisplay(ball):
   1267         if ball is not None:
   1268             if hasattr(ball, 'model'):
   1269                 if ball.model is not None:
   1270                     if hasattr(ball.model, 'display'):
   1271                         ball.model.display = not ball.model.display
   1272 
   1273     @staticmethod
   1274     def ToggleShaderDebugger(ball, graphicID):
   1275         if ball is not None:
   1276             if hasattr(ball, 'model'):
   1277                 if ball.model is not None:
   1278                     ShaderDebugger(object=ball.model, graphicID=graphicID)
   1279 
   1280     @staticmethod
   1281     def OpenTextureViewer(ball):
   1282         if ball is not None:
   1283             if hasattr(ball, 'model'):
   1284                 if ball.model is not None:
   1285                     TextureWindow(object=ball.model)
   1286 
   1287     @staticmethod
   1288     def GetGMStructureStateMenu(itemID = None, slimItem = None):
   1289         subMenu = MenuList()
   1290         if hasattr(slimItem, 'posState') and slimItem.posState is not None:
   1291             currentState = slimItem.posState
   1292             if currentState not in pos.ONLINE_STABLE_STATES:
   1293                 if currentState == pos.STRUCTURE_ANCHORED:
   1294                     subMenu.append(('Online', sm.RemoteSvc('slash').SlashCmd, ('/pos online ' + str(itemID),)))
   1295                     subMenu.append(('Unanchor', sm.RemoteSvc('slash').SlashCmd, ('/pos unanchor ' + str(itemID),)))
   1296                 elif currentState == pos.STRUCTURE_UNANCHORED:
   1297                     subMenu.append(('Anchor', sm.RemoteSvc('slash').SlashCmd, ('/pos anchor ' + str(itemID),)))
   1298             else:
   1299                 subMenu.append(('Offline', sm.RemoteSvc('slash').SlashCmd, ('/pos offline ' + str(itemID),)))
   1300         return subMenu
   1301 
   1302     @staticmethod
   1303     def GetGMBallsAndBoxesMenu(itemID = None, slimItem = None, charID = None, invItem = None, mapItem = None):
   1304         return modelDebugFunctions.GetGMBallsAndBoxesMenu(itemID, slimItem, charID, invItem, mapItem)
   1305 
   1306     @staticmethod
   1307     def GetOwnerLabel(ownerID):
   1308         return menuFunctions.GetOwnerLabel(ownerID)
   1309 
   1310     @staticmethod
   1311     def ImFleetLeaderOrCommander():
   1312         return sm.GetService('fleet').IsCommanderOrBoss()
   1313 
   1314     @staticmethod
   1315     def CheckImFleetLeader():
   1316         return session.fleetrole == evefleet.fleetRoleLeader
   1317 
   1318     @staticmethod
   1319     def CheckImWingCmdr():
   1320         return session.fleetrole == evefleet.fleetRoleWingCmdr
   1321 
   1322     @staticmethod
   1323     def CheckImSquadCmdr():
   1324         return session.fleetrole == evefleet.fleetRoleSquadCmdr
   1325 
   1326     def GetWarpOptions(self, FleetWarpToMethod, WarpToMethod, itemID):
   1327         if not InShipInSpace():
   1328             return MenuList()
   1329         warptoLabel = movementFunctions.GetDefaultWarpToLabel()
   1330         defaultWarpDist = self.GetDefaultActionDistance('WarpTo')
   1331         return self._GetWarpOptions(FleetWarpToMethod, WarpToMethod, itemID, warptoLabel, defaultWarpDist)
   1332 
   1333     def _GetWarpOptions(self, FleetWarpToMethod, WarpToMethod, itemID, warptoLabel, warpDist):
   1334         ret = MenuList([(warptoLabel, WarpToMethod, (itemID, warpDist)), (MenuLabel('UI/Inflight/Submenus/WarpToWithin', {'distance': 0}), self.WarpToMenu(WarpToMethod, itemID))])
   1335         formationName = {'fleetFormation': GetSelectedFormationName()}
   1336         if self.CheckImFleetLeader():
   1337             ret.extend([(MenuLabel('UI/Fleet/WarpFleet', formationName), FleetWarpToMethod, (itemID, float(warpDist))), (MenuLabel('UI/Fleet/FleetSubmenus/WarpFleetToWithin', formationName), self.WarpToMenu(FleetWarpToMethod, itemID))])
   1338         elif self.CheckImWingCmdr():
   1339             ret.extend([(MenuLabel('UI/Fleet/WarpWing', formationName), FleetWarpToMethod, (itemID, float(warpDist))), (MenuLabel('UI/Fleet/FleetSubmenus/WarpWingToWithin', formationName), self.WarpToMenu(FleetWarpToMethod, itemID))])
   1340         elif self.CheckImSquadCmdr():
   1341             ret.extend([(MenuLabel('UI/Fleet/WarpSquad', formationName), FleetWarpToMethod, (itemID, float(warpDist))), (MenuLabel('UI/Fleet/FleetSubmenus/WarpSquadToWithin', formationName), self.WarpToMenu(FleetWarpToMethod, itemID))])
   1342         return ret
   1343 
   1344     def SolarsystemScanMenu(self, scanResultID):
   1345         WarpToMethod = self.WarpToScanResult
   1346         FleetWarpToMethod = self.WarpFleetToScanResult
   1347         itemID = scanResultID
   1348         return self.GetWarpOptions(FleetWarpToMethod, WarpToMethod, itemID)
   1349 
   1350     def WarpToScanResult(self, scanResultID, minRange = None):
   1351         self._WarpXToScanResult(scanResultID, minRange)
   1352 
   1353     def WarpFleetToScanResult(self, scanResultID, minRange = None):
   1354         self._WarpXToScanResult(scanResultID, minRange, fleet=True)
   1355 
   1356     @staticmethod
   1357     def _WarpXToScanResult(scanResultID, minRange = None, fleet = False):
   1358         michelle = sm.GetService('michelle')
   1359         bp = michelle.GetRemotePark()
   1360         if bp is not None:
   1361             sm.GetService('autoPilot').CancelSystemNavigation()
   1362             itemID, typeID = sm.GetService('sensorSuite').GetPositionalSiteItemIDFromTargetID(scanResultID)
   1363             if itemID is None:
   1364                 subject, subjectID = 'scan', scanResultID
   1365             else:
   1366                 subject, subjectID = 'item', itemID
   1367             michelle.CmdWarpToStuff(subject, subjectID, minRange=minRange, fleet=fleet)
   1368             sm.StartService('space').WarpDestination(celestialID=scanResultID)
   1369 
   1370     @staticmethod
   1371     def IsItemDead(ballPark, itemID):
   1372         ball = ballPark.GetBall(itemID)
   1373         return not ball or ball.isMoribund
   1374 
   1375     def BookmarkMenu(self, bookmark):
   1376         return MergeMenus([self._BookmarkMenu(bookmark)])
   1377 
   1378     @telemetry.ZONE_METHOD
   1379     def _BookmarkMenu(self, bookmark):
   1380         typeID = bookmark.typeID
   1381         itemID = bookmark.itemID or bookmark.locationID
   1382         menuEntries = MenuList()
   1383         slimItem = None
   1384         bp = sm.StartService('michelle').GetBallpark()
   1385         if bp:
   1386             slimItem = bp.GetInvItem(itemID)
   1387         infoArgs = (slimItem.typeID,
   1388          slimItem.itemID,
   1389          0,
   1390          None,
   1391          None) if slimItem else (typeID,
   1392          itemID,
   1393          0,
   1394          None,
   1395          None)
   1396         menuEntries += [[MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo, infoArgs]]
   1397         if not self.sessionChecker:
   1398             self.sessionChecker = SessionChecker(session, sm)
   1399         bm = BookmarkChecker(slimItem or (itemID, typeID), bookmark, cfg, self.sessionChecker)
   1400         mapItemID, mapTypeID = bm.GetMapIDs()
   1401         groupID = bm.item.groupID
   1402         groupName = evetypes.GetGroupNameByGroup(groupID)
   1403         if bm.IsStructure():
   1404             menuEntries.extend(GetStructureMenu(bm))
   1405         if bm.OfferDock():
   1406             menuEntries += [[MenuLabel('UI/Inflight/DockInStation'),
   1407               self.Dock,
   1408               (itemID,),
   1409               None,
   1410               None,
   1411               'DockInStation']]
   1412         if bm.OfferStargateJump():
   1413             jumpInfo = bm.GetJumpInfo()
   1414             cfg.evelocations.Prime([jumpInfo.toCelestialID, jumpInfo.locationID])
   1415             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/Jump'), lambda : self.StargateJump(itemID, typeID, jumpInfo.toCelestialID, jumpInfo.locationID)))
   1416             if not bm.isWaypoint():
   1417                 menuEntries += [[MenuLabel('UI/Inflight/AddFirstWaypoint'), sm.StartService('starmap').SetWaypoint, (jumpInfo.locationID,)]]
   1418         if bm.OfferJumpThroughStargate():
   1419             localStargate = FindLocalStargate(bm.GetWaypointSolarsystemID())
   1420             if localStargate:
   1421                 menuEntries += [[MenuLabel('UI/Inflight/JumpThroughStargate'),
   1422                   self.StargateJump,
   1423                   (localStargate.itemID,
   1424                    localStargate.typeID,
   1425                    localStargate.jumps[0].toCelestialID,
   1426                    localStargate.jumps[0].locationID),
   1427                   eveicon.jump_to]]
   1428         if bm.OfferJumpThroughStructureJumpGate():
   1429             localJumpBridge = FindLocalJumpGateForDestinationPath(bm.GetWaypointSolarsystemID())
   1430             if localJumpBridge:
   1431                 menuEntries += [[MenuLabel('UI/Inflight/JumpThroughJumpgate'),
   1432                   self.JumpThroughStructureJumpBridge,
   1433                   (localJumpBridge.itemID,),
   1434                   eveicon.jump_to]]
   1435         if bm.OfferWarpTo():
   1436             defaultWarpDist = self.GetDefaultActionDistance('WarpTo')
   1437             if not bm.IsDeadspaceBookmark():
   1438                 menuEntries.append(WarpToMenuEntryData(MenuLabel('UI/Inflight/Submenus/WarpToWithin'), func=lambda : movementFunctions.WarpToBookmark(bookmark, float(defaultWarpDist)), subMenuData=self.WarpToMenu(movementFunctions.WarpToBookmark, bookmark)))
   1439             else:
   1440                 menuEntries += [[MenuLabel('UI/Inflight/WarpToBookmark'), movementFunctions.WarpToBookmark, (bookmark, float(defaultWarpDist))]]
   1441             formationName = {'fleetFormation': GetSelectedFormationName()}
   1442             if bm.session.IsPilotFleetLeader():
   1443                 label = MenuLabel('UI/Fleet/WarpFleetToLocation', formationName) if bm.IsDeadspaceBookmark() else MenuLabel('UI/Fleet/WarpFleetToLocationWithinDistance', {'warpToDistance': fmtutil.FmtDist(float(defaultWarpDist)),
   1444                  'fleetFormation': GetSelectedFormationName()})
   1445                 menuEntries += [[label, movementFunctions.WarpToBookmark, (bookmark, float(defaultWarpDist), True)]]
   1446                 menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/WarpFleetToWithin', formationName), self.WarpToMenu(movementFunctions.WarpFleetToBookmark, bookmark)]]
   1447             if bm.session.IsPilotWingCommander():
   1448                 label = MenuLabel('UI/Fleet/WarpWingToLocation', formationName) if bm.IsDeadspaceBookmark() else MenuLabel('UI/Fleet/WarpWingToLocationWithinDistance', {'warpToDistance': fmtutil.FmtDist(float(defaultWarpDist)),
   1449                  'fleetFormation': GetSelectedFormationName()})
   1450                 menuEntries += [[label, movementFunctions.WarpToBookmark, (bookmark, float(defaultWarpDist), True)]]
   1451                 menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/WarpWingToWithin', formationName), self.WarpToMenu(movementFunctions.WarpFleetToBookmark, bookmark)]]
   1452             if bm.session.IsPilotSquadCommander():
   1453                 label = MenuLabel('UI/Fleet/WarpSquadToLocation', formationName) if bm.IsDeadspaceBookmark() else MenuLabel('UI/Fleet/WarpSquadToLocationWithinDistance', {'warpToDistance': fmtutil.FmtDist(float(defaultWarpDist)),
   1454                  'fleetFormation': GetSelectedFormationName()})
   1455                 menuEntries += [[label, movementFunctions.WarpToBookmark, (bookmark, float(defaultWarpDist), True)]]
   1456                 menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/WarpSquadToWithin', formationName), self.WarpToMenu(movementFunctions.WarpFleetToBookmark, bookmark)]]
   1457         if bm.OfferApproachLocation():
   1458             menuEntries += [[MenuLabel('UI/Inflight/ApproachLocationActionGroup'), movementFunctions.ApproachLocation, (bookmark,)]]
   1459         if bm.OfferAlignTo():
   1460             menuEntries += [[MenuLabel('UI/Inflight/AlignTo'), self.AlignToBookmark, (getattr(bookmark, 'bookmarkID', None),)]]
   1461         if bm.OfferSetDestination():
   1462             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/SetDestination'), lambda : sm.StartService('starmap').SetWaypoint(mapItemID, True)))
   1463         if bm.OfferAddWaypoint():
   1464             menuEntries += [[MenuLabel('UI/Inflight/AddWaypoint'), sm.StartService('starmap').SetWaypoint, (mapItemID,)]]
   1465         elif bm.isWaypoint():
   1466             menuEntries += [[MenuLabel('UI/Inflight/RemoveWaypoint'), sm.StartService('starmap').ClearWaypoints, (mapItemID,)]]
   1467         if bm.OfferBroadcastTravelTo():
   1468             menuEntries += [None]
   1469             menuEntries += [MenuEntryData(MenuLabel('UI/Fleet/FleetBroadcast/Commands/BroadcastTravelTo'), lambda : sm.GetService('fleet').SendBroadcast_TravelTo(mapItemID), texturePath=iconsByBroadcastType[BROADCAST_TRAVEL_TO])]
   1470         if bm.OfferLookAtObject():
   1471             menuEntries += [[MenuLabel('UI/Inflight/LookAtObject'), self.TryLookAt, (itemID,)]]
   1472             if bool(gfxsettings.Get(gfxsettings.UI_ADVANCED_CAMERA)):
   1473                 menuEntries += [[MenuLabel('UI/Inflight/SetAsCameraParent'), self.SetParent, (itemID,)]]
   1474         if bm.OfferResetCamera():
   1475             menuEntries += [[MenuLabel('UI/Inflight/ResetCamera'), sm.GetService('sceneManager').GetActiveSpaceCamera().ResetCamera]]
   1476         if bm.OfferShowLocationOnMap():
   1477             menuEntries += [None]
   1478             menuEntries += [[MenuLabel('UI/Commands/ShowLocationOnMap'), self.ShowInMap, (mapItemID,)]]
   1479             menuEntries += [[MenuLabel('UI/Inflight/ShowInMapBrowser', {'locationType': groupName}), self.ShowInMapBrowser, (mapItemID,)]]
   1480         if bm.OfferAvoidLocation():
   1481             menuEntries += [[MenuLabel('UI/Inflight/AvoidLocation', {'theLocation': mapItemID,
   1482                'locationType': groupName}), self.clientPathfinderService.AddAvoidanceItem, (mapItemID,)]]
   1483         elif bm.OfferStopAvoidingLocation():
   1484             menuEntries += [[MenuLabel('UI/Inflight/StopAvoidingLocation', {'theLocation': mapItemID,
   1485                'locationType': groupName}), self.clientPathfinderService.RemoveAvoidanceItem, (mapItemID,)]]
   1486         if bm.OfferViewPlanetaryProduction():
   1487             menuEntries += [[MenuLabel('UI/PI/Common/ViewInPlanetMode'), self.ViewPlanetaryProduction, (itemID,)]]
   1488         elif bm.OfferExitPlanetaryProduction():
   1489             menuEntries += [[MenuLabel('UI/PI/Common/ExitPlanetMode'), sm.GetService('viewState').CloseSecondaryView, ()]]
   1490         if bm.OfferEditBookmark():
   1491             menuEntries += [[MenuLabel('UI/Inflight/EditBookmark'), sm.GetService('addressbook').EditBookmark, (bookmark,)]]
   1492             menuEntries += [[MenuLabel('UI/Inflight/RemoveBookmark'), sm.GetService('addressbook').DeleteBookmarks, ([getattr(bookmark, 'bookmarkID', None)],)]]
   1493         if bm.OfferSetName():
   1494             menuEntries += [[MenuLabel('UI/Commands/SetName'), self.SetName, (bm.item,)]]
   1495         if bm.OfferScoopToCargoHold():
   1496             menuEntries += [[MenuLabel('UI/Inflight/ScoopToCargoHold'), self.Scoop, (itemID, typeID)]]
   1497         if bm.OfferEditProfileForStructure():
   1498             menuEntries += [[MenuLabel('UI/Commands/EditProfileForStructure'), openFunctions.OpenProfileSettingsForStructure, (itemID,)]]
   1499         if bm.OfferToggleOverviewVisibility():
   1500             menuEntries.append(overviewMenuUtil.GetToggleEntry(groupID))
   1501         if session.role & (ROLE_GML | ROLE_WORLDMOD):
   1502             menuEntries.insert(0, ('GM / WM Extras', ('isDynamic', self.GetGMMenu, (itemID,
   1503                slimItem,
   1504                None,
   1505                None,
   1506                None,
   1507                typeID))))
   1508         del bm
   1509         return menuEntries
   1510 
   1511     @telemetry.ZONE_METHOD
   1512     def CelestialMenu(self, itemID, mapItem = None, slimItem = None, typeID = None, parentID = None, hint = None):
   1513         if type(itemID) == list:
   1514             menus = []
   1515             for data in itemID:
   1516                 m = self._CelestialMenu(data, hint, len(itemID) > 1)
   1517                 menus.append(m)
   1518 
   1519             return MergeMenus(menus)
   1520         else:
   1521             ret = self._CelestialMenu((itemID,
   1522              mapItem,
   1523              slimItem,
   1524              typeID,
   1525              parentID), hint)
   1526             return MergeMenus([ret])
   1527 
   1528     def UnmergedCelestialMenu(self, slimItem):
   1529         return self._CelestialMenu((slimItem.itemID,
   1530          None,
   1531          slimItem,
   1532          None,
   1533          None))
   1534 
   1535     @telemetry.ZONE_METHOD
   1536     def _CelestialMenu(self, data, hint = None, multi = 0):
   1537         itemID, mapItem, slimItem, typeID, parentID = data
   1538         categoryID = None
   1539         dist = False
   1540         bp = sm.StartService('michelle').GetBallpark()
   1541         if bp:
   1542             slimItem = slimItem or bp.GetInvItem(itemID)
   1543             otherBall = bp.GetBall(itemID)
   1544             ownBall = bp.GetBall(session.shipid)
   1545             dist = otherBall and ownBall and max(0, otherBall.surfaceDist)
   1546         if slimItem:
   1547             typeID = slimItem.typeID
   1548             parentID = sm.StartService('map').GetParent(itemID) or session.solarsystemid
   1549             categoryID = slimItem.categoryID
   1550         mapItemID = None
   1551         mapFunctionID = itemID
   1552         mapItem = mapItem or sm.StartService('map').GetItem(itemID, categoryID=categoryID)
   1553         if mapItem:
   1554             typeID = mapItem.typeID
   1555             parentID = getattr(mapItem, 'locationID', None) or const.locationUniverse
   1556             if typeID == const.groupSolarSystem:
   1557                 mapItemID = mapItem.itemID
   1558         if typeID is None:
   1559             return []
   1560         groupID = evetypes.GetGroupID(typeID)
   1561         if categoryID == const.categoryCharge and groupID != const.groupScannerProbe:
   1562             return []
   1563         if groupID in [const.groupSolarSystem, const.groupConstellation, const.groupRegion] and parentID != session.solarsystemid:
   1564             mapFunctionID = mapItemID or itemID
   1565         if parentID is None and groupID == const.groupStation and itemID:
   1566             tmp = sm.StartService('ui').GetStationStaticInfo(itemID)
   1567             if tmp is not None:
   1568                 parentID = tmp.solarSystemID
   1569         niceRange = dist is not False and fmtutil.FmtDist(dist) or localization.GetByLabel('UI/Inflight/NoDistanceAvailable')
   1570         defaultWarpDist = self.GetDefaultActionDistance('WarpTo')
   1571         groupName = evetypes.GetGroupNameByGroup(groupID)
   1572         menuEntries = MenuList()
   1573         if not self.sessionChecker:
   1574             self.sessionChecker = SessionChecker(session, sm)
   1575         celestial = CelestialChecker(slimItem or (itemID, typeID), cfg, self.sessionChecker)
   1576         celestial.isMultiSelection = bool(multi)
   1577         if celestial.OfferDroneMenu():
   1578             for droneEntry in self.DroneMenu([[itemID,
   1579               typeID,
   1580               slimItem.ownerID,
   1581               slimItem.locationID]], 1):
   1582                 menuEntries += droneEntry
   1583 
   1584         if celestial.OfferUseFittingService():
   1585             menuEntries += [[MenuLabel('UI/Fitting/UseFittingService'), uicore.cmd.GetCommandToExecute('OpenFitting'), ()]]
   1586         if celestial.OfferBoardShip():
   1587             boardCmd = self.Board if self.sessionChecker.IsPilotInShipInSpace() else sm.GetService('structureControl').EjectFromStructure
   1588             if self.sessionChecker.IsPilotControllingStructure():
   1589                 structureTypeID = sm.GetService('structureDirectory').GetStructureInfo(session.structureid).typeID
   1590                 if idCheckers.IsDockableStructure(structureTypeID):
   1591                     boardCmd = None
   1592             if boardCmd:
   1593                 menuEntries += [[MenuLabel('UI/Inflight/BoardShip'), boardCmd, (itemID,)]]
   1594         elif celestial.failure_label:
   1595             menuEntries.reasonsWhyNotAvailable['UI/Inflight/BoardShip'] = self.GetUnavailableText(celestial)
   1596         if celestial.OfferOpenCargo():
   1597             menuEntries += [[MenuLabel('UI/Commands/OpenCargo'),
   1598               self.OpenCargo,
   1599               [itemID],
   1600               None,
   1601               None,
   1602               'OpenCargo']]
   1603         elif celestial.failure_label:
   1604             menuEntries.reasonsWhyNotAvailable['UI/Commands/OpenCargo'] = self.GetUnavailableText(celestial)
   1605         if celestial.OfferEjectFromShip():
   1606             menuEntries += [[MenuLabel('UI/Inflight/EjectFromShip'), self.Eject]]
   1607         elif celestial.failure_label:
   1608             menuEntries.reasonsWhyNotAvailable['UI/Inflight/EjectFromShip'] = self.GetUnavailableText(celestial)
   1609         if celestial.OfferSetName():
   1610             menuEntries += [[MenuLabel('UI/Commands/SetName'), self.SetName, (celestial.item,)]]
   1611         if celestial.OfferBroadcastEnemySpotted():
   1612             senderID, = sm.GetService('fleet').CurrentFleetBroadcastOnItem(itemID, state.gbEnemySpotted)
   1613             menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/BroadCastEnemySpotted', {'character': senderID}), ('isDynamic', self.CharacterMenu, (senderID,))]]
   1614         if celestial.OfferStopMyShip():
   1615             label = 'UI/Inflight/StopMyCapsule' if groupID == const.groupCapsule else 'UI/Inflight/StopMyShip'
   1616             menuEntries += [[MenuLabel(label), movementFunctions.StopMyShip]]
   1617         elif celestial.failure_label:
   1618             label = 'UI/Inflight/StopMyCapsule' if groupID == const.groupCapsule else 'UI/Inflight/StopMyShip'
   1619             fail_text = self.GetUnavailableText(celestial)
   1620             menuEntries.reasonsWhyNotAvailable[label] = fail_text
   1621             menuEntries.reasonsWhyNotAvailable['UI/Commands/OpenMyCargo'] = fail_text
   1622         if celestial.OfferStoreVessel():
   1623             menuEntries += [[MenuLabel('UI/Inflight/POS/StoreVesselInSMA'), self.StoreVessel, (itemID, session.shipid)]]
   1624         menuEntries.extend(openFunctions.GetOpenShipHoldMenus(celestial))
   1625         if celestial.OfferConfigureShipCloneFacility():
   1626             menuEntries += [[MenuLabel('UI/Commands/ConfigureShipCloneFacility'), self.ShipCloneConfig, (itemID,)]]
   1627         if celestial.OfferReconnectToLostDrones():
   1628             menuEntries += [[MenuLabel('UI/Commands/ReconnectToLostDrones'), self.ReconnectToDrones]]
   1629         if celestial.OfferSafeLogoff():
   1630             if AllowCharacterLogoff(sm.GetService('machoNet')):
   1631                 menuEntries += [[MenuLabel('UI/Inflight/SafeLogoff'), uicore.cmd.CmdLogOff]]
   1632             else:
   1633                 menuEntries += [[MenuLabel('UI/Inflight/SafeLogoff/SafeLogoffQuitGame'), self.SafeLogoff]]
   1634         if celestial.OfferSelfDestructShip():
   1635             menuEntries += [[MenuLabel('UI/Inflight/SelfDestructShipOrPod'), self.SelfDestructShip, (itemID,)]]
   1636         elif celestial.OfferAbortSelfDestructShip():
   1637             menuEntries += [[MenuLabel('UI/Inflight/AbortSelfDestruct'), self.AbortSelfDestructShip, (itemID,)]]
   1638         elif celestial.failure_label:
   1639             menuEntries.reasonsWhyNotAvailable['UI/Inflight/SelfDestructShipOrPod'] = self.GetUnavailableText(celestial)
   1640         if celestial.OfferEnterStarbasePassword():
   1641             menuEntries += [[MenuLabel('UI/Inflight/POS/EnterStarbasePassword'), self.EnterPOSPassword]]
   1642         if celestial.OfferActivateAutopilot():
   1643             menuEntries += [[MenuLabel('UI/Inflight/ActivateAutopilot'), self.ToggleAutopilot, (1,)]]
   1644         elif celestial.failure_label:
   1645             menuEntries.reasonsWhyNotAvailable['UI/Inflight/ActivateAutopilot'] = self.GetUnavailableText(celestial)
   1646         if celestial.OfferDeactivateAutopilot():
   1647             menuEntries += [[MenuLabel('UI/Inflight/DeactivateAutopilot'), self.ToggleAutopilot, (0,)]]
   1648         elif celestial.failure_label:
   1649             menuEntries.reasonsWhyNotAvailable['UI/Inflight/DeactivateAutopilot'] = self.GetUnavailableText(celestial)
   1650         if celestial.IsMyActiveShip():
   1651             if self.sessionChecker.isShipJumpCapable():
   1652                 menuEntries += [[MenuLabel('UI/CapitalNavigation/CapitalNavigationWindow/OpenJumpNavigation'), uicore.cmd.GetCommandToExecute('OpenCapitalNavigation'), ()]]
   1653                 menuEntries += [[MenuLabel('UI/Inflight/Submenus/JumpTo'), ('isDynamic', self.GetHybridBeaconJumpMenu, [])]]
   1654                 if self.sessionChecker.canOpenJumpPortal():
   1655                     menuEntries += [[MenuLabel('UI/Inflight/Submenus/BridgeTo'), ('isDynamic', self.GetHybridBridgeMenu, [])]]
   1656                 if self.sessionChecker.canPerformGroupJump():
   1657                     menuEntries += [[MenuLabel('UI/Inflight/Submenus/ConduitJumpTo'), ('isDynamic', self.GetHybridBeaconGroupJumpMenu, [])]]
   1658         if celestial.OfferMoonMiningPointMenu():
   1659             menuEntries.extend(self.GetMoonMiningPointMenu(celestial, slimItem))
   1660         if celestial.OfferWarpTo():
   1661             if celestial.IsShip() and self.sessionChecker.isPilotInSameFleetAs(slimItem.charID):
   1662                 warpFn = self.WarpToMember
   1663                 warpID = slimItem.charID
   1664             else:
   1665                 warpFn = movementFunctions.WarpToItem
   1666                 warpID = itemID
   1667             menuEntries.append(WarpToMenuEntryData(MenuLabel('UI/Inflight/Submenus/WarpToWithin'), func=lambda : warpFn(warpID, float(defaultWarpDist)), subMenuData=self.WarpToMenu(warpFn, warpID)))
   1668             if self.sessionChecker.IsPilotFleetMember():
   1669                 warpFleetFn = self.WarpFleetToMember if warpFn is self.WarpToMember else self.WarpFleet
   1670                 formationName = {'fleetFormation': GetSelectedFormationName()}
   1671                 if self.sessionChecker.IsPilotFleetLeader():
   1672                     menuEntries += [[MenuLabel('UI/Fleet/WarpFleet', formationName), warpFleetFn, (warpID, float(defaultWarpDist))]]
   1673                     menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/WarpFleetToWithin', formationName), self.WarpToMenu(warpFleetFn, warpID)]]
   1674                 if self.sessionChecker.IsPilotWingCommander():
   1675                     menuEntries += [[MenuLabel('UI/Fleet/WarpWing', formationName), warpFleetFn, (warpID, float(defaultWarpDist))]]
   1676                     menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/WarpWingToWithin', formationName), self.WarpToMenu(warpFleetFn, warpID)]]
   1677                 if self.sessionChecker.IsPilotSquadCommander():
   1678                     menuEntries += [[MenuLabel('UI/Fleet/WarpSquad', formationName), warpFleetFn, (warpID, float(defaultWarpDist))]]
   1679                     menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/WarpSquadToWithin', formationName), self.WarpToMenu(warpFleetFn, warpID)]]
   1680         elif celestial.failure_label:
   1681             fail_text = self.GetUnavailableText(celestial)
   1682             menuEntries.reasonsWhyNotAvailable[movementFunctions.GetDefaultWarpToLabel().labelPath] = fail_text
   1683             if 'UI/Inflight/WarpToMoonMiningPoint' not in menuEntries.reasonsWhyNotAvailable:
   1684                 menuEntries.reasonsWhyNotAvailable['UI/Inflight/WarpToMoonMiningPoint'] = fail_text
   1685         menuEntries += [None]
   1686         if celestial.OfferApproachObject():
   1687             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/ApproachObject'), lambda : movementFunctions.Approach(itemID), internalName='Approach', typeID=typeID))
   1688         elif celestial.failure_label:
   1689             menuEntries.reasonsWhyNotAvailable['UI/Inflight/ApproachObject'] = self.GetUnavailableText(celestial)
   1690         if celestial.OfferOrbitObject():
   1691             menuEntries.append(OrbitMenuEntryData(MenuLabel('UI/Inflight/OrbitObject'), func=lambda : movementFunctions.Orbit(itemID), subMenuData=movementFunctions.GetOrbitMenu(itemID, typeID, dist, niceRange), internalName='Orbit', typeID=typeID))
   1692         elif celestial.failure_label:
   1693             menuEntries.reasonsWhyNotAvailable['UI/Inflight/OrbitObject'] = self.GetUnavailableText(celestial)
   1694         if celestial.OfferKeepAtRange():
   1695             menuEntries.append(KeepAtRangeMenuEntryData(MenuLabel('UI/Inflight/Submenus/KeepAtRange'), func=lambda : movementFunctions.KeepAtRange(itemID), subMenuData=movementFunctions.GetKeepAtRangeMenu(itemID, typeID, dist, niceRange)))
   1696         elif celestial.failure_label:
   1697             menuEntries.reasonsWhyNotAvailable['UI/Inflight/Submenus/KeepAtRange'] = self.GetUnavailableText(celestial)
   1698         if celestial.OfferAlignTo():
   1699             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/AlignTo'), lambda : self.AlignTo(itemID)))
   1700         if celestial.OfferStructureMenu():
   1701             menuEntries.extend(GetStructureMenu(celestial))
   1702         if celestial.OfferBroadcastTarget():
   1703             menuEntries += [MenuEntryData(MenuLabel('UI/Fleet/FleetBroadcast/Commands/BroadcastTarget'), lambda : sm.GetService('fleet').SendBroadcast_Target(itemID), texturePath=iconsByBroadcastType[BROADCAST_TARGET])]
   1704         if celestial.OfferBroadcastWarpTo():
   1705             menuEntries += [MenuEntryData(MenuLabel('UI/Fleet/FleetBroadcast/Commands/BroadcastWarpTo'), lambda : sm.GetService('fleet').SendBroadcast_WarpTo(itemID, typeID), texturePath=iconsByBroadcastType[BROADCAST_WARP_TO])]
   1706         if celestial.OfferBroadcastAlignTo():
   1707             menuEntries += [MenuEntryData(MenuLabel('UI/Fleet/FleetBroadcast/Commands/BroadcastAlignTo'), lambda : sm.GetService('fleet').SendBroadcast_AlignTo(itemID, typeID), texturePath=iconsByBroadcastType[BROADCAST_ALIGN_TO])]
   1708         if celestial.OfferBroadcastJumpTo():
   1709             menuEntries += [MenuEntryData(MenuLabel('UI/Fleet/FleetBroadcast/Commands/BroadcastJumpTo'), lambda : sm.GetService('fleet').SendBroadcast_JumpTo(itemID, typeID), texturePath=iconsByBroadcastType[BROADCAST_JUMP_TO])]
   1710         if celestial.OfferJumpFleetThroughToSystem():
   1711             menuEntries += [None]
   1712             menuEntries += [[MenuLabel('UI/Fleet/JumpThroughToSystem', {'solarsystem': celestial.GetActiveFleetBridge()[0]}), self.JumpThroughFleet, (slimItem.charID or slimItem.ownerID, itemID)]]
   1713         if celestial.OfferBroadcastHealTarget():
   1714             menuEntries += [MenuEntryData(MenuLabel('UI/Fleet/FleetBroadcast/Commands/BroadcastHealTarget'), lambda : sm.GetService('fleet').SendBroadcast_Heal_Target(itemID), texturePath=eveicon.heal_first_aid)]
   1715         if celestial.OfferDock():
   1716             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/DockInStation'), lambda : self.Dock(itemID), internalName='DockInStation'))
   1717         elif celestial.failure_label:
   1718             menuEntries.reasonsWhyNotAvailable['UI/Inflight/DockInStation'] = self.GetUnavailableText(celestial)
   1719         if celestial.IsDockable() and celestial.session.isPilotWarping() and not celestial.OfferDock():
   1720             self.AddDisabledEntryForWarp(menuEntries, 'UI/Inflight/DockInStation')
   1721         if celestial.OfferStargateJump():
   1722             jumpInfo = celestial.GetJumpInfo()
   1723             cfg.evelocations.Prime([jumpInfo.toCelestialID, jumpInfo.locationID])
   1724             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/Jump'), lambda : self.StargateJump(celestial.item.itemID, celestial.item.typeID, jumpInfo.toCelestialID, jumpInfo.locationID), internalName='Jump'))
   1725         elif celestial.failure_label:
   1726             menuEntries.reasonsWhyNotAvailable['UI/Inflight/Jump'] = self.GetUnavailableText(celestial)
   1727         if celestial.IsStargate() and celestial.session.isPilotWarping() and not celestial.OfferStargateJump():
   1728             self.AddDisabledEntryForWarp(menuEntries, 'UI/Inflight/Jump')
   1729         if celestial.OfferShipcasterJump():
   1730             if celestial.IsShipcasterStarterLauncher():
   1731                 targetSolarsystemID, _ = GetTargetForStarterShipcaster(itemID)
   1732                 text = localization.GetByLabel('UI/Inflight/JumpByShipcasterToSystem', solarsystem=targetSolarsystemID)
   1733                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/JumpByShipcaster', {'text': text}), lambda : self.JumpThroughStarterShipcaster(celestial.item.itemID), internalName='JumpThroughStarterShipcaster'))
   1734             else:
   1735                 targetSolarsystemID, _ = GetTargetForShipcaster(itemID)
   1736                 text = localization.GetByLabel('UI/Inflight/JumpByShipcasterToSystem', solarsystem=targetSolarsystemID)
   1737                 menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/JumpByShipcaster', {'text': text}), lambda : self.JumpThroughShipcaster(celestial.item.itemID), internalName='JumpThroughShipcaster'))
   1738         elif celestial.failure_label:
   1739             failureText, disabledOption = GetFailureTextAndDisabledOption(itemID, celestial)
   1740             if disabledOption:
   1741                 menuEntries.append(disabledOption)
   1742             menuEntries.reasonsWhyNotAvailable['UI/Inflight/JumpByShipcaster'] = failureText
   1743         if celestial.OfferAddFirstWaypoint():
   1744             jumpInfo = celestial.GetJumpInfo()
   1745             cfg.evelocations.Prime([jumpInfo.toCelestialID, jumpInfo.locationID])
   1746             menuEntries += [[MenuLabel('UI/Inflight/AddFirstWaypoint'), sm.StartService('starmap').SetWaypoint, (jumpInfo.locationID, False, True)]]
   1747         if celestial.OfferActivateGate():
   1748             crimewatchSvc = sm.GetService('crimewatchSvc')
   1749             requiredSafetyLevel, _, _ = crimewatchSvc.GetRequiredSafetyLevelForActivatingAccelerationGate(itemID)
   1750             if requiredSafetyLevel == const.shipSafetyLevelNone:
   1751                 menuClass = eveMenu.CriminalMenuEntryView
   1752             elif requiredSafetyLevel == const.shipSafetyLevelPartial:
   1753                 menuClass = eveMenu.SuspectMenuEntryView
   1754             else:
   1755                 menuClass = None
   1756             menuEntries += [[MenuLabel('UI/Inflight/ActivateGate'),
   1757               self.GetAbyssalGateFunction(typeID) or self.ActivateAccelerationGate,
   1758               (itemID,),
   1759               None,
   1760               menuClass]]
   1761         elif celestial.failure_label:
   1762             menuEntries.reasonsWhyNotAvailable['UI/Inflight/ActivateGate'] = self.GetUnavailableText(celestial)
   1763             if celestial.IsWarpGate() and self.sessionChecker.isPilotWarping():
   1764                 self.AddDisabledEntryForWarp(menuEntries, 'UI/Inflight/ActivateGate')
   1765         if celestial.OfferActivatRandomTraceGate():
   1766             menuEntries += [[MenuLabel('UI/Inflight/ActivateTraceGate'), self.ActivateRandomJumpTraceGate, (itemID,)]]
   1767         elif celestial.failure_label:
   1768             menuEntries.reasonsWhyNotAvailable['UI/Inflight/ActivateTraceGate'] = self.GetUnavailableText(celestial)
   1769         if celestial.OfferEnterWormhole():
   1770             menuEntries += [[MenuLabel('UI/Inflight/EnterWormhole'), self.EnterWormhole, (itemID,)]]
   1771         elif celestial.failure_label:
   1772             menuEntries.reasonsWhyNotAvailable['UI/Inflight/EnterWormhole'] = self.GetUnavailableText(celestial)
   1773             if celestial.IsWormhole() and self.sessionChecker.isPilotWarping():
   1774                 self.AddDisabledEntryForWarp(menuEntries, 'UI/Inflight/EnterWormhole')
   1775         menuEntries += [None]
   1776         if celestial.OfferLookAtObject():
   1777             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/LookAtObject'), lambda : self.TryLookAt(itemID)))
   1778             if bool(gfxsettings.Get(gfxsettings.UI_ADVANCED_CAMERA)):
   1779                 menuEntries += [[MenuLabel('UI/Inflight/SetAsCameraParent'), self.SetParent, (itemID,)]]
   1780         elif celestial.failure_label:
   1781             menuEntries.reasonsWhyNotAvailable['UI/Inflight/LookAtObject'] = self.GetUnavailableText(celestial)
   1782         if celestial.OfferSetAsCameraInterest():
   1783             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/SetAsCameraInterest'), lambda : self.SetInterest(itemID)))
   1784         if celestial.OfferResetCamera():
   1785             menuEntries += [[MenuLabel('UI/Inflight/ResetCamera'), sm.GetService('sceneManager').GetActiveSpaceCamera().ResetCamera]]
   1786         elif celestial.failure_label:
   1787             menuEntries.reasonsWhyNotAvailable['UI/Inflight/ResetCamera'] = self.GetUnavailableText(celestial)
   1788         if celestial.OfferAccessCustomOfficePoco() or celestial.OfferAccessCustomOfficeSkyhook():
   1789             menuEntries += [None]
   1790             menuEntries += [[MenuLabel('UI/PI/Common/AccessCustomOffice'), self.OpenPlanetCustomsOfficeImportWindow, [itemID]]]
   1791         if celestial.OfferAccessOrbitalSkyhookOffice():
   1792             menuEntries += [[MenuLabel('UI/OrbitalSkyhook/SkyhookWnd/AccessOrbitalSkyhookOffice'), self.OpenOrbitalSkyhookWindow, [itemID]]]
   1793         elif celestial.failure_label:
   1794             menuEntries.reasonsWhyNotAvailable['UI/OrbitalSkyhook/SkyhookWnd/AccessOrbitalSkyhookOffice'] = self.GetUnavailableText(celestial)
   1795         if celestial.OfferAccessMercenaryDen():
   1796             menuEntries.append(MenuEntryData(text=MenuLabel('UI/Sovereignty/MercenaryDen/ConfigurationWindow/ConfigureMercenaryDen'), func=lambda : self.OpenMercenaryDen(itemID)))
   1797         elif celestial.failure_label:
   1798             menuEntries.reasonsWhyNotAvailable['UI/Sovereignty/MercenaryDen/ConfigurationWindow/ConfigureMercenaryDen'] = self.GetUnavailableText(celestial)
   1799         menuEntries += [None]
   1800         if celestial.OfferAccessMoonMaterialBay():
   1801             menuEntries += [[MenuLabel('UI/Inflight/OpenMoonMaterialBay'), self.OpenMoonMaterialBay, [itemID]]]
   1802         if celestial.OfferOpenUpgradeHold():
   1803             menuEntries += [[MenuLabel('UI/DustLink/OpenUpgradeHold'), self.OpenUpgradeWindow, [itemID]]]
   1804         if celestial.OfferAbandonWreck():
   1805             menuEntries += [[MenuLabel('UI/Inflight/AbandonWreack'), self.AbandonLoot, [itemID]]]
   1806             menuEntries += [[MenuLabel('UI/Inflight/AbandonAllWrecks'), self.AbandonAllLoot, [itemID]]]
   1807         if celestial.OfferAbandonCargo():
   1808             menuEntries += [[MenuLabel('UI/Inflight/AbandonCargo'), self.AbandonLoot, [itemID]]]
   1809             menuEntries += [[MenuLabel('UI/Inflight/AbandonAllCargo'), self.AbandonAllLoot, [itemID]]]
   1810         if celestial.OfferScoopToCargoHold():
   1811             menuEntries += [[MenuLabel('UI/Inflight/ScoopToCargoHold'), self.Scoop, (itemID, typeID)]]
   1812         if celestial.OfferScoopToFleetHangar():
   1813             menuEntries += [[MenuLabel('UI/Inflight/ScoopToFleetHangar'), self.ScoopToFleetHangar, (itemID, typeID)]]
   1814         if celestial.OfferScoopToFighterBay():
   1815             menuEntries += [[MenuLabel('UI/Inflight/ScoopToFighterBay'), self.ScoopToFighterBay, (itemID, typeID)]]
   1816         if celestial.OfferScoopToShipMaintenanceBay():
   1817             menuEntries += [[MenuLabel('UI/Inflight/POS/ScoopToShipMaintenanceBay'), self.ScoopSMA, (itemID,)]]
   1818         if celestial.OfferScoopToInfrastructureHold():
   1819             menuEntries += [[MenuLabel('UI/Inflight/ScoopToInfrastructureHold'), self.ScoopToInfrastructureHold, (itemID, typeID)]]
   1820         if celestial.OfferScoopToMobileDepot():
   1821             menuEntries += [[MenuLabel('UI/Inflight/ScoopToMobileDepotHold'), self.ScoopToMobileDepotHold, (itemID,)]]
   1822         if celestial.OfferAnchorPOSObject():
   1823             menuEntries += [[MenuLabel('UI/Inflight/POS/AnchorObject'), self.AnchorObject, (itemID, 1)]]
   1824         if celestial.OfferUnanchorPOSObject():
   1825             menuEntries += [[MenuLabel('UI/Inflight/UnanchorObject'), self.AnchorObject, (itemID, 0)]]
   1826         elif celestial.failure_label:
   1827             menuEntries.reasonsWhyNotAvailable['UI/Inflight/UnanchorObject'] = self.GetUnavailableText(celestial)
   1828         if celestial.IsPOSStructure():
   1829             menuEntries.append(None)
   1830         if celestial.OfferAccessPOSFuelBay():
   1831             menuEntries += [[MenuLabel('UI/Inflight/POS/AccessPOSFuelBay'), self.OpenPOSFuelBay, (itemID,)]]
   1832         if celestial.OfferAccessPOSStrontiumBay():
   1833             menuEntries += [[MenuLabel('UI/Inflight/POS/AccessPOSStrontiumBay'), self.OpenStrontiumBay, (itemID,)]]
   1834         if celestial.OfferAccessPOSAmmo():
   1835             menuEntries += [[MenuLabel('UI/Inflight/POS/AccessPOSAmmo'), self.OpenPOSStructureCharges, (itemID, True)]]
   1836         if celestial.OfferAccessPOSActiveCrystal():
   1837             menuEntries += [[MenuLabel('UI/Inflight/POS/AccessPOSActiveCrystal'), self.OpenPOSStructureChargeCrystal, (itemID,)]]
   1838         if celestial.OfferAccessPOSCrystalStorage():
   1839             menuEntries += [[MenuLabel('UI/Inflight/POS/AccessPOSCrystalStorage'), self.OpenPOSStructureChargesStorage, (itemID,)]]
   1840         if celestial.OfferStoreVesselInSMA():
   1841             menuEntries += [[MenuLabel('UI/Inflight/POS/StoreVesselInSMA'), self.StoreVessel, (itemID, session.shipid)]]
   1842         if celestial.OfferAccessPOSStorage():
   1843             openFunc = self.OpenCorpHangarArray
   1844             if celestial.IsPersonalHangarArray():
   1845                 openFunc = self.OpenPersonalHangar
   1846             elif celestial.IsSilo():
   1847                 openFunc = self.OpenPOSSilo
   1848             elif celestial.IsReactor():
   1849                 openFunc = self.OpenPOSMobileReactor
   1850             menuEntries += [[MenuLabel('UI/Inflight/POS/AccessPOSStorage'), openFunc, (itemID,)]]
   1851         elif celestial.failure_label:
   1852             menuEntries.reasonsWhyNotAvailable['UI/Inflight/POS/AccessPOSStorage'] = self.GetUnavailableText(celestial)
   1853         if celestial.OfferManageControlTower():
   1854             menuEntries += [[MenuLabel('UI/Inflight/POS/ManageControlTower'), self.ManageControlTower, (slimItem,)]]
   1855         if celestial.OfferSetNewPasswordForForceField():
   1856             menuEntries += [[MenuLabel('UI/Inflight/POS/SetNewPasswordForForceField'), self.EnterForceFieldPassword, (itemID,)]]
   1857         if celestial.OfferAccessPOSVessels():
   1858             menuEntries += [[MenuLabel('UI/Inflight/POS/AccessPOSVessels'), self.OpenPOSShipMaintenanceArray, (itemID,)]]
   1859             menuEntries += [None]
   1860         elif celestial.failure_label:
   1861             menuEntries.reasonsWhyNotAvailable['UI/Inflight/AccessPOSVessels'] = self.GetUnavailableText(celestial)
   1862         if celestial.OfferSetName():
   1863             menuEntries += [[MenuLabel('UI/Commands/SetName'), self.SetName, (slimItem,)]]
   1864         if celestial.OfferAccessPOSRefinery():
   1865             menuEntries += [[MenuLabel('UI/Inflight/POS/AccessPOSRefinery'), self.OpenPOSRefinery, (itemID,)]]
   1866         elif celestial.failure_label:
   1867             menuEntries.reasonsWhyNotAvailable['UI/Inflight/POS/AccessPOSRefinery'] = self.GetUnavailableText(celestial)
   1868         if celestial.OfferAccessPOSCompression():
   1869             menuEntries += [[MenuLabel('UI/Inflight/POS/AccessPOSCompression'), self.OpenPOSCompression, (itemID,)]]
   1870         elif celestial.failure_label:
   1871             menuEntries.reasonsWhyNotAvailable['UI/Inflight/POS/AccessPOSCompression'] = self.GetUnavailableText(celestial)
   1872         if celestial.OfferOpenInfrastructureHubPanel():
   1873             menuEntries += [[MenuLabel('UI/FactionWarfare/IHub/OpenInfrastructureHubPanel'), openFunctions.OpenInfrastructureHubPanel, (itemID,)]]
   1874         if celestial.OfferOpenSovFuelDepositWindow():
   1875             menuEntries += [[MenuLabel('UI/Sovereignty/SovHub/ReagentBay/DepositReagents'), openFunctions.OpenSovFuelDepositWindow, (itemID, slimItem)]]
   1876         elif celestial.failure_label:
   1877             menuEntries.reasonsWhyNotAvailable['UI/Sovereignty/SovHub/ReagentBay/DepositReagents'] = self.GetUnavailableText(celestial)
   1878         if celestial.OfferOpenSovHubConfigWindow():
   1879             menuEntries += [[MenuLabel('UI/Menusvc/OpenSovHubConfigWindow'), openFunctions.OpenSovHubWindow, (itemID,)]]
   1880         elif celestial.failure_label:
   1881             menuEntries.reasonsWhyNotAvailable['UI/Menusvc/OpenSovHubConfigWindow'] = self.GetUnavailableText(celestial)
   1882         if celestial.OfferOpenSovSystemCleanup():
   1883             menuEntries += [MenuEntryData(MenuLabel('UI/Sovereignty/SovHub/SystemCleanup/OfferCleanup'), open_sov_system_cleanup, texturePath=eveicon.hourglass)]
   1884         if celestial.OfferTransferSovStructureOwnership():
   1885             menuEntries += [[MenuLabel('UI/Inflight/POS/TransferSovStructureOwnership'), self.TransferOwnership, (itemID,)]]
   1886         if celestial.OfferSelfDestructShipOrPod():
   1887             menuEntries += [[MenuLabel('UI/Inflight/SelfDestructShipOrPod'), self.SelfDestructStructure, (itemID,)]]
   1888         elif celestial.OfferAbortSelfDestructStructure():
   1889             menuEntries += [[MenuLabel('UI/Inflight/AbortSelfDestruct'), self.AbortSelfDestructStructure, (itemID,)]]
   1890         if celestial.OfferAnchorStructure():
   1891             menuEntries += [[MenuLabel('UI/Inflight/POS/AnchorStructure'), sm.StartService('posAnchor').StartAnchorPosSelect, (itemID,)]]
   1892         if celestial.OfferUnanchorStructure():
   1893             menuEntries += [[MenuLabel('UI/Inflight/POS/UnanchorStructure'), self.UnanchorStructure, (itemID,)]]
   1894         if celestial.OfferPutStructureOnline():
   1895             menuEntries += [[MenuLabel('UI/Inflight/PutStructureOnline'), self.ToggleObjectOnline, (itemID, 1)]]
   1896         if celestial.OfferPutStructureOffline():
   1897             menuEntries += [[MenuLabel('UI/Inflight/PutStructureOffline'), self.ToggleObjectOnline, (itemID, 0)]]
   1898         if celestial.OfferRelinquishPOSControl():
   1899             menuEntries += [[MenuLabel('UI/Inflight/POS/RelinquishPOSControl'), self.pwn.RelinquishStructureControl, (slimItem,)]]
   1900         if celestial.OfferAssumeStructureControl():
   1901             menuEntries += [[MenuLabel('UI/Inflight/POS/AssumeStructureControl'), self.pwn.AssumeStructureControl, (slimItem,)]]
   1902         if celestial.OfferUnlockStructureTarget():
   1903             menuEntries += [[MenuLabel('UI/Inflight/POS/UnlcokSTructureTarget'), self.pwn.UnlockStructureTarget, (itemID,)]]
   1904         if celestial.OfferAnchorOrbital():
   1905             menuEntries += [[MenuLabel('UI/Inflight/POS/AnchorObject'), self.AnchorOrbital, (itemID,)]]
   1906         if celestial.OfferUnanchorOrbital():
   1907             menuEntries += [[MenuLabel('UI/Inflight/UnanchorObject'), self.UnanchorOrbital, (itemID,)]]
   1908         if celestial.OfferConfigureOrbitalPoco() or celestial.OfferConfigureOrbitalSkyhook():
   1909             menuEntries += [[MenuLabel('UI/DustLink/ConfigureOrbital'),
   1910               self.ConfigureOrbital,
   1911               (slimItem,),
   1912               eveicon.settings]]
   1913         if celestial.OfferTransferCorporationOwnershipPoco() or celestial.OfferTransferCorporationOwnershipSkyhook():
   1914             menuEntries += [[MenuLabel('UI/Inflight/POS/TransferSovStructureOwnership'),
   1915               self.TransferCorporationOwnership,
   1916               (itemID,),
   1917               eveicon.trade]]
   1918         if celestial.OfferMarkWreckNotViewed():
   1919             menuEntries += [[MenuLabel('UI/Inflight/MarkWreckNotViewed'), sm.GetService('wreck').MarkViewed, (itemID, False)]]
   1920         elif celestial.OfferMarkWreckViewed():
   1921             menuEntries += [[MenuLabel('UI/Inflight/MarkWreckViewed'), sm.GetService('wreck').MarkViewed, (itemID, True)]]
   1922         menuEntries += [None]
   1923         if celestial.OfferCancelLockTarget():
   1924             menuEntries += [[MenuLabel('UI/Inflight/CancelLockTarget'), self.CancelLockTarget, (itemID,)]]
   1925         elif celestial.OfferUnlockTarget():
   1926             menuEntries += [[MenuLabel('UI/Inflight/UnlockTarget'), self.UnlockTarget, (itemID,)]]
   1927         elif celestial.failure_label:
   1928             menuEntries.reasonsWhyNotAvailable['UI/Inflight/UnlockTarget'] = self.GetUnavailableText(celestial)
   1929         if celestial.OfferLockTarget():
   1930             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/LockTarget'), lambda : self.LockTarget(itemID), internalName='LockTarget', typeID=typeID))
   1931         elif celestial.failure_label:
   1932             menuEntries.reasonsWhyNotAvailable['UI/Inflight/LockTarget'] = self.GetUnavailableText(celestial)
   1933         if celestial.OfferFleetTagItem():
   1934             menuEntries += [None]
   1935             tagItemMenu = [(MenuLabel('UI/Fleet/FleetTagNumber'), [ (' ' + str(i), self.TagItem, (itemID, str(i))) for i in xrange(10) ])]
   1936             tagItemMenu += [(MenuLabel('UI/Fleet/FleetTagLetter'), [ (' ' + str(i), self.TagItem, (itemID, str(i))) for i in 'ABCDEFGHIJXYZ' ])]
   1937             menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/FleetTagItem'), tagItemMenu]]
   1938             menuEntries += [[MenuLabel('UI/Fleet/FleetSubmenus/UntagItem'), self.TagItem, (itemID, None)]]
   1939         if celestial.OfferStartConversation():
   1940             menuEntries += [[MenuLabel('UI/Chat/StartConversation'), sm.StartService('agents').OpenDialogueWindow, (sm.StartService('godma').GetType(typeID).agentID,)]]
   1941         elif celestial.failure_label:
   1942             menuEntries.reasonsWhyNotAvailable['UI/Chat/StartConversation'] = self.GetUnavailableText(celestial)
   1943         menuEntries += [None]
   1944         if celestial.OfferSetNewPasswordForContainer():
   1945             desc = localization.GetByLabel('UI/Inventory/ItemActions/SetNewPasswordForContainer')
   1946             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/SetNewPasswordForContainer'), self.AskNewContainerPassword, (itemID, desc, const.SCCPasswordTypeGeneral)]]
   1947         if celestial.OfferSetNewConfigPasswordForContainer():
   1948             desc = localization.GetByLabel('UI/Inventory/ItemActions/SetNewConfigPasswordForContainer')
   1949             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/SetNewConfigPasswordForContainer'), self.AskNewContainerPassword, (itemID, desc, const.SCCPasswordTypeConfig)]]
   1950         if celestial.OfferViewLog():
   1951             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/ViewLog'), openFunctions.ViewAuditLogForALSC, (itemID,)]]
   1952         if celestial.OfferConfigureALSC():
   1953             menuEntries += [[MenuLabel('UI/Inventory/ItemActions/ConfigureALSContainer'), self.ConfigureALSC, (itemID,)]]
   1954         if celestial.OfferRetrievePasswordALSC():
   1955             menuEntries += [[MenuLabel('UI/Commands/RetrievePassword'), self.RetrievePasswordALSC, (itemID,)]]
   1956         if celestial.OfferAccessShippingUnit():
   1957             menuEntries += [[MenuLabel('UI/Menusvc/AccessShippingUnit'), self.OpenShippingUnitStorage, (itemID,)]]
   1958         if celestial.OfferOpenCargoBay():
   1959             menuEntries += [[MenuLabel('UI/Commands/OpenCargo'), cargobay.OpenCargoWindow, [itemID, typeID, self]]]
   1960         if celestial.OfferActivateMicroJumpDrive():
   1961             menuEntries += [[MenuLabel('UI/Inflight/SpaceComponents/MicroJumpDriver/ActivateMicroJumpDrive'), microJumpDriver.ActivateMicroJumpDrive, [sm.GetService('michelle'), itemID]]]
   1962         if celestial.OfferItemTraderAccess():
   1963             menuEntries += [[MenuLabel('UI/Inflight/SpaceComponents/ItemTrader/Access'), self.RequestTrade, [itemID]]]
   1964         if celestial.OfferOpenUnderConstruction():
   1965             menuEntries += [[MenuLabel('UI/Inflight/SpaceComponents/UnderConstruction/Access'), self.OpenUnderConstruction, [itemID]]]
   1966         if celestial.OfferLinkWithShip():
   1967             menuEntries += [[MenuLabel(GetLinkButtonLabelPath(typeID)), linkWithShip.InitiateLink, [sm.GetService('michelle'), itemID]]]
   1968             if session.role & (ROLE_GML | ROLE_WORLDMOD):
   1969                 menuEntries += [['GM: LINK QUICKLY!', linkWithShip.InitiateLinkQuick, [sm.GetService('michelle'), itemID]]]
   1970         if celestial.OfferConnectToPhaseStabilizer():
   1971             menuEntries += [[MenuLabel('UI/Inflight/SpaceComponents/PhaseStabilizer/ConnectShip'), phaseStabilizer.ConnectShip, [sm.GetService('michelle'), itemID]]]
   1972         if celestial.OfferTowableMenu():
   1973             menuEntries.extend(towGameObjective.GetMenuEntries(celestial))
   1974         elif celestial.failure_label:
   1975             menuEntries.reasonsWhyNotAvailable['UI/Inflight/SpaceComponents/TowGameObjective/startTowing'] = self.GetUnavailableText(celestial)
   1976         if celestial.OfferConfigureFacility():
   1977             menuEntries += [[MenuLabel('UI/Menusvc/ConfigureFacility'), self.ConfigureIndustryTax, (itemID, typeID)]]
   1978         if celestial.OfferJumpThroughStargate():
   1979             localStargate = FindLocalStargate(celestial.GetWaypointSolarsystemID())
   1980             if localStargate:
   1981                 menuEntries += [[MenuLabel('UI/Inflight/JumpThroughStargate'),
   1982                   self.StargateJump,
   1983                   (localStargate.itemID,
   1984                    localStargate.typeID,
   1985                    localStargate.jumps[0].toCelestialID,
   1986                    localStargate.jumps[0].locationID),
   1987                   eveicon.jump_to,
   1988                   None,
   1989                   'Jump']]
   1990         if celestial.OfferJumpThroughStructureJumpGate():
   1991             localJumpBridge = FindLocalJumpGateForDestinationPath(celestial.GetWaypointSolarsystemID())
   1992             if localJumpBridge:
   1993                 menuEntries += [[MenuLabel('UI/Inflight/JumpThroughJumpgate'),
   1994                   self.JumpThroughStructureJumpBridge,
   1995                   (localJumpBridge.itemID,),
   1996                   eveicon.jump_to]]
   1997         if celestial.OfferSetDestination():
   1998             menuEntries.append(MenuEntryData(MenuLabel('UI/Inflight/SetDestination'), lambda : sm.StartService('starmap').SetWaypoint(itemID, True)))
   1999         if celestial.OfferAddWaypoint():
   2000             menuEntries += [[MenuLabel('UI/Inflight/AddWaypoint'), sm.StartService('starmap').SetWaypoint, (itemID,)]]
   2001         elif celestial.isWaypoint():
   2002             menuEntries += [[MenuLabel('UI/Inflight/RemoveWaypoint'), sm.StartService('starmap').ClearWaypoints, (itemID,)]]
   2003         if celestial.OfferBroadcastTravelTo():
   2004             menuEntries += [None]
   2005             menuEntries += [MenuEntryData(MenuLabel('UI/Fleet/FleetBroadcast/Commands/BroadcastTravelTo'), lambda : sm.GetService('fleet').SendBroadcast_TravelTo(itemID), texturePath=iconsByBroadcastType[BROADCAST_TRAVEL_TO])]
   2006         if celestial.OfferEditProfileForStructure():
   2007             menuEntries += [[MenuLabel('UI/Commands/EditProfileForStructure'), openFunctions.OpenProfileSettingsForStructure, (itemID,)]]
   2008         if celestial.OfferSetHomeStation():
   2009             menuEntries += [[MenuLabel('UI/Menusvc/SetHomeStation'), self.SetHomeStation, (itemID,)]]
   2010         if celestial.OfferToggleOverviewVisibility():
   2011             menuEntries.append(overviewMenuUtil.GetToggleEntry(groupID))
   2012         if celestial.OfferBookmarkLocation():
   2013             if celestial.IsBeacon():
   2014                 beacon = sm.GetService('michelle').GetItem(itemID)
   2015                 if beacon and hasattr(beacon, 'dunDescriptionID') and beacon.dunDescriptionID:
   2016                     hint = localization.GetByMessageID(beacon.dunDescriptionID)
   2017             if parentID:
   2018                 menuEntries += [None]
   2019             menuEntries += [[MenuLabel('UI/Inflight/BookmarkLocation'), self.Bookmark, (itemID,
   2020                typeID,
   2021                parentID,
   2022                hint)]]
   2023         if celestial.OfferShowLocationOnMap():
   2024             menuEntries += [None]
   2025             menuEntries += [[MenuLabel('UI/Commands/ShowLocationOnMap'), self.ShowInMap, (itemID,)]]
   2026             menuEntries += [[MenuLabel('UI/Inflight/ShowInMapBrowser', {'locationType': groupName}), self.ShowInMapBrowser, (itemID,)]]
   2027         if celestial.OfferAvoidLocation():
   2028             menuEntries += [[MenuLabel('UI/Inflight/AvoidLocation', {'theLocation': mapFunctionID,
   2029                'locationType': groupName}), self.clientPathfinderService.AddAvoidanceItem, (itemID,)]]
   2030         elif celestial.OfferStopAvoidingLocation():
   2031             menuEntries += [[MenuLabel('UI/Inflight/StopAvoidingLocation', {'theLocation': mapFunctionID,
   2032                'locationType': groupName}), self.clientPathfinderService.RemoveAvoidanceItem, (itemID,)]]
   2033         if celestial.OfferViewPlanetaryProduction():
   2034             menuEntries += [[MenuLabel('UI/PI/Common/ViewInPlanetMode'), self.ViewPlanetaryProduction, (itemID,)]]
   2035         elif celestial.OfferExitPlanetaryProduction():
   2036             menuEntries += [[MenuLabel('UI/PI/Common/ExitPlanetMode'), sm.GetService('viewState').CloseSecondaryView, ()]]
   2037         if not celestial.isMultiSelection:
   2038             menuEntries += [[MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo, (typeID,
   2039                itemID,
   2040                0,
   2041                None,
   2042                parentID)]]
   2043         if celestial.OfferMoonMenuOptions():
   2044             menuEntries.append(MenuEntryData(MenuLabel('UI/Menusvc/MoonsMenuOption'), subMenuData=lambda : self.GetMoons(celestial.GetMoonsForPlanet()), texturePath=sm.GetService('bracket').GetBracketIconByGroupID(appConst.groupMoon)))
   2045         if celestial.OfferCustomsOfficeMenu():
   2046             customsOfficeID = celestial.GetPocoOrbitals()[0]
   2047             menuEntries.append(MenuEntryData(MenuLabel('UI/PI/Common/CustomsOffice'), subMenuData=lambda : self.GetCustomsOfficeMenu(customsOfficeID), texturePath=sm.GetService('bracket').GetBracketIconByGroupID(appConst.groupOrbitalInfrastructure), func=lambda : movementFunctions.WarpToItem(customsOfficeID)))
   2048         if celestial.OfferOrbitalSkyhook():
   2049             skyhookIDs = celestial.GetSkyhookOrbitals()
   2050             if skyhookIDs:
   2051                 skyhookID = skyhookIDs[0]
   2052                 menuEntries.append(MenuEntryData(MenuLabel('UI/OrbitalSkyhook/OrbitalSkyhook'), subMenuData=lambda : self.GetCustomsOfficeMenu(skyhookID), texturePath=sm.GetService('bracket').GetBracketIconByGroupID(appConst.groupSkyhook), func=lambda : movementFunctions.WarpToItem(skyhookID)))
   2053         if celestial.OfferPilotMenu():
   2054             menuEntries += [None]
   2055             if slimItem.charID:
   2056                 menuEntries.append(MenuEntryData(MenuLabel('UI/Common/Pilot', {'character': slimItem.charID}), subMenuData=lambda : self.CharacterMenu(slimItem.charID), texturePath=eveicon.person))
   2057             else:
   2058                 menuEntries.append(MenuEntryData(MenuLabel('UI/Menusvc/PilotEmpty'), isEnabled=False, texturePath=eveicon.person))
   2059                 menuEntries.append(MenuEntryData(MenuLabel('UI/Menusvc/OwnerName', {'owner': slimItem.ownerID}), subMenuData=lambda : self.CharacterMenu(slimItem.ownerID), texturePath=eveicon.person))
   2060         if celestial.OfferSimulateShip():
   2061             menuEntries += [(MenuLabel('UI/Fitting/FittingWindow/SimulateShip'), openFunctions.SimulateFitting, (utillib.KeyVal(shipTypeID=typeID, fitData=[]),))]
   2062         if session.role & (ROLE_GML | ROLE_WORLDMOD):
   2063             menuEntries.insert(0, ('GM / WM Extras', ('isDynamic', self.GetGMMenu, (itemID,
   2064                slimItem,
   2065                None,
   2066                None,
   2067                mapItem,
   2068                typeID))))
   2069         return menuEntries
   2070 
   2071     @staticmethod
   2072     def RequestTrade(itemID):
   2073         return sm.GetService('michelle').GetBallpark().componentRegistry.GetComponentForItem(itemID, ITEM_TRADER).RequestTrade()
   2074 
   2075     def OpenUnderConstruction(self, itemID):
   2076         comp = sm.GetService('michelle').GetBallpark().componentRegistry.GetComponentForItem(itemID, UNDER_CONSTRUCTION)
   2077         self.GetCloseAndTryCommand(itemID, comp.OpenUnderConstructionWnd, ())
   2078 
   2079     @staticmethod
   2080     def ViewPlanetaryProduction(planetID, *args):
   2081         return sm.GetService('viewState').ActivateView('planet', planetID=planetID)
   2082 
   2083     def GetMoonMiningPointMenu(self, celestial, slimItem):
   2084         subMenu = MenuList()
   2085         if not celestial.IsMoon():
   2086             return subMenu
   2087         if slimItem:
   2088             beaconItemID = getattr(slimItem, MOON_BEACONID_NAME, None)
   2089             if beaconItemID:
   2090                 subMenu += [[MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo, (invconst.typeMoonMiningBeacon, beaconItemID, 0)]]
   2091         menuEntries = MenuList()
   2092         if celestial.OfferWarpToMoonMiningPoint():
   2093             defaultWarpDist = self.GetDefaultActionDistance('WarpTo')
   2094             label = MenuLabel('UI/Inflight/WarpToMoonMiningPoint', {'distance': fmtutil.FmtDist(float(defaultWarpDist))})
   2095             subMenu += self._GetWarpOptions(movementFunctions.WarpFleetToMiningPointPoint, movementFunctions.WarpToMiningPointPoint, slimItem.itemID, label, defaultWarpDist)
   2096             menuEntries += [[MenuLabel('UI/Inflight/MoonMiningPoint'), subMenu]]
   2097         elif celestial.failure_label:
   2098             menuEntries.reasonsWhyNotAvailable['UI/Inflight/WarpToMoonMiningPoint'] = self.GetUnavailableText(celestial)
   2099         return menuEntries
   2100 
   2101     def JumpThroughStructureJumpBridge(self, structureID):
   2102         bp = sm.StartService('michelle').GetRemotePark()
   2103         if bp is None:
   2104             return
   2105         self.LogNotice('Jump through structure jump bridge', structureID)
   2106         self.GetCloseAndTryCommand(structureID, self.ReallyJumpThroughStructureJumpBridge, (structureID,))
   2107 
   2108     @staticmethod
   2109     def ReallyJumpThroughStructureJumpBridge(structureID):
   2110         bp = sm.StartService('michelle').GetBallpark()
   2111         if bp is None:
   2112             return
   2113         shipSlimItem = bp.GetInvItem(session.shipid)
   2114         jumpBridge = GetJumpBridgeComponent(bp, structureID)
   2115         jumpBridge.ValidateJumpAttempt(shipSlimItem.itemID, shipSlimItem.typeID)
   2116         didJumpThrough = sm.StartService('sessionMgr').PerformSessionChange('jump', sm.RemoteSvc('structureJumpBridgeMgr').CmdJumpThroughStructureStargate, structureID)
   2117         if didJumpThrough:
   2118             sm.GetService('starmap').RemoveWaypointIfFirst(structureID)
   2119         return didJumpThrough
   2120 
   2121     @staticmethod
   2122     def OpenCapitalNavigation(*args):
   2123         if eveCfg.GetActiveShip():
   2124             CapitalNav.Open()
   2125 
   2126     def GetHybridBeaconJumpMenu(self):
   2127         moduleBeaconCallback = self.JumpToFleetModuleBeacon
   2128         deployableBeaconCallback = self.JumpToFleetDeployableBeacon
   2129         structureBeaconCallback = self.JumpToStructureBeacon
   2130         return self._GetCynoTargetSubMenus(moduleBeaconCallback, deployableBeaconCallback, structureBeaconCallback)
   2131 
   2132     def GetHybridBridgeMenu(self):
   2133         moduleBeaconCallback = self.BridgeToFleetModuleBeacon
   2134         deployableBeaconCallback = self.BridgeToFleetDeployableBeacon
   2135         structureBeaconCallback = self.BridgeToBeaconStructure
   2136         return self._GetCynoTargetSubMenus(moduleBeaconCallback, deployableBeaconCallback, structureBeaconCallback)
   2137 
   2138     def GetHybridBeaconGroupJumpMenu(self):
   2139         moduleBeaconCallback = self.GroupJumpToFleetModuleBeacon
   2140         deployableBeaconCallback = self.GroupJumpToFleetDeployableBeacon
   2141         structureBeaconCallback = self.GroupJumpToStructureBeacon
   2142         return self._GetCynoTargetSubMenus(moduleBeaconCallback, deployableBeaconCallback, structureBeaconCallback)
   2143 
   2144     def _GetCynoTargetSubMenus(self, moduleBeaconCallback, deployableBeaconCallback, structureBeaconCallback):
   2145         fullMenu = MenuList()
   2146         menuSize = 20
   2147         if session.fleetid:
   2148             fleetSvc = sm.GetService('fleet')
   2149             fleetModuleTargets = []
   2150             for charID, (solarsystemID, beaconID, typeID) in fleetSvc.GetActiveBeacons().iteritems():
   2151                 if solarsystemID == session.solarsystemid:
   2152                     continue
   2153                 character = cfg.eveowners.Get(charID)
   2154                 cynoTypeText = fleetSvc.GetCynoTypeText(typeID)
   2155                 menuLabel = MenuLabel('UI/Fleet/FleetSubmenus/ModuleCynoBeaconLabel', {'fleetMemberName': character.name,
   2156                  'system': solarsystemID,
   2157                  'cynoType': cynoTypeText})
   2158                 menuArgs = (charID,
   2159                  solarsystemID,
   2160                  beaconID,
   2161                  typeID)
   2162                 sortKey = character.name
   2163                 fleetModuleTargets.append((sortKey, (menuLabel, menuArgs)))
   2164 
   2165             fleetModuleTargets = SortListOfTuples(fleetModuleTargets)
   2166             for menuLabel, menuArgs in fleetModuleTargets:
   2167                 fullMenu.append([menuLabel, moduleBeaconCallback, menuArgs])
   2168 
   2169             fleetDeployableTargets = []
   2170             for deployableID, (solarSystemID, beaconID, ownerID) in fleetSvc.activeDeployableBeacons.iteritems():
   2171                 if solarSystemID == session.solarsystemid:
   2172                     continue
   2173                 ownerName = cfg.eveowners.Get(ownerID)
   2174                 menuLabel = MenuLabel('UI/Fleet/FleetSubmenus/DeployableCynoBeaconLabel', {'fleetMemberName': ownerName.name,
   2175                  'system': solarSystemID})
   2176                 menuArgs = (deployableID, solarSystemID, beaconID)
   2177                 sortKey = ownerName.name
   2178                 fleetDeployableTargets.append((sortKey, (menuLabel, menuArgs)))
   2179 
   2180             fleetDeployableTargets = SortListOfTuples(fleetDeployableTargets)
   2181             for menuLabel, menuArgs in fleetDeployableTargets:
   2182                 fullMenu.append([menuLabel, deployableBeaconCallback, menuArgs])
   2183 
   2184         structureTargets = []
   2185         structureBeacons = sm.GetService('structureDirectory').GetAccessibleOnlineCynoBeaconStructures()
   2186         cfg.evelocations.Prime([ beacon[3] for beacon in structureBeacons ])
   2187         dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation()
   2188         jumpDriveRange = dogmaLocation.GetAttributeValue(eveCfg.GetActiveShip(), const.attributeJumpDriveRange)
   2189         for structureID, typeID, ownerID, solarSystemID, structureState, name in structureBeacons:
   2190             if solarSystemID == session.solarsystemid:
   2191                 continue
   2192             distance = GetLightYearDistance(session.solarsystemid2, solarSystemID)
   2193             if distance > jumpDriveRange:
   2194                 continue
   2195             solarsystem = cfg.evelocations.Get(solarSystemID)
   2196             menuLabel = MenuLabel('UI/Fleet/FleetSubmenus/StructureCynoBeaconLabel', {'structureName': name})
   2197             menuArgs = (solarSystemID, structureID)
   2198             extraArgForLongMenuMerging = solarsystem.name
   2199             structureTargets.append((solarsystem.name, (menuLabel, menuArgs, extraArgForLongMenuMerging)))
   2200 
   2201         structureTargets = SortListOfTuples(structureTargets)
   2202         if len(structureTargets):
   2203             if len(fullMenu) > 0:
   2204                 fullMenu.append(None)
   2205             structureMenu = []
   2206             for menuLabel, menuArgs, extraArgForLongMenuMerging in structureTargets:
   2207                 structureMenu.append([menuLabel,
   2208                  structureBeaconCallback,
   2209                  menuArgs,
   2210                  extraArgForLongMenuMerging])
   2211 
   2212             fullMenu.extend(self.CreateSubMenusForLongMenus(structureMenu, menuSize, subMenuFunc=self.GetJumpSubMenu))
   2213         if len(fullMenu) > 0:
   2214             return fullMenu
   2215         else:
   2216             return ([MenuLabel('UI/Inflight/NoDestination'), self.DoNothing],)
   2217 
   2218     @staticmethod
   2219     def CreateSubMenusForLongMenus(menuList, menuSize, subMenuFunc, *args):
   2220         allMenuItems = []
   2221         menuListLeft = menuList[:]
   2222         while len(menuListLeft) > menuSize:
   2223             allMenuItems.append(menuListLeft[:menuSize])
   2224             menuListLeft = menuListLeft[menuSize:]
   2225 
   2226         if menuListLeft:
   2227             allMenuItems.append(menuListLeft)
   2228         if len(allMenuItems) == 1:
   2229             m = subMenuFunc(allMenuItems[0])
   2230         else:
   2231             m = MenuList()
   2232             for sub in allMenuItems:
   2233                 firstItem = sub[0]
   2234                 lastItem = sub[-1]
   2235                 if firstItem:
   2236                     firstLetter = firstItem[3][0]
   2237                 else:
   2238                     firstLetter = '0'
   2239                 if lastItem:
   2240                     lastLetter = lastItem[3][0]
   2241                 else:
   2242                     lastLetter = '-1'
   2243                 m.append(('%s ... %s' % (firstLetter, lastLetter), ('isDynamic', subMenuFunc, [sub])))
   2244 
   2245         return m
   2246 
   2247     @staticmethod
   2248     def GetJumpSubMenu(subMenuItems, *args):
   2249         m = MenuList()
   2250         for menuItem in subMenuItems:
   2251             if menuItem is None:
   2252                 m.append(None)
   2253                 continue
   2254             name, eachFunc, eachArgs, systemName = menuItem
   2255             m.append([name, eachFunc, eachArgs])
   2256 
   2257         return m
   2258 
   2259     @staticmethod
   2260     def ConfirmMenu(func):
   2261         m = [(MenuLabel('UI/Menusvc/ConfirmMenuOption'), func)]
   2262         return m
   2263 
   2264     @staticmethod
   2265     def WarpToMenu(func, ID):
   2266         ranges = movementFunctions.GetWarpToRanges()
   2267         defMenuWarpOptions = [ (fmtutil.FmtDist(rnge), defaultRangeUtils.SetDefaultWarpToDist, (rnge,)) for rnge in ranges ]
   2268         warpDistMenu = [(MenuLabel('UI/Inflight/WarpToWithin', {'distance': fmtutil.FmtDist(ranges[0])}), func, (ID, float(ranges[0]))),
   2269          (MenuLabel('UI/Inflight/WarpToWithin', {'distance': fmtutil.FmtDist(ranges[1])}), func, (ID, float(ranges[1]))),
   2270          (MenuLabel('UI/Inflight/WarpToWithin', {'distance': fmtutil.FmtDist(ranges[2])}), func, (ID, float(ranges[2]))),
   2271          (MenuLabel('UI/Inflight/WarpToWithin', {'distance': fmtutil.FmtDist(ranges[3])}), func, (ID, float(ranges[3]))),
   2272          (MenuLabel('UI/Inflight/WarpToWithin', {'distance': fmtutil.FmtDist(ranges[4])}), func, (ID, float(ranges[4]))),
   2273          (MenuLabel('UI/Inflight/WarpToWithin', {'distance': fmtutil.FmtDist(ranges[5])}), func, (ID, float(ranges[5]))),
   2274          (MenuLabel('UI/Inflight/WarpToWithin', {'distance': fmtutil.FmtDist(ranges[6])}), func, (ID, float(ranges[6]))),
   2275          None,
   2276          (MenuLabel('UI/Inflight/Submenus/SetDefaultWarpRange'), defMenuWarpOptions)]
   2277         return warpDistMenu
   2278 
   2279     def GetMenuForOwner(self, ownerID):
   2280         owner = cfg.eveowners.Get(ownerID)
   2281         return self.GetMenuFromItemIDTypeID(ownerID, owner.typeID)
   2282 
   2283     def GetMenuFromItemIDTypeID(self, itemID, typeID, invItem = None, includeMarketDetails = False, abstractInfo = None, **kwargs):
   2284         if typeID is None:
   2285             return MenuList()
   2286         if invItem:
   2287             return self.InvItemMenu(invItem)
   2288         groupID = evetypes.GetGroupID(typeID)
   2289         categoryID = evetypes.GetCategoryID(typeID)
   2290         if groupID == const.groupCharacter:
   2291             return self.CharacterMenu(itemID, **kwargs)
   2292         if categoryID in CELESTIAL_MENU_CATEGORIES:
   2293             menu = self.CelestialMenu(itemID, typeID=typeID)
   2294             if includeMarketDetails:
   2295                 menu.extend(self.MarketDetailMenu(typeID))
   2296             return menu
   2297         m = MenuList()
   2298         m += [(MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo, (typeID,
   2299            itemID,
   2300            0,
   2301            None,
   2302            None,
   2303            abstractInfo))]
   2304         if groupID == const.groupCorporation and idCheckers.IsCorporation(itemID) and not idCheckers.IsNPC(itemID):
   2305             m += [(MenuLabel('UI/Commands/GiveMoney'), sm.StartService('wallet').TransferMoney, (session.charid,
   2306                None,
   2307                itemID,
   2308                None))]
   2309         if industryCommon.IsBlueprintCategory(categoryID):
   2310             from eve.client.script.ui.shared.industry.industryWnd import Industry
   2311             bpData = abstractInfo.get('bpData', None) if abstractInfo else None
   2312             m += ((localization.GetByLabel('UI/Industry/ViewInIndustry'), Industry.OpenOrShowBlueprint, (itemID, typeID, bpData)),)
   2313         if groupID in [const.groupCorporation, const.groupAlliance, const.groupFaction]:
   2314             addressBookSvc = sm.GetService('addressbook')
   2315             inAddressbook = addressBookSvc.IsInAddressBook(itemID, 'contact')
   2316             isBlocked = addressBookSvc.IsBlocked(itemID)
   2317             isNPC = idCheckers.IsNPC(itemID)
   2318             if inAddressbook:
   2319                 m += ((MenuLabel('UI/PeopleAndPlaces/EditContact'), addressBookSvc.AddToPersonalMulti, [itemID, 'contact', True]),)
   2320                 m += ((MenuLabel('UI/PeopleAndPlaces/RemoveContact'), addressBookSvc.DeleteEntryMulti, [[itemID], 'contact']),)
   2321             else:
   2322                 m.append(MenuEntryData(MenuLabel('UI/PeopleAndPlaces/AddContact'), lambda : addressBookSvc.AddToPersonalMulti([itemID], 'contact')))
   2323             if not isNPC:
   2324                 if isBlocked:
   2325                     m += ((MenuLabel('UI/PeopleAndPlaces/UnblockContact'), addressBookSvc.UnblockOwner, [[itemID]]),)
   2326                 else:
   2327                     m += ((MenuLabel('UI/PeopleAndPlaces/BlockContact'), addressBookSvc.BlockOwner, [itemID]),)
   2328             iAmDiplomat = (const.corpRoleDirector | const.corpRoleDiplomat) & session.corprole != 0
   2329             if iAmDiplomat:
   2330                 inCorpAddressbook = addressBookSvc.IsInAddressBook(itemID, 'corpcontact')
   2331                 if inCorpAddressbook:
   2332                     m += ((MenuLabel('UI/PeopleAndPlaces/EditCorpContact'), addressBookSvc.AddToPersonalMulti, [itemID, 'corpcontact', True]),)
   2333                     m += ((MenuLabel('UI/PeopleAndPlaces/RemoveCorpContact'), addressBookSvc.DeleteEntryMulti, [[itemID], 'corpcontact']),)
   2334                 else:
   2335                     m += ((MenuLabel('UI/PeopleAndPlaces/AddCorpContact'), addressBookSvc.AddToPersonalMulti, [itemID, 'corpcontact']),)
   2336                 if session.allianceid:
   2337                     execCorp = sm.GetService('alliance').GetAlliance(session.allianceid).executorCorpID == session.corpid
   2338                     if execCorp:
   2339                         inAllianceAddressbook = addressBookSvc.IsInAddressBook(itemID, 'alliancecontact')
   2340                         if inAllianceAddressbook:
   2341                             m += ((MenuLabel('UI/PeopleAndPlaces/EditAllianceContact'), addressBookSvc.AddToPersonalMulti, [itemID, 'alliancecontact', True]),)
   2342                             m += ((MenuLabel('UI/PeopleAndPlaces/RemoveAllianceContact'), addressBookSvc.DeleteEntryMulti, [[itemID], 'alliancecontact']),)
   2343                         else:
   2344                             m += ((MenuLabel('UI/PeopleAndPlaces/AddAllianceContact'), addressBookSvc.AddToPersonalMulti, [itemID, 'alliancecontact']),)
   2345             if session.corprole & const.corpRoleDirector == const.corpRoleDirector and groupID in (const.groupCorporation, const.groupAlliance):
   2346                 if itemID not in (session.corpid, session.allianceid) and not idCheckers.IsNPC(itemID):
   2347                     if sm.GetService('warPermit').CanDeclareWarAgainst(itemID):
   2348                         m += ((MenuLabel('UI/Corporations/CorporationWindow/Alliances/Rankings/DeclareWar'), self.DeclareWarAgainst, [itemID]),)
   2349         if includeMarketDetails:
   2350             if session.charid:
   2351                 if evetypes.GetMarketGroupID(typeID) is not None:
   2352                     self._AddMarketDetailsOption(m, typeID)
   2353                 if evetypes.IsPublished(typeID):
   2354                     m += [(MenuLabel('UI/Inventory/ItemActions/FindInContracts'), sm.GetService('contracts').FindRelated, (typeID,
   2355                        None,
   2356                        None,
   2357                        None,
   2358                        None,
   2359                        None))]
   2360                     m += [[MenuLabel('UI/Inventory/ItemActions/FindPersonalAssets'), invItemFunctions.FindInPersonalAssets, (typeID,)]]
   2361         if categoryID in compareCategories:
   2362             m += [(MenuLabel('UI/Compare/CompareButton'), self.CompareType, (typeID,))]
   2363         if session.role & (ROLE_GML | ROLE_WORLDMOD | ROLE_LEGIONEER):
   2364             charID = itemID if idCheckers.IsOwner(itemID) else None
   2365             m.insert(0, ('GM / WM Extras', ('isDynamic', self.GetGMMenu, (None,
   2366                None,
   2367                charID,
   2368                None,
   2369                None,
   2370                typeID))))
   2371         return m
   2372 
   2373     @staticmethod
   2374     def CompareType(typeID, itemID = 0, *args):
   2375         if use_new_comparison_tool.is_enabled():
   2376             from eve.client.script.ui.comparison.comparisonWindow import ComparisonWindow
   2377             ComparisonWindow.open_and_compare(typeID, itemID)
   2378         else:
   2379             from eve.client.script.ui.shared.neocom.compare import TypeCompare
   2380             typeWnd = TypeCompare.Open()
   2381             typeWnd.AddTypeID(typeID, itemID)
   2382 
   2383     def CompareTypes(self, typeIDs, itemIDs = None):
   2384         if use_new_comparison_tool.is_enabled():
   2385             from eve.client.script.ui.comparison.comparisonWindow import ComparisonWindow
   2386             if itemIDs:
   2387                 type_and_item_ids = [ (type_id, item_id) for type_id, item_id in zip(typeIDs, itemIDs) ]
   2388             else:
   2389                 type_and_item_ids = [ (type_id, None) for type_id in typeIDs ]
   2390             ComparisonWindow.open_and_compare_multiple(type_and_item_ids)
   2391         else:
   2392             for type_id in typeIDs:
   2393                 self.CompareType(type_id)
   2394 
   2395     def GetMenuForSkill(self, typeID):
   2396         m = MenuList()
   2397         if session.role & ROLE_GML == ROLE_GML:
   2398             m.extend(sm.GetService('info').GetGMGiveSkillMenu(typeID))
   2399         skillInfo = sm.GetService('skills').GetSkillIncludingLapsed(typeID)
   2400         if skillInfo is not None:
   2401             m += sm.GetService('skillqueue').GetAddMenuForSkillEntries(typeID, skillInfo)
   2402         else:
   2403             m.append((MenuLabel('UI/Inventory/ItemActions/BuyThisType'), self.QuickBuy, (typeID,)))
   2404         m += self.GetMenuFromItemIDTypeID(None, typeID, includeMarketDetails=True)
   2405         return m
   2406 
   2407     def GetMoons(self, moons):
   2408         if not moons:
   2409             return [(MenuLabel('UI/Menusvc/PlanetHasNoMoons'), self.DoNothing)]
   2410         moons = SortListOfTuples([ (moon.orbitIndex, moon) for moon in moons ])
   2411         moonmenu = []
   2412         for moon in moons:
   2413             label = MenuLabel('UI/Inflight/Submenus/MoonX', {'moonNumber': moon.orbitIndex})
   2414             moonmenu.append(MenuEntryData(label, subMenuData=lambda itemID = moon.itemID: self.ExpandMoon(itemID, moon), func=lambda itemID = moon.itemID: movementFunctions.WarpToItem(itemID)))
   2415 
   2416         return moonmenu
   2417 
   2418     def GetCustomsOfficeMenu(self, customsOfficeID, *args):
   2419         return self.CelestialMenu(customsOfficeID)
   2420 
   2421     @staticmethod
   2422     def TransferToCargo(itemKey):
   2423         sm.GetService('clientDogmaIM').GetDogmaLocation().UnloadAmmoToContainer(session.shipid, itemKey, session.shipid)
   2424 
   2425     @staticmethod
   2426     def LoadCharges(item):
   2427         sm.GetService('clientDogmaIM').GetDogmaLocation().LoadChargeToAllModules(item)
   2428 
   2429     def DoNothing(self, *args):
   2430         pass
   2431 
   2432     @staticmethod
   2433     def ExpandMoon(itemID, moon):
   2434         return StartMenuService().CelestialMenu(itemID, moon)
   2435 
   2436     def Activate(self, slimItem):
   2437         if IsControllingStructure():
   2438             return
   2439         itemID, groupID, categoryID = slimItem.itemID, slimItem.groupID, slimItem.categoryID
   2440         if itemID == session.shipid:
   2441             myship = sm.StartService('godma').GetItem(session.shipid)
   2442             if myship.groupID == const.groupCapsule:
   2443                 bp = sm.StartService('michelle').GetRemotePark()
   2444                 if bp is not None:
   2445                     bp.CmdStop()
   2446             else:
   2447                 uicore.cmd.GetCommandAndExecute('OpenCargoHoldOfActiveShip')
   2448             return
   2449         bp = sm.StartService('michelle').GetBallpark()
   2450         if bp:
   2451             ownBall = bp.GetBall(session.shipid)
   2452             otherBall = bp.GetBall(itemID)
   2453             dist = None
   2454             if ownBall and otherBall:
   2455                 dist = bp.GetSurfaceDist(ownBall.id, otherBall.id)
   2456             if dist < const.minWarpDistance:
   2457                 if groupID == const.groupStation and dist < const.maxDockingDistance:
   2458                     self.Dock(itemID)
   2459                 elif groupID == const.groupControlBunker:
   2460                     openFunctions.OpenInfrastructureHubPanel(otherBall.id)
   2461                 elif groupID != const.groupMissionContainer and groupID in CONTAINERGROUPS:
   2462                     self.OpenCargo(itemID, 'SomeCargo')
   2463                 else:
   2464                     movementFunctions.ShipApproach(itemID)
   2465             else:
   2466                 self.AlignTo(itemID)
   2467 
   2468     def AnchorObject(self, itemID, anchorFlag):
   2469         dogmaLM = self.godma.GetDogmaLM()
   2470         if dogmaLM:
   2471             typeID = sm.StartService('michelle').GetItem(itemID).typeID
   2472             anchoringDelay = self.godma.GetType(typeID).anchoringDelay
   2473             if anchorFlag:
   2474                 dogmaLM.Activate(itemID, const.effectAnchorDrop)
   2475                 prompt_player_fsd_dialog('AnchoringObject', {'delay': anchoringDelay / 1000.0})
   2476             else:
   2477                 dogmaLM.Activate(itemID, const.effectAnchorLift)
   2478                 prompt_player_fsd_dialog('UnanchoringObject', {'delay': anchoringDelay / 1000.0})
   2479 
   2480     def UnanchorStructure(self, itemID):
   2481         item = sm.GetService('michelle').GetItem(itemID)
   2482         orphaned = self.pwn.StructureIsOrphan(itemID)
   2483         if orphaned:
   2484             msgName = 'ConfirmOrphanStructureUnanchor'
   2485         elif item.groupID == const.groupInfrastructureHub:
   2486             msgName = 'ConfirmInfrastructureHubUnanchor'
   2487         elif item.groupID == const.groupAssemblyArray:
   2488             msgName = 'ConfirmAssemblyArrayUnanchor'
   2489         elif item.groupID == const.groupPersonalHangar:
   2490             msgName = 'ConfirmUnanchoringPersonalHangar'
   2491         else:
   2492             msgName = 'ConfirmStructureUnanchor'
   2493         if prompt_player_fsd_dialog(msgName, {'item': item.typeID}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES:
   2494             return
   2495         unanchoringDelay = self.godma.GetType(item.typeID).unanchoringDelay
   2496         dogmaLM = sm.GetService('godma').GetDogmaLM()
   2497         dogmaLM.Activate(itemID, const.effectAnchorLiftForStructures)
   2498         prompt_player_fsd_dialog('UnanchoringObject', {'delay': unanchoringDelay / 1000.0})
   2499 
   2500     def ToggleObjectOnline(self, itemID, onlineFlag):
   2501         dogmaLM = self.godma.GetDogmaLM()
   2502         if dogmaLM:
   2503             item = sm.StartService('michelle').GetItem(itemID)
   2504             if onlineFlag:
   2505                 if item.groupID in (const.groupSovereigntyClaimMarkers,):
   2506                     if prompt_player_fsd_dialog('ConfirmSovStructureOnline', {}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES:
   2507                         return
   2508                 dogmaLM.Activate(itemID, const.effectOnlineForStructures)
   2509             else:
   2510                 if item.groupID == const.groupControlTower:
   2511                     msgName = 'ConfirmTowerOffline'
   2512                 elif item.groupID == const.groupSovereigntyClaimMarkers:
   2513                     msgName = 'ConfirmSovereigntyClaimMarkerOffline'
   2514                 else:
   2515                     msgName = 'ConfirmStructureOffline'
   2516                 if prompt_player_fsd_dialog(msgName, {'item': (const.UE_TYPEID, item.typeID)}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES:
   2517                     return
   2518                 dogmaLM.Deactivate(itemID, const.effectOnlineForStructures)
   2519 
   2520     @staticmethod
   2521     def DeclareWar():
   2522         return menuFunctions.DeclareWar()
   2523 
   2524     @staticmethod
   2525     def DeclareWarAgainst(againstID):
   2526         return menuFunctions.DeclareWarAgainst(againstID)
   2527 
   2528     @staticmethod
   2529     def TransferOwnership(itemID):
   2530         return menuFunctions.TransferOwnership(itemID)
   2531 
   2532     @staticmethod
   2533     def AbortSelfDestructStructure(itemID):
   2534         return menuFunctions.AbortSelfDestructStructure(itemID)
   2535 
   2536     @staticmethod
   2537     def SelfDestructStructure(itemID):
   2538         return menuFunctions.SelfDestructStructure(itemID)
   2539 
   2540     @staticmethod
   2541     def TransferCorporationOwnership(itemID):
   2542         return menuFunctions.TransferCorporationOwnership(itemID)
   2543 
   2544     def AskNewContainerPassword(self, id_, desc, which = 1, setnew = '', setold = ''):
   2545         return menuFunctions.AskNewContainerPassword(self.invCache, id_, desc, which, setnew, setold)
   2546 
   2547     @staticmethod
   2548     def LockDownBlueprint(invItem):
   2549         return invItemFunctions.LockDownBlueprint(invItem)
   2550 
   2551     @staticmethod
   2552     def UnlockBlueprint(invItem):
   2553         return invItemFunctions.UnlockBlueprint(invItem)
   2554 
   2555     def ALSCLock(self, invItems):
   2556         return invItemFunctions.ALSCLock(invItems, self.invCache)
   2557 
   2558     def ALSCUnlock(self, invItems):
   2559         return invItemFunctions.ALSCUnlock(invItems, self.invCache)
   2560 
   2561     def ConfigureALSC(self, itemID):
   2562         return menuFunctions.ConfigureALSC(itemID, self.invCache)
   2563 
   2564     def RetrievePasswordALSC(self, itemID):
   2565         return menuFunctions.RetrievePasswordALSC(itemID, self.invCache)
   2566 
   2567     def OpenShippingUnitStorage(self, itemID):
   2568         self.GetCloseAndTryCommand(itemID, self.ReallyOpenShippingUnitStorage, (itemID,))
   2569 
   2570     @staticmethod
   2571     def ReallyOpenShippingUnitStorage(itemID):
   2572         entity = moniker.GetEntityAccess()
   2573         if entity:
   2574             entity.OpenShippingUnitStorage(itemID)
   2575 
   2576     def GetFleetMemberMenu(self, func, args):
   2577         menuSize = 20
   2578         watchlistCharIDs = sm.GetService('fleet').GetFavorites()
   2579         charIDsInBallpark = set()
   2580         bp = sm.GetService('michelle').GetBallpark()
   2581         if bp:
   2582             charIDsInBallpark = set(filter(None, {getattr(x, 'charID', None) for x in bp.slimItems.itervalues()}))
   2583         fleet = []
   2584         watchlistMembers = []
   2585         for member in sm.GetService('fleet').GetMembers().itervalues():
   2586             if member.charID == session.charid or member.charID not in charIDsInBallpark:
   2587                 continue
   2588             data = cfg.eveowners.Get(member.charID)
   2589             memberInfo = (data.name.lower(), (member.charID, data.name))
   2590             fleet.append(memberInfo)
   2591             if member.charID in watchlistCharIDs:
   2592                 watchlistMembers.append(memberInfo)
   2593 
   2594         fleet = SortListOfTuples(fleet)
   2595         if watchlistMembers:
   2596             watchlistMembers = SortListOfTuples(watchlistMembers)
   2597             watchlistEntry = [(localization.GetByLabel('UI/Fleet/WatchList'), ('isDynamic', self.GetSubFleetMemberMenu, (watchlistMembers, func, args))), None]
   2598         else:
   2599             watchlistEntry = []
   2600         alles = []
   2601         while len(fleet) > menuSize:
   2602             alles.append(fleet[:menuSize])
   2603             fleet = fleet[menuSize:]
   2604 
   2605         if fleet:
   2606             alles.append(fleet)
   2607         if not alles:
   2608             return [(MenuLabel('UI/Fleet/NoValidOptions'), None)]
   2609         elif len(alles) == 1:
   2610             return watchlistEntry + self.GetSubFleetMemberMenu(alles[0], func, args)
   2611         else:
   2612             return watchlistEntry + [ ('%c ... %c' % (sub[0][1][0], sub[-1][1][0]), ('isDynamic', self.GetSubFleetMemberMenu, (sub, func, args))) for sub in alles ]
   2613 
   2614     @staticmethod
   2615     def GetSubFleetMemberMenu(memberIDs, func, args):
   2616         return [ [name, func, (charID, args)] for charID, name in memberIDs ]
   2617 
   2618     def BridgeToMember(self, charID):
   2619         beaconStuff = sm.GetService('fleet').GetActiveBeaconForChar(charID)
   2620         if beaconStuff is None:
   2621             return
   2622         solarsystemID, beaconID, typeID = beaconStuff
   2623         self.BridgeToFleetModuleBeacon(charID, solarsystemID, beaconID, typeID)
   2624 
   2625     @staticmethod
   2626     def BridgeToBeaconStructure(solarSystemID, structureID):
   2627         sm.GetService('cynoTravel').BridgeToBeaconStructure(solarSystemID, structureID)
   2628 
   2629     @staticmethod
   2630     def BridgeToFleetModuleBeacon(charID, solarsystemID, beaconID, typeID):
   2631         sm.GetService('cynoTravel').BridgeToFleetModuleBeacon(charID, solarsystemID, beaconID)
   2632 
   2633     @staticmethod
   2634     def BridgeToFleetDeployableBeacon(deployableID, solarsystemID, beaconID):
   2635         sm.GetService('cynoTravel').BridgeToFleetDeployableBeacon(deployableID, solarsystemID, beaconID)
   2636 
   2637     @staticmethod
   2638     def JumpThroughFleet(otherCharID, otherShipID):
   2639         sm.GetService('cynoTravel').JumpThroughFleet(otherCharID, otherShipID)
   2640 
   2641     def JumpToMember(self, charid):
   2642         beaconStuff = sm.GetService('fleet').GetActiveBeaconForChar(charid)
   2643         if beaconStuff is None:
   2644             return
   2645         solarsystemID, beaconID, typeID = beaconStuff
   2646         self.JumpToFleetModuleBeacon(charid, solarsystemID, beaconID, typeID)
   2647 
   2648     @staticmethod
   2649     def JumpToFleetModuleBeacon(charid, solarsystemID, beaconID, typeID):
   2650         sm.GetService('cynoTravel').JumpToFleetModuleBeacon(charid, solarsystemID, beaconID)
   2651 
   2652     @staticmethod
   2653     def JumpToFleetDeployableBeacon(deployableID, solarsystemID, beaconID):
   2654         sm.GetService('cynoTravel').JumpToFleetDeployableBeacon(deployableID, solarsystemID, beaconID)
   2655 
   2656     @staticmethod
   2657     def JumpToStructureBeacon(solarSystemID, structureID):
   2658         sm.GetService('cynoTravel').JumpToStructureBeacon(solarSystemID, structureID)
   2659 
   2660     def GroupJumpToMember(self, charid):
   2661         beaconStuff = sm.GetService('fleet').GetActiveBeaconForChar(charid)
   2662         if beaconStuff is None:
   2663             return
   2664         solarsystemID, beaconID, typeID = beaconStuff
   2665         self.GroupJumpToFleetModuleBeacon(charid, solarsystemID, beaconID, typeID)
   2666 
   2667     @staticmethod
   2668     def GroupJumpToFleetModuleBeacon(charid, solarsystemID, beaconID, typeID):
   2669         sm.GetService('cynoTravel').GroupJumpToFleetModuleBeacon(charid, solarsystemID, beaconID)
   2670 
   2671     @staticmethod
   2672     def GroupJumpToFleetDeployableBeacon(deployableID, solarsystemID, beaconID):
   2673         sm.GetService('cynoTravel').GroupJumpToFleetDeployableBeacon(deployableID, solarsystemID, beaconID)
   2674 
   2675     @staticmethod
   2676     def GroupJumpToStructureBeacon(solarSystemID, structureID):
   2677         sm.GetService('cynoTravel').GroupJumpToStructureBeacon(solarSystemID, structureID)
   2678 
   2679     @staticmethod
   2680     def LeaveFleet():
   2681         sm.GetService('fleet').LeaveFleet()
   2682 
   2683     @staticmethod
   2684     def MakeLeader(charid):
   2685         sm.GetService('fleet').MakeLeader(charid)
   2686 
   2687     @staticmethod
   2688     def KickMember(charid):
   2689         sm.GetService('fleet').KickMember(charid)
   2690 
   2691     @staticmethod
   2692     def InviteToFleet(charIDs, ignoreWars = 0):
   2693         if type(charIDs) != list:
   2694             charIDs = [charIDs]
   2695         charErrors = {}
   2696         for charID in charIDs:
   2697             try:
   2698                 sm.GetService('fleet').Invite(charID, None, None, None)
   2699             except UserError as ue:
   2700                 charErrors[charID] = ue
   2701                 sys.exc_clear()
   2702 
   2703         if len(charErrors) == 1:
   2704             raise charErrors.values()[0]
   2705         elif len(charErrors) > 1:
   2706             charNames = None
   2707             for charID in charErrors.iterkeys():
   2708                 if charNames is not None:
   2709                     charNames += ', %s' % cfg.eveowners.Get(charID).name
   2710                 else:
   2711                     charNames = cfg.eveowners.Get(charID).name
   2712 
   2713             raise UserError('FleetInviteMultipleErrors', {'namelist': charNames})
   2714 
   2715     @staticmethod
   2716     def WarpFleet(targetID, warpRange = None):
   2717         michelle = sm.GetService('michelle')
   2718         bp = michelle.GetRemotePark()
   2719         if bp is not None:
   2720             sm.GetService('autoPilot').CancelSystemNavigation()
   2721             michelle.CmdWarpToStuff('item', targetID, minRange=warpRange, fleet=True)
   2722             sm.StartService('space').WarpDestination(celestialID=targetID)
   2723 
   2724     @staticmethod
   2725     def WarpToMember(charID, warpRange = None):
   2726         michelle = sm.GetService('michelle')
   2727         bp = michelle.GetRemotePark()
   2728         if bp is not None:
   2729             sm.GetService('autoPilot').CancelSystemNavigation()
   2730             michelle.CmdWarpToStuff('char', charID, minRange=warpRange)
   2731             sm.StartService('space').WarpDestination(fleetMemberID=charID)
   2732 
   2733     @staticmethod
   2734     def WarpFleetToMember(charID, warpRange = None):
   2735         michelle = sm.GetService('michelle')
   2736         bp = michelle.GetRemotePark()
   2737         if bp is not None:
   2738             sm.GetService('autoPilot').CancelSystemNavigation()
   2739             michelle.CmdWarpToStuff('char', charID, minRange=warpRange, fleet=True)
   2740             sm.StartService('space').WarpDestination(fleetMemberID=charID)
   2741 
   2742     @staticmethod
   2743     def TacticalItemClicked(itemID):
   2744         isTargeted = sm.GetService('target').IsTarget(itemID)
   2745         if isTargeted:
   2746             sm.GetService('stateSvc').SetState(itemID, state.activeTarget, 1)
   2747         uicore.cmd.ExecuteCombatCommand(itemID, uiconst.UI_CLICK)
   2748 
   2749     def AlignTo(self, alignID):
   2750         if alignID == session.shipid:
   2751             return
   2752         if self._CheckAlignToSiteBracket(alignID):
   2753             return
   2754         self._AlignTo(alignID, isBookmark=False)
   2755 
   2756     def _AlignTo(self, alignID, isBookmark = False):
   2757         bp = sm.GetService('michelle').GetRemotePark()
   2758         if bp is None:
   2759             return
   2760         sm.GetService('tacticalNavigation').NotifyOfAlignCommand(alignID)
   2761         if isBookmark:
   2762             targetID, bookmarkID = None, alignID
   2763         else:
   2764             targetID, bookmarkID = alignID, None
   2765         self.StoreAlignTarget(alignTargetID=targetID, aligningToBookmark=isBookmark)
   2766         sm.GetService('space').SetIndicationTextInstantly(ballMode=destiny.DSTBALL_GOTO, followId=targetID, followRange=None)
   2767         bp.CmdAlignTo(dstID=targetID, bookmarkID=bookmarkID)
   2768         sm.GetService('autoPilot').CancelSystemNavigation()
   2769         if not isBookmark:
   2770             sm.GetService('flightPredictionSvc').OptionActivated('AlignTo', alignID)
   2771 
   2772     @staticmethod
   2773     def _CheckAlignToSiteBracket(itemID):
   2774         bracket = sm.GetService('sensorSuite').siteController.spaceLocations.GetBracketByBallID(itemID)
   2775         if bracket:
   2776             bracket.AlignTo()
   2777             return True
   2778         return False
   2779 
   2780     def AlignToBookmark(self, alignID):
   2781         self._AlignTo(alignID, isBookmark=True)
   2782 
   2783     def StoreAlignTarget(self, alignTargetID = None, aligningToBookmark = False, *args):
   2784         self.lastAlignTargetID = alignTargetID
   2785         self.lastAlignedToBookmark = aligningToBookmark
   2786 
   2787     def GetLastAlignTarget(self, *args):
   2788         return (self.lastAlignTargetID, self.lastAlignedToBookmark)
   2789 
   2790     def ClearAlignTargets(self, *args):
   2791         self.lastAlignTargetID = None
   2792         self.lastAlignedToBookmark = None
   2793 
   2794     @staticmethod
   2795     def TagItem(itemID, tag):
   2796         bp = sm.StartService('michelle').GetRemotePark()
   2797         if bp:
   2798             bp.CmdFleetTagTarget(itemID, tag)
   2799 
   2800     @staticmethod
   2801     def LockTarget(targetID):
   2802         sm.StartService('target').TryLockTarget(targetID)
   2803 
   2804     @staticmethod
   2805     def UnlockTarget(targetID):
   2806         sm.StartService('target').UnlockTarget(targetID)
   2807 
   2808     @staticmethod
   2809     def CancelLockTarget(targetID):
   2810         sm.StartService('target').CancelAddTarget(targetID)
   2811 
   2812     @staticmethod
   2813     def ShowInfo(typeID, itemID = None, new = 0, rec = None, parentID = None, abstractInfo = None, *args):
   2814         sm.GetService('info').ShowInfo(typeID, itemID, new, rec, parentID, abstractinfo=abstractInfo)
   2815 
   2816     @staticmethod
   2817     def ShowInfoForItem(itemID):
   2818         if sm.GetService('sensorSuite').IsSiteBall(itemID):
   2819             return
   2820         bp = sm.StartService('michelle').GetBallpark()
   2821         if bp:
   2822             itemTypeID = bp.GetInvItem(itemID).typeID
   2823             sm.GetService('info').ShowInfo(itemTypeID, itemID)
   2824 
   2825     @staticmethod
   2826     def PreviewType(typeID):
   2827         sm.GetService('preview').PreviewType(typeID)
   2828 
   2829     def StoreVessel(self, destID, shipID):
   2830         if shipID != session.shipid:
   2831             return
   2832         shipItem = self.godma.GetStateManager().GetItem(shipID)
   2833         if shipItem.groupID == const.groupCapsule:
   2834             return
   2835         destItem = uix.GetBallparkRecord(destID)
   2836         if destItem.categoryID == const.categoryShip:
   2837             msgName = 'ConfirmStoreVesselInShip'
   2838         else:
   2839             msgName = 'ConfirmStoreVesselInStructure'
   2840         if prompt_player_fsd_dialog(msgName, {'dest': destItem.typeID}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES:
   2841             return
   2842         if shipID != session.shipid:
   2843             return
   2844         shipItem = self.godma.GetStateManager().GetItem(shipID)
   2845         if shipItem.groupID == const.groupCapsule:
   2846             return
   2847         ship = sm.StartService('gameui').GetShipAccess()
   2848         if ship:
   2849             sm.ScatterEvent('OnBeforeActiveShipChanged', shipID, eveCfg.GetActiveShip())
   2850             sm.StartService('sessionMgr').PerformSessionChange('storeVessel', ship.StoreVessel, destID)
   2851 
   2852     @staticmethod
   2853     def OpenCorpHangarArray(itemID):
   2854         Inventory.OpenOrShow(invID=('POSCorpHangars', itemID))
   2855 
   2856     @staticmethod
   2857     def OpenPersonalHangar(itemID):
   2858         Inventory.OpenOrShow(invID=('POSPersonalHangar', itemID))
   2859 
   2860     @staticmethod
   2861     def OpenPOSSilo(itemID):
   2862         Inventory.OpenOrShow(invID=('POSSilo', itemID))
   2863 
   2864     @staticmethod
   2865     def OpenPOSMobileReactor(itemID):
   2866         Inventory.OpenOrShow(invID=('POSMobileReactor', itemID))
   2867 
   2868     @staticmethod
   2869     def OpenPOSShipMaintenanceArray(itemID):
   2870         Inventory.OpenOrShow(invID=('POSShipMaintenanceArray', itemID))
   2871 
   2872     @staticmethod
   2873     def OpenPOSStructureChargesStorage(itemID):
   2874         Inventory.OpenOrShow(invID=('POSStructureChargesStorage', itemID))
   2875 
   2876     @staticmethod
   2877     def OpenPOSStructureChargeCrystal(itemID):
   2878         Inventory.OpenOrShow(invID=('POSStructureChargeCrystal', itemID))
   2879 
   2880     @staticmethod
   2881     def OpenPOSFuelBay(itemID):
   2882         Inventory.OpenOrShow(invID=('POSFuelBay', itemID))
   2883 
   2884     @staticmethod
   2885     def OpenPOSRefinery(itemID):
   2886         Inventory.OpenOrShow(invID=('POSRefinery', itemID))
   2887 
   2888     @staticmethod
   2889     def OpenPOSCompression(itemID):
   2890         Inventory.OpenOrShow(invID=('POSCompression', itemID))
   2891 
   2892     @staticmethod
   2893     def OpenPOSStructureCharges(itemID, showCapacity = 0):
   2894         Inventory.OpenOrShow(invID=('POSStructureCharges', itemID))
   2895 
   2896     @staticmethod
   2897     def OpenStrontiumBay(itemID):
   2898         Inventory.OpenOrShow(invID=('POSStrontiumBay', itemID))
   2899 
   2900     @staticmethod
   2901     def OpenMoonMaterialBay(itemID):
   2902         Inventory.OpenOrShow(invID=('StructureMoonMaterialBay', itemID))
   2903 
   2904     def ManageControlTower(self, itemID):
   2905         uthread.new(self._ManageControlTower, itemID)
   2906 
   2907     @staticmethod
   2908     def _ManageControlTower(itemID):
   2909         uicore.cmd.GetCommandAndExecute('OpenMoonMining', itemID)
   2910 
   2911     @staticmethod
   2912     def OpenSpaceComponentInventory(itemID):
   2913         Inventory.OpenOrShow(invID=('SpaceComponentInventory', itemID))
   2914 
   2915     @staticmethod
   2916     def Bookmark(itemID, typeID, parentID, note = None):
   2917         sm.StartService('addressbook').BookmarkLocationPopup(itemID, typeID, parentID, note)
   2918 
   2919     @staticmethod
   2920     def ShowInMapBrowser(itemID, *args):
   2921         uicore.cmd.GetCommandAndExecute('OpenMapBrowser', itemID)
   2922 
   2923     @staticmethod
   2924     def ShowInMap(itemID, *args):
   2925         OpenMap(interestID=itemID)
   2926 
   2927     def Dock(self, itemID):
   2928         item = sm.GetService('michelle').GetItem(itemID)
   2929         message_bus = JourneyMessenger(sm.GetService('publicGatewaySvc'))
   2930         uthread.new(message_bus.linked, 'Dock')
   2931         if item and item.categoryID == const.categoryStation:
   2932             self.DockStation(itemID)
   2933         elif item and item.categoryID == const.categoryStructure:
   2934             sm.GetService('structureDocking').Dock(itemID)
   2935 
   2936     def DockStation(self, itemID):
   2937         sm.ScatterEvent('OnClientEvent_DockCmdExecuted', itemID)
   2938         bp = sm.StartService('michelle').GetBallpark()
   2939         if not bp:
   2940             return
   2941         self.GetCloseAndTryCommand(itemID, movementFunctions.RealDock, (itemID,))
   2942 
   2943     def GetIllegality(self, itemID, typeID = None, solarSystemID = None):
   2944         if solarSystemID is None:
   2945             solarSystemID = session.solarsystemid
   2946         toFactionID = sm.StartService('faction').GetFactionOfSolarSystem(solarSystemID)
   2947         if typeID is not None and evetypes.GetGroupID(typeID) not in (const.groupCargoContainer,
   2948          const.groupSecureCargoContainer,
   2949          const.groupAuditLogSecureContainer,
   2950          const.groupFreightContainer):
   2951             illegality = inventorycommon.typeHelpers.GetIllegalityInFaction(typeID, toFactionID)
   2952             if illegality:
   2953                 return evetypes.GetName(typeID)
   2954             return ''
   2955         stuff = ''
   2956         invItem = self.invCache.GetInventoryFromId(itemID)
   2957         for item in invItem.List():
   2958             try:
   2959                 illegality = inventorycommon.typeHelpers.GetIllegalityInFaction(item.typeID, toFactionID)
   2960                 if illegality:
   2961                     stuff += evetypes.GetName(item.typeID) + ', '
   2962                 if evetypes.GetGroupID(item.typeID) in (const.groupCargoContainer,
   2963                  const.groupSecureCargoContainer,
   2964                  const.groupAuditLogSecureContainer,
   2965                  const.groupFreightContainer):
   2966                     sublegality = self.GetIllegality(item.itemID, solarSystemID=solarSystemID)
   2967                     if sublegality:
   2968                         stuff += sublegality + ', '
   2969             except Exception:
   2970                 log.LogTraceback('bork in illegality check 2')
   2971                 sys.exc_clear()
   2972 
   2973         return stuff[:-2]
   2974 
   2975     def StargateJump(self, stargateID, typeID, beaconID = None, solarSystemID = None):
   2976         if beaconID:
   2977             gateJumpSvc = sm.GetService('gatejump')
   2978             if gateJumpSvc.IsNextSystemInRoute(solarSystemID):
   2979                 sm.ScatterEvent('OnClientEvent_JumpToNextSystemInRouteCmdExecuted')
   2980             self.GetCloseAndTryCommand(stargateID, gateJumpSvc.JumpThroughGate, (stargateID,
   2981              typeID,
   2982              beaconID,
   2983              solarSystemID), interactionRange=const.maxStargateJumpingDistance)
   2984 
   2985     def ActivateAccelerationGate(self, gateID):
   2986         slimItem = sm.StartService('michelle').GetBallpark().GetInvItem(gateID)
   2987         if slimItem:
   2988             interactionRange = getattr(slimItem, 'gateActivationRange', const.maxStargateJumpingDistance) or const.maxStargateJumpingDistance
   2989         else:
   2990             interactionRange = const.maxStargateJumpingDistance
   2991         self.GetCloseAndTryCommand(gateID, movementFunctions.RealActivateAccelerationGate, (gateID,), interactionRange=interactionRange)
   2992 
   2993     def ActivateAbyssalAccelerationGate(self, gateID):
   2994         self.GetCloseAndTryCommand(gateID, movementFunctions.RealActivateAbyssalGate, (gateID,), interactionRange=const.maxStargateJumpingDistance)
   2995 
   2996     def ActivateAbyssalEndGate(self, gateID):
   2997         self.GetCloseAndTryCommand(gateID, movementFunctions.RealActivateAbyssalEndGate, (gateID,), interactionRange=const.maxStargateJumpingDistance)
   2998 
   2999     def ActivatePVPAbyssalEndGate(self, gateID):
   3000         self.GetCloseAndTryCommand(gateID, movementFunctions.RealActivatePVPAbyssalEndGate, (gateID,), interactionRange=const.maxStargateJumpingDistance)
   3001 
   3002     def ActivateVoidSpaceExitGate(self, gateID):
   3003         self.GetCloseAndTryCommand(gateID, movementFunctions.RealActivateVoidSpaceExitGate, (gateID,), interactionRange=const.maxStargateJumpingDistance)
   3004 
   3005     def ActivateAbyssalEntranceAccelerationGate(self, id):
   3006         self.GetCloseAndTryCommand(id, movementFunctions.RealActivateEntranceToAbyssalGate, (id,), interactionRange=const.maxStargateJumpingDistance)
   3007 
   3008     def ActivateRandomJumpTraceGate(self, id):
   3009         self.GetCloseAndTryCommand(id, movementFunctions.RealActivateRandomFilamentGate, (id,), interactionRange=const.maxStargateJumpingDistance)
   3010 
   3011     def EnterWormhole(self, itemID):
   3012         self.GetCloseAndTryCommand(itemID, movementFunctions.RealEnterWormhole, (itemID,), interactionRange=const.maxWormholeEnterDistance)
   3013 
   3014     def JumpThroughShipcaster(self, itemID):
   3015         targetSolarsystemID, targetLandingPadID = GetTargetForShipcaster(itemID)
   3016         self.GetCloseAndTryCommand(itemID, movementFunctions.RealJumpThroughShipcaster, (itemID, targetSolarsystemID, targetLandingPadID), interactionRange=SHIPCASTER_PROXIMITY_TO_JUMP)
   3017 
   3018     def JumpThroughStarterShipcaster(self, itemID):
   3019         self.GetCloseAndTryCommand(itemID, movementFunctions.RealJumpThroughStarterShipcaster, (itemID,), interactionRange=SHIPCASTER_PROXIMITY_TO_JUMP)
   3020 
   3021     @staticmethod
   3022     def CopyItemIDToClipboard(itemID):
   3023         blue.pyos.SetClipboardData(str(itemID))
   3024 
   3025     def OpenCargo(self, itemID, *args):
   3026         slimItem = sm.StartService('michelle').GetBallpark().GetInvItem(itemID)
   3027         if slimItem:
   3028             sm.ScatterEvent('OnOpenCargoExecuted', slimItem)
   3029         self.GetCloseAndTryCommand(itemID, self.RealOpenCargo, (itemID,))
   3030         if self.IsTooFarToExecuteCommand(itemID):
   3031             prompt_player_fsd_dialog('OpenCargoTooFar')
   3032 
   3033     def RealOpenCargo(self, itemID, *args):
   3034         if getattr(self, '_openingCargo', 0):
   3035             return
   3036         setattr(self, '_openingCargo', 1)
   3037         uthread.new(self._OpenCargo, itemID)
   3038 
   3039     def _OpenCargo(self, _id):
   3040         if type(_id) != types.ListType:
   3041             _id = [_id]
   3042         for itemID in _id:
   3043             try:
   3044                 if itemID == eveCfg.GetActiveShip():
   3045                     uicore.cmd.GetCommandAndExecute('OpenCargoHoldOfActiveShip')
   3046                 else:
   3047                     slim = sm.GetService('michelle').GetItem(itemID)
   3048                     if slim and slim.groupID == const.groupWreck:
   3049                         invID = ('ItemWreck', itemID)
   3050                     else:
   3051                         invID = ('ItemFloatingCargo', itemID)
   3052                     invCtrl.GetInvCtrlFromInvID(invID).GetItems()
   3053                     if not (slim and HasCargoBayComponent(slim.typeID)):
   3054                         sm.GetService('inv').AddTemporaryInvLocation(invID)
   3055                     Inventory.OpenOrShow(invID=invID)
   3056             finally:
   3057                 self._openingCargo = 0
   3058 
   3059     def OpenMercenaryDen(self, itemID):
   3060         self.GetCloseAndTryCommand(itemID, self.RealOpenMercenaryDen, (itemID,))
   3061         if not is_mercenary_den_close_enough_to_configure(itemID):
   3062             prompt_player_fsd_dialog('ConfigureMercenaryDenTooFar')
   3063 
   3064     def RealOpenMercenaryDen(self, itemID):
   3065         slim = sm.GetService('michelle').GetItem(itemID)
   3066         if slim and HasMercenaryDenComponent(slim.typeID):
   3067             openFunctions.OpenMercenaryDenWindow(slim.itemID, slim.typeID)
   3068 
   3069     @staticmethod
   3070     def OpenPlanetCustomsOfficeImportWindow(customsOfficeID):
   3071         sm.GetService('planetUI').OpenPlanetCustomsOfficeImportWindow(customsOfficeID)
   3072 
   3073     @staticmethod
   3074     def OpenOrbitalSkyhookWindow(itemID):
   3075         from eve.client.script.ui.shared.skyhook.skyhookWnd import OpenSkyhookWindow
   3076         OpenSkyhookWindow(itemID)
   3077 
   3078     @staticmethod
   3079     def OpenUpgradeWindow(orbitalID):
   3080         sm.GetService('planetUI').OpenUpgradeWindow(orbitalID)
   3081 
   3082     @staticmethod
   3083     def AbandonLoot(wreckID, *args):
   3084         return menuFunctions.AbandonLoot(wreckID)
   3085 
   3086     @staticmethod
   3087     def AbandonAllLoot(wreckID, *args):
   3088         return menuFunctions.AbandonAllLoot(wreckID)
   3089 
   3090     def ShipCloneConfig(self, shipID = None):
   3091         if shipID == eveCfg.GetActiveShip():
   3092             uthread.new(self._ShipCloneConfig)
   3093 
   3094     @staticmethod
   3095     def _ShipCloneConfig():
   3096         uicore.cmd.GetCommandAndExecute('OpenShipConfig')
   3097 
   3098     @staticmethod
   3099     def EnterPOSPassword():
   3100         sm.StartService('pwn').EnterShipPassword()
   3101 
   3102     @staticmethod
   3103     def EnterForceFieldPassword(towerID):
   3104         sm.StartService('pwn').EnterTowerPassword(towerID)
   3105 
   3106     @staticmethod
   3107     def Eject():
   3108         return menuFunctions.Eject()
   3109 
   3110     @staticmethod
   3111     def Board(shipID):
   3112         return menuFunctions.Board(shipID)
   3113 
   3114     @staticmethod
   3115     def BoardSMAShip(structureID, shipID):
   3116         return menuFunctions.BoardSMAShip(structureID, shipID)
   3117 
   3118     @staticmethod
   3119     def ToggleAutopilot(on):
   3120         if on:
   3121             sm.StartService('autoPilot').SetOn()
   3122         else:
   3123             sm.StartService('autoPilot').SetOff('toggled through menu')
   3124 
   3125     @staticmethod
   3126     def AbortSelfDestructShip(pickid):
   3127         return menuFunctions.AbortSelfDestructShip(pickid)
   3128 
   3129     @staticmethod
   3130     def SelfDestructShip(pickid):
   3131         return menuFunctions.SelfDestructShip(pickid)
   3132 
   3133     @staticmethod
   3134     def SafeLogoff():
   3135         return menuFunctions.SafeLogoff()
   3136 
   3137     @staticmethod
   3138     def SetParent(pickid):
   3139         sm.GetService('sceneManager').GetActiveSpaceCamera().LookAt(pickid, smooth=False)
   3140 
   3141     @staticmethod
   3142     def SetInterest(pickid):
   3143         sm.GetService('sceneManager').GetActiveSpaceCamera().Track(pickid)
   3144 
   3145     @staticmethod
   3146     def TryLookAt(itemID):
   3147         return menuFunctions.TryLookAt(itemID)
   3148 
   3149     @staticmethod
   3150     def ToggleLookAt(itemID, **kwargs):
   3151         return menuFunctions.ToggleLookAt(itemID, **kwargs)
   3152 
   3153     @staticmethod
   3154     def SelectTarget(itemID):
   3155         sm.GetService('stateSvc').SetState(itemID, states.multiSelected, True)
   3156         if itemID in sm.GetService('fighters').shipFighterState.GetAllFighterIDsInSpace() or itemID == session.shipid:
   3157             movementFunctions.SelectForNavigation(itemID)
   3158 
   3159     def Scoop(self, objectID, typeID, password = None):
   3160         self.GetCloseAndTryCommand(objectID, self.RealScoop, (objectID, typeID, password))
   3161 
   3162     def RealScoop(self, objectID, typeID, password = None):
   3163         ship = sm.StartService('gameui').GetShipAccess()
   3164         if ship:
   3165             if not self.CheckIllegalOkay(objectID, typeID):
   3166                 return
   3167             if not self.crimewatchSvc.IsOkToScoopItem(objectID):
   3168                 self.crimewatchSvc.SafetyActivated(const.shipSafetyLevelPartial)
   3169                 return
   3170             try:
   3171                 if evetypes.GetCategoryID(typeID) == const.categoryFighter:
   3172                     self.ScoopAbandonedFighterFromSpace(objectID, const.flagCargo)
   3173                 elif password is None:
   3174                     ship.Scoop(objectID)
   3175                 else:
   3176                     ship.Scoop(objectID, password)
   3177             except UserError as e:
   3178                 if e.msg == 'ShpScoopSecureCC':
   3179                     if password:
   3180                         caption = localization.GetByLabel('UI/Menusvc/IncorrectPassword')
   3181                         label = localization.GetByLabel('UI/Menusvc/PleaseTryEnteringPasswordAgain')
   3182                     else:
   3183                         caption = localization.GetByLabel('UI/Menusvc/PasswordRequired')
   3184                         label = localization.GetByLabel('UI/Menusvc/PleaseEnterPassword')
   3185                     passw = utilWindows.NamePopup(caption=caption, label=label, setvalue='', maxLength=50, passwordChar='*')
   3186                     if passw:
   3187                         self.Scoop(objectID, typeID, password=passw)
   3188                 else:
   3189                     raise
   3190                 sys.exc_clear()
   3191 
   3192     def ScoopToFleetHangar(self, objectID, typeID):
   3193         self.GetCloseAndTryCommand(objectID, self.RealScoopToFleetHangar, (objectID, typeID))
   3194 
   3195     def RealScoopToFleetHangar(self, objectID, typeID):
   3196         ship = sm.GetService('gameui').GetShipAccess()
   3197         if ship:
   3198             if not self.CheckIllegalOkay(objectID, typeID):
   3199                 return
   3200             if not self.crimewatchSvc.IsOkToScoopItem(objectID):
   3201                 self.crimewatchSvc.SafetyActivated(const.shipSafetyLevelPartial)
   3202                 return
   3203             if evetypes.GetCategoryID(typeID) == const.categoryFighter:
   3204                 self.ScoopAbandonedFighterFromSpace(objectID, const.flagFleetHangar)
   3205             else:
   3206                 ship.ScoopToFleetHangar(objectID)
   3207 
   3208     def ScoopToFighterBay(self, objectID, typeID):
   3209         self.GetCloseAndTryCommand(objectID, self.RealScoopToFighterBay, (objectID, typeID))
   3210 
   3211     def RealScoopToFighterBay(self, objectID, typeID):
   3212         ship = sm.GetService('gameui').GetShipAccess()
   3213         if ship:
   3214             if not self.CheckIllegalOkay(objectID, typeID):
   3215                 return
   3216             self.ScoopAbandonedFighterFromSpace(objectID, const.flagFighterBay)
   3217 
   3218     def ScoopToInfrastructureHold(self, objectID, typeID):
   3219         ship = sm.GetService('gameui').GetShipAccess()
   3220         if ship:
   3221             ship.ScoopToInfrastructureHold(objectID)
   3222 
   3223     def ScoopToMobileDepotHold(self, objectID):
   3224         ship = sm.GetService('gameui').GetShipAccess()
   3225         if ship:
   3226             ship.ScoopToMobileDepotHold(objectID)
   3227 
   3228     def CheckIllegalOkay(self, objectID, typeID):
   3229         toFactionID = sm.StartService('faction').GetFactionOfSolarSystem(session.solarsystemid)
   3230         stuff = self.GetIllegality(objectID, typeID)
   3231         if stuff and toFactionID and prompt_player_fsd_dialog('ConfirmScoopWithIllicitGoods', {'faction': cfg.eveowners.Get(toFactionID).name}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES:
   3232             return False
   3233         return True
   3234 
   3235     def ScoopSMA(self, objectID):
   3236         self.GetCloseAndTryCommand(objectID, self.RealScoopSMA, (objectID,))
   3237 
   3238     @staticmethod
   3239     def RealScoopSMA(objectID):
   3240         ship = sm.StartService('gameui').GetShipAccess()
   3241         if ship:
   3242             ship.ScoopToSMA(objectID)
   3243 
   3244     def ScoopAbandonedFighterFromSpace(self, fighterID, toFlagID):
   3245         self.fighters.ScoopAbandonedFighterFromSpace(fighterID, toFlagID)
   3246 
   3247     @staticmethod
   3248     def QuickBuy(typeID, quantity = 1):
   3249         sm.StartService('marketutils').Buy(typeID, quantity=quantity)
   3250 
   3251     @staticmethod
   3252     def SellItems(invItems):
   3253         return marketMenu.SellItems(invItems)
   3254 
   3255     @staticmethod
   3256     def SellPlex():
   3257         from eve.client.script.ui.shared.inventory.plexVault import PlexVaultController
   3258         controller = PlexVaultController()
   3259         controller.SellPlex()
   3260 
   3261     @staticmethod
   3262     def QuickContract(invItems, *args):
   3263         sm.GetService('contracts').OpenCreateContract(items=invItems)
   3264 
   3265     @staticmethod
   3266     def ShowMarketDetails(invItem = None, typeID = None):
   3267         uthread.new(sm.StartService('marketutils').ShowMarketDetails, typeID or invItem.typeID, None)
   3268 
   3269     def _AddMarketDetailsOption(self, menuEntries, typeID):
   3270         menuEntries.append(MenuEntryData(MenuLabel('UI/Inventory/ItemActions/ViewTypesMarketDetails'), lambda : self.ShowMarketDetails(typeID=typeID), internalName='ViewMarketDetails', typeID=typeID))
   3271 
   3272     def GetContainerContents(self, invItem, dockableID):
   3273         return invItemFunctions.GetContainerContents(invItem, self.invCache, dockableID)
   3274 
   3275     @staticmethod
   3276     def AddToQuickBar(typeID, parent = 0):
   3277         return menuFunctions.AddToQuickBar(typeID, parent)
   3278 
   3279     @staticmethod
   3280     def RemoveFromQuickBar(node):
   3281         return menuFunctions.RemoveFromQuickBar(node)
   3282 
   3283     @staticmethod
   3284     def ActivateShip(invItem):
   3285         if invItem.singleton and not uicore.uilib.Key(uiconst.VK_CONTROL):
   3286             sm.StartService('station').TryActivateShip(invItem)
   3287 
   3288     @staticmethod
   3289     def LeaveShip(invItem):
   3290         if invItem.singleton and not uicore.uilib.Key(uiconst.VK_CONTROL):
   3291             sm.StartService('station').TryLeaveShip(invItem)
   3292 
   3293     def StripFitting(self, invItem):
   3294         if prompt_player_fsd_dialog('AskStripShip', None, uiconst.YESNO, suppress=uiconst.ID_YES) == uiconst.ID_YES:
   3295             shipID = invItem.itemID
   3296             self.invCache.StripFitting(shipID)
   3297 
   3298     @staticmethod
   3299     def ExitDockableLocation(*args, **kwargs):
   3300         uicore.cmd.GetCommandAndExecute('CmdExitStation')
   3301 
   3302     def CompressItemInSpace(self, compressibleItem, compressionFacilityBallID):
   3303         return CompressItemInSpace(compressibleItem, compressionFacilityBallID)
   3304 
   3305     def CompressItemInStructure(self, compressibleItem):
   3306         return CompressItemInStructure(compressibleItem)
   3307 
   3308     def DecompressGasInStructure(self, compressedGasItem):
   3309         return decompress_gas(compressedGasItem.itemID)
   3310 
   3311     @staticmethod
   3312     def RepackageItems(invItems):
   3313         invItemFunctions.RepackageItems(invItems)
   3314 
   3315     def Break(self, invItems):
   3316         return invItemFunctions.Break(invItems, self.invCache)
   3317 
   3318     @staticmethod
   3319     def DeliverCourierContract(invItem):
   3320         sm.GetService('contracts').DeliverCourierContractFromItemID(invItem.itemID)
   3321 
   3322     @staticmethod
   3323     def FindCourierContract(invItem):
   3324         sm.GetService('contracts').FindCourierContractFromItemID(invItem.itemID)
   3325 
   3326     @staticmethod
   3327     def LaunchDrones(invItems, *args):
   3328         sm.GetService('godma').GetStateManager().SendDroneSettings()
   3329         eveMisc.LaunchFromShip(invItems)
   3330 
   3331     @staticmethod
   3332     def DeployStructure(invItems):
   3333         sm.GetService('structureDeployment').Deploy(invItems[0])
   3334 
   3335     @staticmethod
   3336     def LaunchForSelf(invItems):
   3337         eveMisc.LaunchFromShip(invItems, session.charid, maxQty=1)
   3338 
   3339     @staticmethod
   3340     def LaunchForCorp(invItems, ignoreWarning = False):
   3341         makesCorpWarDeccable = False
   3342         for eachItem in invItems:
   3343             if eachItem.categoryID in (const.categoryOrbital, const.categoryStructure) or eachItem.groupID == const.groupControlTower:
   3344                 makesCorpWarDeccable = True
   3345                 break
   3346 
   3347         if makesCorpWarDeccable and sm.GetService('warPermit').DoesMyCorpHaveNegativeWarPermit():
   3348             if prompt_player_fsd_dialog('ConfirmDeployFirstStructureMakeWarDeccable', {}, uiconst.YESNO) != uiconst.ID_YES:
   3349                 return
   3350         eveMisc.LaunchFromShip(invItems, session.corpid, ignoreWarning, maxQty=1)
   3351 
   3352     @staticmethod
   3353     def LaunchSMAContents(invItems):
   3354         return invItemFunctions.LaunchSMAContents(invItems[0])
   3355 
   3356     @staticmethod
   3357     def LaunchShipFromWreck(invItems):
   3358         return invItemFunctions.LaunchShipOrContainerFromWreckOrContainer(invItems[0])
   3359 
   3360     @staticmethod
   3361     def LaunchContainerFromContainer(invItem):
   3362         return invItemFunctions.LaunchShipOrContainerFromWreckOrContainer(invItem)
   3363 
   3364     @staticmethod
   3365     def Jettison(invItems):
   3366         return invItemFunctions.Jettison(invItems)
   3367 
   3368     @staticmethod
   3369     def JettisonFuel(invItems):
   3370         return invItemFunctions.JettisonStructureFuel(invItems)
   3371 
   3372     def TrashInvItems(self, invItems):
   3373         return invItemFunctions.TrashInvItems(invItems, self.invCache)
   3374 
   3375     @staticmethod
   3376     def TrainNow(invItems):
   3377         return invItemFunctions.TrainNow(invItems)
   3378 
   3379     @staticmethod
   3380     def InjectSkillIntoBrain(invItems):
   3381         return invItemFunctions.InjectSkillIntoBrain(invItems)
   3382 
   3383     @staticmethod
   3384     def PlugInImplant(invItems):
   3385         return invItemFunctions.PlugInImplant(invItems)
   3386 
   3387     @staticmethod
   3388     def RedeemCurrency(item, qty):
   3389         return menuFunctions.RedeemCurrency(item, qty)
   3390 
   3391     @staticmethod
   3392     def ActivateCharacterReSculpt(itemID):
   3393         return menuFunctions.ActivateCharacterReSculpt(itemID)
   3394 
   3395     @staticmethod
   3396     def ActivateMultiTraining(itemID):
   3397         return ActivateMultiTraining(itemID=itemID)
   3398 
   3399     @staticmethod
   3400     def ActivateSkillExtractor(item):
   3401         return menuFunctions.ActivateSkillExtractor(item)
   3402 
   3403     @staticmethod
   3404     def ActivateSkillInjector(item, quantity):
   3405         return menuFunctions.ActivateSkillInjector(item, quantity)
   3406 
   3407     def GetActivateSkillInjectorMenuEntry(self, invItem):
   3408         if invItem.typeID == invconst.typeAlphaTrainingInjector:
   3409             quantity = 1
   3410         else:
   3411             quantity = invItem.stacksize
   3412         menuLabel = MenuLabel('UI/Commands/ActivateSkillInjector', {'injector': invItem.typeID,
   3413          'quantity': quantity})
   3414         return [[menuLabel, self.ActivateSkillInjector, (invItem, quantity)]]
   3415 
   3416     @staticmethod
   3417     def OpenCrate(typeID, itemID, stacksize):
   3418         return menuFunctions.OpenCrate(typeID, itemID, stacksize)
   3419 
   3420     @staticmethod
   3421     def CraftDynamicItem(item):
   3422         return menuFunctions.CraftDynamicItem(item)
   3423 
   3424     @staticmethod
   3425     def ActivateAbyssalKey(item):
   3426         return menuFunctions.ActivateAbyssalKey(item)
   3427 
   3428     @staticmethod
   3429     def ActivateWarpVector(item):
   3430         return menuFunctions.ActivateWarpVector(item)
   3431 
   3432     @staticmethod
   3433     def ActivateVoidSpaceKey(item):
   3434         return menuFunctions.ActivateVoidSpaceKey(item)
   3435 
   3436     @staticmethod
   3437     def ActivateRandomJumpKey(item):
   3438         return menuFunctions.ActivateRandomJumpKey(item)
   3439 
   3440     @staticmethod
   3441     def ActivatePVPfilamentKey(item):
   3442         return menuFunctions.ActivatePVPfilamentKey(item)
   3443 
   3444     @staticmethod
   3445     def ConsumeBooster(invItems):
   3446         return invItemFunctions.ConsumeBooster(invItems)
   3447 
   3448     @staticmethod
   3449     def ConsumeExpertSystem(invItem):
   3450         return invItemFunctions.ConsumeExpertSystem(invItem)
   3451 
   3452     def DeliverToStructure(self, invItems):
   3453         return invItemFunctions.DeliverToStructure(invItems, self.invCache)
   3454 
   3455     def AssembleContainer(self, invItems):
   3456         invMgr = self.invCache.GetInventoryMgr()
   3457         for invItem in invItems:
   3458             invMgr.AssembleCargoContainer(invItem.itemID, None, 0.0)
   3459 
   3460     @staticmethod
   3461     def ShowInIndustryWindow(invItem):
   3462         Industry.OpenOrShowBlueprint(blueprintID=invItem.itemID)
   3463 
   3464     @staticmethod
   3465     def SetHomeStation(stationID):
   3466         homestation.set_home_station(stationID)
   3467 
   3468     @staticmethod
   3469     @ThrottlePerSecond()
   3470     def AssembleShip(invItems):
   3471         return invItemFunctions.AssembleShip(invItems)
   3472 
   3473     @staticmethod
   3474     @ThrottlePerSecond()
   3475     def AssembleAndBoardShip(invItem):
   3476         invItemFunctions.AssembleAndBoardShip(invItem)
   3477 
   3478     @staticmethod
   3479     def HandleMultipleCallError(droneID, ret, messageName):
   3480         return droneFunctions.HandleMultipleCallError(droneID, ret, messageName)
   3481 
   3482     @staticmethod
   3483     def EngageTarget(droneIDs):
   3484         return droneFunctions.EngageTarget(droneIDs)
   3485 
   3486     @staticmethod
   3487     def Assist(charID, droneIDs):
   3488         return droneFunctions.Assist(charID, droneIDs)
   3489 
   3490     @staticmethod
   3491     def Guard(charID, droneIDs):
   3492         return droneFunctions.Guard(charID, droneIDs)
   3493 
   3494     @staticmethod
   3495     def MineRepeatedly(droneIDs):
   3496         return droneFunctions.MineRepeatedly(droneIDs)
   3497 
   3498     @staticmethod
   3499     def Salvage(droneIDs):
   3500         return droneFunctions.Salvage(droneIDs)
   3501 
   3502     @staticmethod
   3503     def DroneUnanchor(droneIDs):
   3504         return droneFunctions.DroneUnanchor(droneIDs)
   3505 
   3506     @staticmethod
   3507     def ReturnAndOrbit(droneIDs):
   3508         return droneFunctions.ReturnAndOrbit(droneIDs)
   3509 
   3510     @staticmethod
   3511     def ReturnToDroneBay(droneIDs):
   3512         return droneFunctions.ReturnToDroneBay(droneIDs)
   3513 
   3514     def ScoopToDroneBay(self, objectIDs):
   3515         if len(objectIDs) == 1:
   3516             self.GetCloseAndTryCommand(objectIDs[0], self.RealScoopToDroneBay, (objectIDs,))
   3517         else:
   3518             self.RealScoopToDroneBay(objectIDs)
   3519 
   3520     @staticmethod
   3521     def RealScoopToDroneBay(objectIDs):
   3522         return droneFunctions.RealScoopToDroneBay(objectIDs)
   3523 
   3524     def FitDrone(self, invItems):
   3525         return droneFunctions.FitDrone(invItems, self.invCache)
   3526 
   3527     @staticmethod
   3528     def AbandonDrone(droneIDs):
   3529         return droneFunctions.AbandonDrone(droneIDs)
   3530 
   3531     @staticmethod
   3532     def CopyItemIDAndMaybeQuantityToClipboard(invItem):
   3533         return menuFunctions.CopyItemIDAndMaybeQuantityToClipboard(invItem)
   3534 
   3535     def SetName(self, invOrSlimItem):
   3536         return menuFunctions.SetName(invOrSlimItem, self.invCache)
   3537 
   3538     def AskNewContainerPwd(self, invItems, desc, which = 1):
   3539         for invItem in invItems:
   3540             self.AskNewContainerPassword(invItem.itemID, desc, which)
   3541 
   3542     @staticmethod
   3543     def GetDefaultActionDistance(key):
   3544         return defaultRangeUtils.FetchRangeSetting(key)
   3545 
   3546     def CopyCoordinates(self, itemID):
   3547         ball = self.michelle.GetBall(itemID)
   3548         if ball:
   3549             blue.pyos.SetClipboardData(str((ball.x, ball.y, ball.z)))
   3550 
   3551     @staticmethod
   3552     def AnchorOrbital(itemID):
   3553         posMgr = Moniker('posMgr', session.solarsystemid)
   3554         posMgr.AnchorOrbital(itemID)
   3555 
   3556     @staticmethod
   3557     def UnanchorOrbital(itemID):
   3558         posMgr = Moniker('posMgr', session.solarsystemid)
   3559         posMgr.UnanchorOrbital(itemID)
   3560 
   3561     @staticmethod
   3562     def ConfigureOrbital(item):
   3563         sm.GetService('planetUI').OpenConfigureWindow(item)
   3564 
   3565     @staticmethod
   3566     def ConfigureIndustryTax(itemID, typeID):
   3567         facilityName = cfg.evelocations.Get(itemID).name
   3568         if not facilityName:
   3569             facilityName = evetypes.GetName(typeID)
   3570         FacilityTaxWindow.Open(facilityID=itemID, facilityName=facilityName)
   3571 
   3572     @staticmethod
   3573     def IsTooFarToExecuteCommand(itemID, interactionRange = DEFAULT_INTERACTION_RANGE):
   3574         if not sm.GetService('autoPilot').IsSystemNavigationComplete(itemID, interactionRange):
   3575             return True
   3576 
   3577     @staticmethod
   3578     def GetCloseAndTryCommand(itemID, cmdMethod, args, interactionRange = DEFAULT_INTERACTION_RANGE):
   3579         sm.GetService('autoPilot').NavigateSystemTo(itemID, interactionRange, cmdMethod, *args)
   3580 
   3581     @staticmethod
   3582     def ReconnectToDrones():
   3583         return droneFunctions.ReconnectToDrones()
   3584 
   3585     @staticmethod
   3586     def SetDefaultDist(key):
   3587         return movementFunctions.SetDefaultDist(key)
   3588 
   3589     @staticmethod
   3590     def AddDisabledEntryForWarp(menuEntries, textPath):
   3591         menuEntries.append(MenuEntryData(MenuLabel(textPath), isEnabled=False, hint=localization.GetByLabel('UI/Menusvc/MenuHints/YouAreInWarp')))
   3592         menuEntries.reasonsWhyNotAvailable[textPath] = localization.GetByLabel('UI/Menusvc/MenuHints/YouAreInWarp')
   3593 
   3594     @staticmethod
   3595     def DoBoardingMoment():
   3596         currentView = sm.GetService('viewState').GetCurrentView()
   3597         if currentView is None or currentView.name != 'hangar':
   3598             return
   3599         currentView.play_boarding_moment()
   3600 
   3601     def GetAbyssalGateFunction(self, typeID):
   3602         if typeID == const.typeAbyssEncounterGate:
   3603             return self.ActivateAbyssalAccelerationGate
   3604         if typeID == const.typeAbyssEntranceGate:
   3605             return self.ActivateAbyssalEntranceAccelerationGate
   3606         if typeID == const.typeAbyssExitGate:
   3607             return self.ActivateAbyssalEndGate
   3608         if typeID == const.typeAbyssPvPGate:
   3609             return self.ActivatePVPAbyssalEndGate
   3610         if typeID == const.typeVoidSpaceExitGate:
   3611             return self.ActivateVoidSpaceExitGate