Merge branch 'abysmal_weather' into singularity

# Conflicts:
#	eve.db
This commit is contained in:
blitzmann
2018-05-27 17:25:47 -04:00
19 changed files with 369 additions and 74 deletions

View File

@@ -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')

View File

@@ -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')

View File

@@ -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')

View File

@@ -0,0 +1,6 @@
runTime = "early"
type = ("projected", "passive")
def handler(fit, beacon, context):
pass

View File

@@ -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')

View File

@@ -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')

View File

@@ -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')

View File

@@ -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')

View File

@@ -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')

View File

@@ -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):

View File

@@ -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")

BIN
eve.db

Binary file not shown.

View File

@@ -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()

View File

@@ -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()

View File

@@ -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:

View File

@@ -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]

View File

@@ -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"])

View File

@@ -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)

View File

@@ -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