226 lines
8.4 KiB
Python
226 lines
8.4 KiB
Python
import re
|
|
from collections import OrderedDict
|
|
from itertools import chain
|
|
|
|
# noinspection PyPackageRequirements
|
|
import wx
|
|
|
|
import gui.fitCommands as cmd
|
|
import gui.mainFrame
|
|
from gui.contextMenu import ContextMenuUnconditional
|
|
from service.market import Market
|
|
|
|
_t = wx.GetTranslation
|
|
|
|
|
|
class Group:
|
|
|
|
def __init__(self):
|
|
self.groups = OrderedDict()
|
|
self.items = []
|
|
|
|
def sort(self):
|
|
self.groups = OrderedDict((k, self.groups[k]) for k in sorted(self.groups))
|
|
for group in self.groups.values():
|
|
group.sort()
|
|
self.items.sort(key=lambda e: e.shortName)
|
|
|
|
|
|
class Entry:
|
|
|
|
def __init__(self, itemID, name, shortName):
|
|
self.itemID = itemID
|
|
self.name = name
|
|
self.shortName = shortName
|
|
|
|
|
|
class AddEnvironmentEffect(ContextMenuUnconditional):
|
|
# CCP doesn't currently provide a mapping between the general Environment, and the specific environment effect
|
|
# (which can be random when going into Abyssal space). This is how we currently define it:
|
|
# environment type: specific type name prefix
|
|
abyssal_mapping = {
|
|
'caustic_toxin_weather': 47862, # Exotic Particle Storm
|
|
'darkness_weather': 47863, # Dark Matter Field
|
|
'infernal_weather': 47864, # Plasma Firestorm
|
|
'electric_storm_weather': 47865, # Electrical Storm
|
|
'xenon_gas_weather': 47866, # Gamma-Ray Afterglow
|
|
}
|
|
|
|
def __init__(self):
|
|
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
|
|
|
def display(self, callingWindow, srcContext):
|
|
return srcContext == "projected"
|
|
|
|
def getText(self, callingWindow, itmContext):
|
|
return _t("Add Environmental Effect")
|
|
|
|
def _addGroup(self, parentMenu, name):
|
|
id = ContextMenuUnconditional.nextID()
|
|
menuItem = wx.MenuItem(parentMenu, id, name)
|
|
parentMenu.Bind(wx.EVT_MENU, self.handleSelection, menuItem)
|
|
return menuItem
|
|
|
|
def _addEffect(self, parentMenu, typeID, name):
|
|
id = ContextMenuUnconditional.nextID()
|
|
self.idmap[id] = typeID
|
|
menuItem = wx.MenuItem(parentMenu, id, name)
|
|
parentMenu.Bind(wx.EVT_MENU, self.handleSelection, menuItem)
|
|
return menuItem
|
|
|
|
def getSubMenu(self, callingWindow, context, rootMenu, i, pitem):
|
|
self.idmap = {}
|
|
data = self.getData()
|
|
msw = "wxMSW" in wx.PlatformInfo
|
|
|
|
def makeMenu(data, parentMenu):
|
|
menu = wx.Menu()
|
|
for group_name in data.groups:
|
|
menuItem = self._addGroup(rootMenu if msw else parentMenu, group_name)
|
|
subMenu = makeMenu(data.groups[group_name], menu)
|
|
menuItem.SetSubMenu(subMenu)
|
|
menu.Append(menuItem)
|
|
for entry in data.items:
|
|
menuItem = self._addEffect(rootMenu if msw else parentMenu, entry.itemID, entry.shortName)
|
|
menu.Append(menuItem)
|
|
menu.Bind(wx.EVT_MENU, self.handleSelection)
|
|
return menu
|
|
|
|
sub = makeMenu(data, rootMenu)
|
|
return sub
|
|
|
|
def handleSelection(self, event):
|
|
# Skip events ids that aren't mapped
|
|
|
|
swObj = self.idmap.get(event.Id, False)
|
|
if not swObj:
|
|
event.Skip()
|
|
return
|
|
|
|
fitID = self.mainFrame.getActiveFit()
|
|
self.mainFrame.command.Submit(cmd.GuiAddProjectedModuleCommand(fitID, swObj))
|
|
|
|
def getData(self):
|
|
data = Group()
|
|
data.groups[_t('Wormhole')] = self.getEffectBeacons(
|
|
_t('ContextMenu|ProjectedEffectManipulation|Black Hole'),
|
|
_t('ContextMenu|ProjectedEffectManipulation|Cataclysmic Variable'),
|
|
_t('ContextMenu|ProjectedEffectManipulation|Magnetar'),
|
|
_t('ContextMenu|ProjectedEffectManipulation|Pulsar'),
|
|
_t('ContextMenu|ProjectedEffectManipulation|Red Giant'),
|
|
_t('ContextMenu|ProjectedEffectManipulation|Wolf Rayet'))
|
|
data.groups[_t('Sansha Incursion')] = self.getEffectBeacons(
|
|
_t('ContextMenu|ProjectedEffectManipulation|Sansha Incursion')
|
|
)
|
|
data.groups[_t('Triglavian Invasion')] = self.getEffectBeacons(
|
|
_t('ContextMenu|ProjectedEffectManipulation|Triglavian Invasion')
|
|
)
|
|
data.groups[_t('Triglavian Invasion')].groups[_t('Destructible Beacons')] = self.getDestructibleBeacons()
|
|
data.groups[_t('Abyssal Weather')] = self.getAbyssalWeather()
|
|
return data
|
|
|
|
def getEffectBeacons(self, *groups):
|
|
"""
|
|
Get dictionary with wormhole system-wide effects
|
|
"""
|
|
compacted = len(groups) <= 1
|
|
sMkt = Market.getInstance()
|
|
|
|
# Container for system-wide effects
|
|
data = Group()
|
|
|
|
# Stuff we don't want to see in names
|
|
garbages = (_t("ContextMenu|ProjectedEffectManipulation|System Effects"), _t("ContextMenu|ProjectedEffectManipulation|Effects"))
|
|
|
|
# Get group with all the system-wide beacons
|
|
grp = sMkt.getGroup("Effect Beacon")
|
|
|
|
# Cycle through them
|
|
for beacon in sMkt.getItemsByGroup(grp):
|
|
# Check if it belongs to any valid group
|
|
for group in groups:
|
|
# Check beginning of the name only
|
|
if re.search(group, beacon.name):
|
|
# Get full beacon name
|
|
beaconname = beacon.name
|
|
for garbage in garbages:
|
|
beaconname = re.sub(garbage, "", beaconname)
|
|
beaconname = re.sub(" {2,}", " ", beaconname).strip()
|
|
# Get short name
|
|
shortname = re.sub(group, "", beacon.name)
|
|
for garbage in garbages:
|
|
shortname = re.sub(garbage, "", shortname)
|
|
shortname = re.sub(" {2,}", " ", shortname).strip()
|
|
# Get group name
|
|
groupname = group
|
|
for garbage in garbages:
|
|
groupname = re.sub(garbage, "", groupname)
|
|
groupname = re.sub(" {2,}", " ", groupname).strip()
|
|
# Add stuff to dictionary
|
|
if compacted:
|
|
container = data.items
|
|
else:
|
|
container = data.groups.setdefault(groupname, Group()).items
|
|
container.append(Entry(beacon.ID, beaconname, shortname))
|
|
# Break loop on 1st result
|
|
break
|
|
data.sort()
|
|
return data
|
|
|
|
def getAbyssalWeather(self):
|
|
sMkt = Market.getInstance()
|
|
data = Group()
|
|
|
|
environments = {x.ID: x for x in sMkt.getGroup("Abyssal Environment").items}
|
|
items = chain(
|
|
sMkt.getGroup("MassiveEnvironments").items,
|
|
sMkt.getGroup("Non-Interactable Object").items)
|
|
for beacon in items:
|
|
if not beacon.isType('projected'):
|
|
continue
|
|
type = self.__class__.abyssal_mapping.get(beacon.name[0:-2], None)
|
|
type = environments.get(type, None)
|
|
if type is None:
|
|
continue
|
|
subdata = data.groups.setdefault(type.name, Group())
|
|
display_name = "{} {}".format(type.name, beacon.name[-1:])
|
|
subdata.items.append(Entry(beacon.ID, display_name, display_name))
|
|
data.sort()
|
|
|
|
# Localized abyssal hazards
|
|
items = sMkt.getGroup("Abyssal Hazards").items
|
|
if items:
|
|
subdata = data.groups.setdefault(_t('Localized'), Group())
|
|
for beacon in sMkt.getGroup("Abyssal Hazards").items:
|
|
if not beacon.isType('projected'):
|
|
continue
|
|
groups = (_t('Bioluminescence'), _t('Caustic'), _t('Filament'))
|
|
for group in groups:
|
|
if re.search(group, beacon.name):
|
|
key = group
|
|
break
|
|
else:
|
|
continue
|
|
|
|
subsubdata = subdata.groups.setdefault(key, Group())
|
|
subsubdata.items.append(Entry(beacon.ID, beacon.name, beacon.name))
|
|
subdata.sort()
|
|
|
|
# PVP weather
|
|
data.items.append(Entry(49766, _t('PvP Weather'), _t('PvP Weather')))
|
|
|
|
return data
|
|
|
|
def getDestructibleBeacons(self):
|
|
data = Group()
|
|
sMkt = Market.getInstance()
|
|
for item in sMkt.getItemsByGroup(sMkt.getGroup('Destructible Effect Beacon')):
|
|
if not item.isType('projected'):
|
|
continue
|
|
data.items.append(Entry(item.ID, item.name, item.name))
|
|
data.sort()
|
|
return data
|
|
|
|
|
|
AddEnvironmentEffect.register()
|