diff --git a/eos/db/gamedata/dynamicAttributes.py b/eos/db/gamedata/dynamicAttributes.py index 04d7de2d0..be0e9b9d1 100644 --- a/eos/db/gamedata/dynamicAttributes.py +++ b/eos/db/gamedata/dynamicAttributes.py @@ -18,7 +18,7 @@ # =============================================================================== from sqlalchemy import Column, Float, Integer, Table, ForeignKey -from sqlalchemy.orm import mapper, relation +from sqlalchemy.orm import mapper, relation, synonym from sqlalchemy.ext.associationproxy import association_proxy from eos.db import gamedata_meta @@ -45,7 +45,8 @@ mapper(DynamicItem, dynamic_table, properties={ "attributes": relation(DynamicItemAttribute), "item": relation(Item, foreign_keys=[dynamic_table.c.typeID]), "resultingItem": relation(Item, foreign_keys=[dynamic_table.c.resultingTypeID]), - }) + "ID": synonym("typeID"), +}) mapper(DynamicItemAttribute, dynamicAttributes_table, properties={"info": relation(AttributeInfo, lazy=False)}) diff --git a/eos/db/gamedata/queries.py b/eos/db/gamedata/queries.py index e7fbca61c..0da3f38a4 100644 --- a/eos/db/gamedata/queries.py +++ b/eos/db/gamedata/queries.py @@ -105,7 +105,7 @@ def getItemWithBaseItemAttribute(lookfor, baseItemID, eager=None): # we have to load all attributes for this object, otherwise we'll lose access to them when we expunge. # todo: figure out a way to eagerly load all these via the query... - for x in inspect(Item).relationships.keys(): + for x in [*inspect(Item).relationships.keys(), 'description']: getattr(item, x) # Copy over the attributes from the base, but ise the items attributes when there's an overlap diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index e400bf951..bdf6af4c1 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -74,16 +74,31 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): MINING_ATTRIBUTES = ("miningAmount",) SYSTEM_GROUPS = ("Effect Beacon", "MassiveEnvironments", "Uninteractable Localized Effect Beacon", "Non-Interactable Object") - def __init__(self, item): + def __init__(self, item, baseItem=None, mutaplasmid=None): """Initialize a module from the program""" - self.__item = item - self.__baseItem = None + + self.itemID = item.ID if item is not None else None + self.baseItemID = baseItem.ID if baseItem is not None else None + self.mutaplasmidID = mutaplasmid.ID if mutaplasmid is not None else None + + if baseItem is not None: + # we're working with a mutated module, need to get abyssal module loaded with the base attributes + # Note: there may be a better way of doing this, such as a metho on this classe to convert(mutaplamid). This + # will require a bit more research though, considering there has never been a need to "swap" out the item of a Module + # before, and there may be assumptions taken with regards to the item never changing (pre-calculated / cached results, for example) + self.__item = eos.db.getItemWithBaseItemAttribute(self.itemID, self.baseItemID) + self.__baseItem = baseItem + self.__mutaplasmid = mutaplasmid + else: + self.__item = item + self.__baseItem = baseItem + self.__mutaplasmid = mutaplasmid if item is not None and self.isInvalid: raise ValueError("Passed item is not a Module") self.__charge = None - self.itemID = item.ID if item is not None else None + self.projected = False self.state = State.ONLINE self.build() @@ -107,6 +122,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if self.baseItemID: self.__item = eos.db.getItemWithBaseItemAttribute(self.itemID, self.baseItemID) self.__baseItem = eos.db.getItem(self.baseItemID) + self.__mutaplasmid = eos.db.getItem(self.mutaplasmidID) if self.__baseItem is None: pyfalog.error("Base Item (id: {0}) does not exist", self.itemID) return @@ -172,6 +188,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @property def isInvalid(self): + # todo: validate baseItem as well if it's set. if self.isEmpty: return False return self.__item is None or \ diff --git a/gui/builtinContextMenus/mutaplasmids.py b/gui/builtinContextMenus/mutaplasmids.py index d26036a00..268e809b2 100644 --- a/gui/builtinContextMenus/mutaplasmids.py +++ b/gui/builtinContextMenus/mutaplasmids.py @@ -41,7 +41,7 @@ class MutaplasmidCM(ContextMenu): for item in mod.item.mutaplasmids: label = item.item.name id = ContextMenu.nextID() - self.eventIDs[id] = item + self.eventIDs[id] = (item, mod) skillItem = wx.MenuItem(sub, id, label) rootMenu.Bind(wx.EVT_MENU, self.activate, skillItem) sub.Append(skillItem) @@ -49,13 +49,13 @@ class MutaplasmidCM(ContextMenu): return sub def activate(self, event): - mutaplasmid = self.eventIDs[event.ID] + mutaplasmid, mod = self.eventIDs[event.Id] fit = self.mainFrame.getActiveFit() sFit = Fit.getInstance() # todo: dev out function to switch module to an abyssal module. Also, maybe open item stats here automatically # with the attribute tab set? - + sFit.convertMutaplasmid(fit, mod.modPosition, mutaplasmid) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fit)) def getBitmap(self, context, selection): diff --git a/service/fit.py b/service/fit.py index 5fb884cad..774b2965c 100644 --- a/service/fit.py +++ b/service/fit.py @@ -575,6 +575,37 @@ class Fit(object): eos.db.commit() return numSlots != len(fit.modules) + def convertMutaplasmid(self, fitID, position, mutaplasmid): + # this is mostly the same thing as the self.changeModule method, however it initializes an abyssal module with + # the old module as it's base, and then replaces it + fit = eos.db.getFit(fitID) + base = fit.modules[position] + fit.modules.toDummy(position) + + try: + m = es_Module(mutaplasmid.resultingItem, base.item, mutaplasmid) + except ValueError: + pyfalog.warning("Invalid item: {0} AHHHH") + return False + + if m.fits(fit): + m.owner = fit + fit.modules.toModule(position, m) + if m.isValidState(State.ACTIVE): + m.state = State.ACTIVE + + # As some items may affect state-limiting attributes of the ship, calculate new attributes first + self.recalc(fit) + # Then, check states of all modules and change where needed. This will recalc if needed + self.checkStates(fit, m) + + fit.fill() + eos.db.commit() + + return True + else: + return None + def changeModule(self, fitID, position, newItemID): fit = eos.db.getFit(fitID)