diff --git a/eos/effects/aoebeaconbioluminescencecloud.py b/eos/effects/aoebeaconbioluminescencecloud.py new file mode 100644 index 000000000..6856fc272 --- /dev/null +++ b/eos/effects/aoebeaconbioluminescencecloud.py @@ -0,0 +1,12 @@ +runTime = "early" +type = ("projected", "passive", "gang") + + +def handler(fit, beacon, context, **kwargs): + for x in range(1, 3): + if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)): + value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x)) + id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)) + + if id: + fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early') diff --git a/eos/effects/aoebeaconcausticcloud.py b/eos/effects/aoebeaconcausticcloud.py new file mode 100644 index 000000000..6856fc272 --- /dev/null +++ b/eos/effects/aoebeaconcausticcloud.py @@ -0,0 +1,12 @@ +runTime = "early" +type = ("projected", "passive", "gang") + + +def handler(fit, beacon, context, **kwargs): + for x in range(1, 3): + if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)): + value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x)) + id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)) + + if id: + fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early') diff --git a/eos/effects/aoebeaconfilamentcloud.py b/eos/effects/aoebeaconfilamentcloud.py new file mode 100644 index 000000000..6856fc272 --- /dev/null +++ b/eos/effects/aoebeaconfilamentcloud.py @@ -0,0 +1,12 @@ +runTime = "early" +type = ("projected", "passive", "gang") + + +def handler(fit, beacon, context, **kwargs): + for x in range(1, 3): + if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)): + value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x)) + id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)) + + if id: + fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early') diff --git a/eos/effects/weatherbasic.py b/eos/effects/weatherbasic.py new file mode 100644 index 000000000..726601d67 --- /dev/null +++ b/eos/effects/weatherbasic.py @@ -0,0 +1,6 @@ +runTime = "early" +type = ("projected", "passive") + + +def handler(fit, beacon, context): + pass diff --git a/eos/effects/weathercaustictoxin.py b/eos/effects/weathercaustictoxin.py new file mode 100644 index 000000000..6856fc272 --- /dev/null +++ b/eos/effects/weathercaustictoxin.py @@ -0,0 +1,12 @@ +runTime = "early" +type = ("projected", "passive", "gang") + + +def handler(fit, beacon, context, **kwargs): + for x in range(1, 3): + if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)): + value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x)) + id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)) + + if id: + fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early') diff --git a/eos/effects/weatherdarkness.py b/eos/effects/weatherdarkness.py new file mode 100644 index 000000000..6856fc272 --- /dev/null +++ b/eos/effects/weatherdarkness.py @@ -0,0 +1,12 @@ +runTime = "early" +type = ("projected", "passive", "gang") + + +def handler(fit, beacon, context, **kwargs): + for x in range(1, 3): + if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)): + value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x)) + id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)) + + if id: + fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early') diff --git a/eos/effects/weatherelectricstorm.py b/eos/effects/weatherelectricstorm.py new file mode 100644 index 000000000..6856fc272 --- /dev/null +++ b/eos/effects/weatherelectricstorm.py @@ -0,0 +1,12 @@ +runTime = "early" +type = ("projected", "passive", "gang") + + +def handler(fit, beacon, context, **kwargs): + for x in range(1, 3): + if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)): + value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x)) + id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)) + + if id: + fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early') diff --git a/eos/effects/weatherinfernal.py b/eos/effects/weatherinfernal.py new file mode 100644 index 000000000..6856fc272 --- /dev/null +++ b/eos/effects/weatherinfernal.py @@ -0,0 +1,12 @@ +runTime = "early" +type = ("projected", "passive", "gang") + + +def handler(fit, beacon, context, **kwargs): + for x in range(1, 3): + if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)): + value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x)) + id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)) + + if id: + fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early') diff --git a/eos/effects/weatherxenongas.py b/eos/effects/weatherxenongas.py new file mode 100644 index 000000000..6856fc272 --- /dev/null +++ b/eos/effects/weatherxenongas.py @@ -0,0 +1,12 @@ +runTime = "early" +type = ("projected", "passive", "gang") + + +def handler(fit, beacon, context, **kwargs): + for x in range(1, 3): + if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)): + value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x)) + id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)) + + if id: + fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early') diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index cb5bedcf9..e768bf216 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -672,6 +672,72 @@ class Fit(object): groups = ("Energy Weapon", "Hybrid Weapon") self.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups, "maxRange", value, stackingPenalties=True) + # Localized environment effects + + if warfareBuffID == 79: # AOE_Beacon_bioluminescence_cloud + self.ship.boostItemAttr("signatureRadius", value, stackingPenalties=True) + + if warfareBuffID == 80: # AOE_Beacon_caustic_cloud_local_repair + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"), + "armorDamageAmount", value, stackingPenalties=True) + + if warfareBuffID == 81: # AOE_Beacon_caustic_cloud_remote_repair + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "armorDamageAmount", value, stackingPenalties=True) + + if warfareBuffID == 88: # AOE_Beacon_filament_cloud_shield_booster + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Operation") or + mod.item.requiresSkill("Shield Emission Systems"), + "capacitorNeed", value, stackingPenalties=True) + + if warfareBuffID == 89: # AOE_Beacon_filament_cloud_ancillary_charge_usage + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Operation") or + mod.item.requiresSkill("Shield Emission Systems"), + "chargeRate", value, stackingPenalties=True) + + # Abysmal Weather Effects + + if warfareBuffID == 90: # Weather_electric_storm_EM_resistance_penalty + for tankType in ("shield", "armor"): + self.ship.boostItemAttr("{}EmDamageResonance".format(tankType), value) + self.ship.boostItemAttr("emDamageResonance", value) # for hull + + if warfareBuffID == 92: # Weather_electric_storm_capacitor_recharge_bonus + self.ship.boostItemAttr("rechargeRate", value, stackingPenalties=True) + + if warfareBuffID == 93: # Weather_xenon_gas_explosive_resistance_penalty + for tankType in ("shield", "armor"): + self.ship.boostItemAttr("{}ExplosiveDamageResonance".format(tankType), value) + self.ship.boostItemAttr("explosiveDamageResonance", value) # for hull + + if warfareBuffID == 94: # Weather_xenon_gas_shield_hp_bonus + self.ship.boostItemAttr("shieldCapacity", value) # for hull + + if warfareBuffID == 95: # Weather_infernal_thermal_resistance_penalty + for tankType in ("shield", "armor"): + self.ship.boostItemAttr("{}ThermalDamageResonance".format(tankType), value) + self.ship.boostItemAttr("thermalDamageResonance", value) # for hull + + if warfareBuffID == 96: # Weather_infernal_armor_hp_bonus + self.ship.boostItemAttr("armorHP", value) # for hull + + if warfareBuffID == 97: # Weather_darkness_turret_range_penalty + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"), + "maxRange", value, stackingPenalties=True) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"), + "falloff", value, stackingPenalties=True) + + if warfareBuffID == 98: # Weather_darkness_velocity_bonus + self.ship.boostItemAttr("maxVelocity", value) + + if warfareBuffID == 99: # Weather_caustic_toxin_kinetic_resistance_penalty + for tankType in ("shield", "armor"): + self.ship.boostItemAttr("{}KineticDamageResonance".format(tankType), value) + self.ship.boostItemAttr("kineticDamageResonance", value) # for hull + + if warfareBuffID == 100: # Weather_caustic_toxin_scan_resolution_bonus + self.ship.boostItemAttr("scanResolution", value, stackingPenalties=True) + del self.commandBonuses[warfareBuffID] def __resetDependentCalcs(self): diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index cf669f273..41bed8c50 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -72,6 +72,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): """An instance of this class represents a module together with its charge and modified attributes""" DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive") MINING_ATTRIBUTES = ("miningAmount",) + SYSTEM_GROUPS = ("Effect Beacon", "MassiveEnvironments", "Uninteractable Localized Effect Beacon", "Non-Interactable Object") def __init__(self, item): """Initialize a module from the program""" @@ -165,7 +166,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): return False return self.__item is None or \ (self.__item.category.name not in ("Module", "Subsystem", "Structure Module") and - self.__item.group.name != "Effect Beacon") + self.__item.group.name not in self.SYSTEM_GROUPS) @property def numCharges(self): @@ -614,7 +615,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): for effectName, slot in effectSlotMap.items(): if effectName in item.effects: return slot - if item.group.name == "Effect Beacon": + if item.group.name in Module.SYSTEM_GROUPS: return Slot.SYSTEM raise ValueError("Passed item does not fit in any known slot") diff --git a/eve.db b/eve.db index f32c7e340..b2b896816 100644 Binary files a/eve.db and b/eve.db differ diff --git a/gui/builtinContextMenus/whProjector.py b/gui/builtinContextMenus/whProjector.py index bafca94ab..3d6783a00 100644 --- a/gui/builtinContextMenus/whProjector.py +++ b/gui/builtinContextMenus/whProjector.py @@ -6,9 +6,23 @@ import wx from service.market import Market from service.fit import Fit from service.settings import ContextMenuSettings +from itertools import chain +import re class WhProjector(ContextMenu): + + # 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 previx + 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() self.settings = ContextMenuSettings.getInstance() @@ -20,32 +34,50 @@ class WhProjector(ContextMenu): return srcContext == "projected" def getText(self, itmContext, selection): - return "Add System Effects" + return "Add Environmental Effect" def getSubMenu(self, context, selection, rootMenu, i, pitem): msw = True if "wxMSW" in wx.PlatformInfo else False sMkt = Market.getInstance() - effdata = sMkt.getSystemWideEffects() + + # Wormholes self.idmap = {} sub = wx.Menu() - for swType in sorted(effdata): - subItem = wx.MenuItem(sub, wx.ID_ANY, swType) - grandSub = wx.Menu() - subItem.SetSubMenu(grandSub) - sub.Append(subItem) + wormhole_item = wx.MenuItem(sub, wx.ID_ANY, "Wormhole") + wormhole_menu = wx.Menu() + wormhole_item.SetSubMenu(wormhole_menu) + sub.Append(wormhole_item) + + effdata = self.getEffectBeacons() + self.buildMenu(effdata, wormhole_menu, rootMenu, msw) + + # Incursions + + effdata = self.getEffectBeacons(incursions=True) + self.buildMenu(effdata, sub, rootMenu, msw) + + # Abyssal Weather + + abyssal_item = wx.MenuItem(sub, wx.ID_ANY, "Abyssal Weather") + abyssal_menu = wx.Menu() + abyssal_item.SetSubMenu(abyssal_menu) + sub.Append(abyssal_item) + + effdata = self.getAbyssalWeather() + self.buildMenu(effdata, abyssal_menu, rootMenu, msw) + + # Localized Weather + + local_item = wx.MenuItem(sub, wx.ID_ANY, "Localized") + local_menu = wx.Menu() + local_item.SetSubMenu(local_menu) + sub.Append(local_item) + + effdata = self.getLocalizedEnvironments() + self.buildMenu(effdata, local_menu, rootMenu, msw) - for swData in sorted(effdata[swType], key=lambda tpl: tpl[2]): - wxid = ContextMenu.nextID() - swObj, swName, swClass = swData - self.idmap[wxid] = (swObj, swName) - grandSubItem = wx.MenuItem(grandSub, wxid, swClass) - if msw: - rootMenu.Bind(wx.EVT_MENU, self.handleSelection, grandSubItem) - else: - grandSub.Bind(wx.EVT_MENU, self.handleSelection, grandSubItem) - grandSub.Append(grandSubItem) return sub def handleSelection(self, event): @@ -61,5 +93,127 @@ class WhProjector(ContextMenu): sFit.project(fitID, swObj) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + def buildMenu(self, data, local_menu, rootMenu, msw): + for swType in sorted(data): + subItem = wx.MenuItem(local_menu, wx.ID_ANY, swType) + grandSub = wx.Menu() + subItem.SetSubMenu(grandSub) + local_menu.Append(subItem) + + for swData in sorted(data[swType], key=lambda tpl: tpl[2]): + wxid = ContextMenu.nextID() + swObj, swName, swClass = swData + self.idmap[wxid] = (swObj, swName) + grandSubItem = wx.MenuItem(grandSub, wxid, swClass) + if msw: + rootMenu.Bind(wx.EVT_MENU, self.handleSelection, grandSubItem) + else: + grandSub.Bind(wx.EVT_MENU, self.handleSelection, grandSubItem) + grandSub.Append(grandSubItem) + + def getEffectBeacons(self, incursions=False): + """ + Get dictionary with system-wide effects + """ + sMkt = Market.getInstance() + + # todo: rework this + # Container for system-wide effects + effects = {} + + # Expressions for matching when detecting effects we're looking for + if incursions: + validgroups = ("Incursion ship attributes effects",) + else: + validgroups = ("Black Hole Effect Beacon", + "Cataclysmic Variable Effect Beacon", + "Magnetar Effect Beacon", + "Pulsar Effect Beacon", + "Red Giant Beacon", + "Wolf Rayet Effect Beacon") + + # Stuff we don't want to see in names + garbages = ("Effect", "Beacon", "ship attributes 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 validgroups: + # Check beginning of the name only + if re.match(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 groupname not in effects: + effects[groupname] = set() + effects[groupname].add((beacon, beaconname, shortname)) + # Break loop on 1st result + break + + return effects + + def getAbyssalWeather(self): + sMkt = Market.getInstance() + + environments = {x.ID: x for x in sMkt.getGroup("Abyssal Environment").items} + items = chain(sMkt.getGroup("MassiveEnvironments").items, sMkt.getGroup("Non-Interactable Object").items) + + effects = {} + + 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 + + if type.name not in effects: + effects[type.name] = set() + + display_name = "{} {}".format(type.name, beacon.name[-1:]) + effects[type.name].add((beacon, display_name, display_name)) + + return effects + + def getLocalizedEnvironments(self): + sMkt = Market.getInstance() + + grp = sMkt.getGroup("Uninteractable Localized Effect Beacon") + + effects = dict() + + for beacon in grp.items: + if not beacon.isType('projected'): + continue + # Localized effects, currently, have a name like "(size) (type) Cloud" + # Until this inevitably changes, do a simple split + name_parts = beacon.name.split(" ") + + key = name_parts[1].strip() + if key not in effects: + effects[key] = set() + + effects[key].add((beacon, beacon.name, beacon.name)) + + return effects + WhProjector.register() diff --git a/gui/builtinItemStatsViews/itemEffects.py b/gui/builtinItemStatsViews/itemEffects.py index e586786a6..37b37c608 100644 --- a/gui/builtinItemStatsViews/itemEffects.py +++ b/gui/builtinItemStatsViews/itemEffects.py @@ -45,7 +45,7 @@ class ItemEffects(wx.Panel): self.effectList.SetColumnWidth(4, 40) item = self.item - effects = item.effects + self.effects = effects = item.effects names = list(effects.keys()) names.sort() @@ -100,14 +100,15 @@ class ItemEffects(wx.Panel): self.RefreshValues(event) - @staticmethod - def OnRightClick(event): + def OnRightClick(self, event): """ Debug use: open effect file with default application. If effect file does not exist, create it """ - file_ = os.path.join(config.pyfaPath, "eos", "effects", "%s.py" % event.GetText().lower()) + effect = self.effects[event.GetText()] + + file_ = os.path.join(config.pyfaPath, "eos", "effects", "%s.py" % effect.handlerName) if not os.path.isfile(file_): open(file_, 'a').close() diff --git a/gui/builtinViewColumns/baseName.py b/gui/builtinViewColumns/baseName.py index 0628eb2ad..368dd74b6 100644 --- a/gui/builtinViewColumns/baseName.py +++ b/gui/builtinViewColumns/baseName.py @@ -28,7 +28,9 @@ from eos.saveddata.fighter import Fighter from eos.saveddata.module import Module, Slot, Rack from eos.saveddata.fit import Fit from service.fit import Fit as FitSvc +from service.market import Market from gui.viewColumn import ViewColumn +from gui.builtinContextMenus.whProjector import WhProjector import gui.mainFrame pyfalog = Logger(__name__) @@ -77,6 +79,15 @@ class BaseName(ViewColumn): else: return "" elif isinstance(stuff, Module): + if self.projectedView: + # check for projected abyssal name + name_check = stuff.item.name[0:-2] + type = WhProjector.abyssal_mapping.get(name_check, None) + if type: + sMkt = Market.getInstance() + type = sMkt.getItem(type) + return "{} {}".format(type.name, stuff.item.name[-1:]) + if stuff.isEmpty: return "%s Slot" % Slot.getName(stuff.slot).capitalize() else: diff --git a/scripts/itemDiff.py b/scripts/itemDiff.py index 0b7476b0b..9afa8ab7b 100755 --- a/scripts/itemDiff.py +++ b/scripts/itemDiff.py @@ -216,7 +216,7 @@ def main(old, new, groups=True, effects=True, attributes=True, renames=True): # Initialize container for the data for each item with empty stuff besides groupID dictionary[itemid] = [groupID, set(), {}] # Add items filtered by group - query = 'SELECT it.typeID, it.groupID FROM invtypes AS it INNER JOIN invgroups AS ig ON it.groupID = ig.groupID WHERE it.published = 1 AND ig.groupName IN ("Effect Beacon", "Ship Modifiers", "Mutaplasmids", "MassiveEnvironments", "Non-Interactable Object")' + query = 'SELECT it.typeID, it.groupID FROM invtypes AS it INNER JOIN invgroups AS ig ON it.groupID = ig.groupID WHERE it.published = 1 AND ig.groupName IN ("Effect Beacon", "Ship Modifiers", "Mutaplasmids", "MassiveEnvironments", "Uninteractable Localized Effect Beacon", "Non-Interactable Object")' cursor.execute(query) for row in cursor: itemid = row[0] diff --git a/scripts/jsonToSql.py b/scripts/jsonToSql.py index 67a56d310..284ff6caf 100755 --- a/scripts/jsonToSql.py +++ b/scripts/jsonToSql.py @@ -213,8 +213,13 @@ def main(db, json_path): if (row["published"] or row['groupID'] == 1306 # group Ship Modifiers, for items like tactical t3 ship modes or row['typeName'].startswith('Civilian') # Civilian weapons - or row['typeID'] in (41549, 41548, 41551,41550) # Micro Bombs (Fighters) - or row['groupID'] in (1882, 1975) # Abysmal weather (environment) + or row['typeID'] in (41549, 41548, 41551, 41550) # Micro Bombs (Fighters) + or row['groupID'] in ( + 1882, + 1975, + 1971, + 1983 # the "container" for the abysmal environments + ) # Abysmal weather (environment) ): eveTypes.add(row["typeID"]) diff --git a/service/fit.py b/service/fit.py index 38b6161a8..5fb884cad 100644 --- a/service/fit.py +++ b/service/fit.py @@ -403,7 +403,7 @@ class Fit(object): elif thing.category.name == "Fighter": fighter = es_Fighter(thing) fit.projectedFighters.append(fighter) - elif thing.group.name == "Effect Beacon": + elif thing.group.name in es_Module.SYSTEM_GROUPS: module = es_Module(thing) module.state = State.ONLINE fit.projectedModules.append(module) diff --git a/service/market.py b/service/market.py index dd2d60d14..ac314ebd5 100644 --- a/service/market.py +++ b/service/market.py @@ -21,6 +21,7 @@ import re import threading from logbook import Logger import queue +from itertools import chain # noinspection PyPackageRequirements import wx @@ -799,50 +800,4 @@ class Market(object): filtered = set([item for item in items if self.getMetaGroupIdByItem(item) in metas]) return filtered - def getSystemWideEffects(self): - """ - Get dictionary with system-wide effects - """ - # Container for system-wide effects - effects = {} - # Expressions for matching when detecting effects we're looking for - validgroups = ("Black Hole Effect Beacon", - "Cataclysmic Variable Effect Beacon", - "Magnetar Effect Beacon", - "Pulsar Effect Beacon", - "Red Giant Beacon", - "Wolf Rayet Effect Beacon", - "Incursion ship attributes effects") - # Stuff we don't want to see in names - garbages = ("Effect", "Beacon", "ship attributes effects") - # Get group with all the system-wide beacons - grp = self.getGroup("Effect Beacon") - beacons = self.getItemsByGroup(grp) - # Cycle through them - for beacon in beacons: - # Check if it belongs to any valid group - for group in validgroups: - # Check beginning of the name only - if re.match(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 groupname not in effects: - effects[groupname] = set() - effects[groupname].add((beacon, beaconname, shortname)) - # Break loop on 1st result - break - return effects +