Implement selectable booster side effects and persist them to the database, very much based on the fighter ability code. Still need to name them and enable the effects.
This also removes the old boosterActiveSideEffect table definition (migration script to drop table still needs to be written)
This commit is contained in:
@@ -24,6 +24,8 @@ import datetime
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.booster import Booster
|
||||
from eos.saveddata.boosterSideEffect import BoosterSideEffect
|
||||
from eos.saveddata.fit import Fit
|
||||
|
||||
boosters_table = Table("boosters", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
@@ -34,19 +36,21 @@ boosters_table = Table("boosters", saveddata_meta,
|
||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
|
||||
)
|
||||
|
||||
# Legacy booster side effect code, should disable but a mapper relies on it.
|
||||
activeSideEffects_table = Table("boostersActiveSideEffects", saveddata_meta,
|
||||
Column("boosterID", ForeignKey("boosters.ID"), primary_key=True),
|
||||
Column("effectID", Integer, primary_key=True))
|
||||
|
||||
booster_side_effect_table = Table("boosterSideEffects", saveddata_meta,
|
||||
Column("boosterID", Integer, ForeignKey("boosters.ID"), primary_key=True, index=True),
|
||||
Column("effectID", Integer, nullable=False, primary_key=True),
|
||||
Column("active", Boolean, default=False))
|
||||
|
||||
|
||||
class ActiveSideEffectsDummy(object):
|
||||
def __init__(self, effectID):
|
||||
self.effectID = effectID
|
||||
|
||||
|
||||
mapper(ActiveSideEffectsDummy, activeSideEffects_table)
|
||||
mapper(Booster, boosters_table,
|
||||
properties={"_Booster__activeSideEffectDummies": relation(ActiveSideEffectsDummy)})
|
||||
properties={
|
||||
"_Booster__sideEffects": relation(
|
||||
BoosterSideEffect,
|
||||
backref="booster",
|
||||
cascade='all, delete, delete-orphan'),
|
||||
}
|
||||
)
|
||||
|
||||
Booster._Booster__activeSideEffectIDs = association_proxy("_Booster__activeSideEffectDummies", "effectID")
|
||||
|
||||
mapper(BoosterSideEffect, booster_side_effect_table)
|
||||
|
||||
@@ -24,6 +24,7 @@ from sqlalchemy.orm import reconstructor, validates
|
||||
import eos.db
|
||||
from eos.effectHandlerHelpers import HandledItem
|
||||
from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut
|
||||
from eos.saveddata.boosterSideEffect import BoosterSideEffect
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
@@ -37,6 +38,9 @@ class Booster(HandledItem, ItemAttrShortcut):
|
||||
|
||||
self.itemID = item.ID if item is not None else None
|
||||
self.active = True
|
||||
|
||||
self.__sideEffects = self.__getSideEffects()
|
||||
|
||||
self.build()
|
||||
|
||||
@reconstructor
|
||||
@@ -58,34 +62,23 @@ class Booster(HandledItem, ItemAttrShortcut):
|
||||
|
||||
def build(self):
|
||||
""" Build object. Assumes proper and valid item already set """
|
||||
self.__sideEffects = []
|
||||
self.__itemModifiedAttributes = ModifiedAttributeDict()
|
||||
self.__itemModifiedAttributes.original = self.__item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self.__item.overrides
|
||||
self.__slot = self.__calculateSlot(self.__item)
|
||||
|
||||
# Legacy booster side effect code, disabling as not currently implemented
|
||||
'''
|
||||
for effect in self.__item.effects.itervalues():
|
||||
if effect.isType("boosterSideEffect"):
|
||||
s = SideEffect(self)
|
||||
s.effect = effect
|
||||
s.active = effect.ID in self.__activeSideEffectIDs
|
||||
self.__sideEffects.append(s)
|
||||
'''
|
||||
if len(self.sideEffects) != len(self.__getSideEffects()):
|
||||
self.__sideEffects = []
|
||||
for ability in self.__getSideEffects():
|
||||
self.__sideEffects.append(ability)
|
||||
|
||||
# Legacy booster side effect code, disabling as not currently implemented
|
||||
'''
|
||||
def iterSideEffects(self):
|
||||
return self.__sideEffects.__iter__()
|
||||
@property
|
||||
def sideEffects(self):
|
||||
return self.__sideEffects or []
|
||||
|
||||
def getSideEffect(self, name):
|
||||
for sideEffect in self.iterSideEffects():
|
||||
if sideEffect.effect.name == name:
|
||||
return sideEffect
|
||||
|
||||
raise KeyError("SideEffect with %s as name not found" % name)
|
||||
'''
|
||||
def __getSideEffects(self):
|
||||
"""Returns list of BoosterSideEffect that are loaded with data"""
|
||||
return [BoosterSideEffect(effect) for effect in self.item.effects.values() if effect.type and 'boosterSideEffect' in effect.type]
|
||||
|
||||
@property
|
||||
def itemModifiedAttributes(self):
|
||||
@@ -161,41 +154,3 @@ class Booster(HandledItem, ItemAttrShortcut):
|
||||
'''
|
||||
|
||||
return copy
|
||||
|
||||
|
||||
# Legacy booster side effect code, disabling as not currently implemented
|
||||
'''
|
||||
class SideEffect(object):
|
||||
def __init__(self, owner):
|
||||
self.__owner = owner
|
||||
self.__active = False
|
||||
self.__effect = None
|
||||
|
||||
@property
|
||||
def active(self):
|
||||
return self.__active
|
||||
|
||||
@active.setter
|
||||
def active(self, active):
|
||||
if not isinstance(active, bool):
|
||||
raise TypeError("Expecting a bool, not a " + type(active))
|
||||
|
||||
if active != self.__active:
|
||||
if active:
|
||||
self.__owner._Booster__activeSideEffectIDs.append(self.effect.ID)
|
||||
else:
|
||||
self.__owner._Booster__activeSideEffectIDs.remove(self.effect.ID)
|
||||
|
||||
self.__active = active
|
||||
|
||||
@property
|
||||
def effect(self):
|
||||
return self.__effect
|
||||
|
||||
@effect.setter
|
||||
def effect(self, effect):
|
||||
if not hasattr(effect, "handler"):
|
||||
raise TypeError("Need an effect with a handler")
|
||||
|
||||
self.__effect = effect
|
||||
'''
|
||||
|
||||
63
eos/saveddata/boosterSideEffect.py
Normal file
63
eos/saveddata/boosterSideEffect.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
from sqlalchemy.orm import reconstructor
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class BoosterSideEffect(object):
|
||||
|
||||
def __init__(self, effect):
|
||||
"""Initialize from the program"""
|
||||
self.__effect = effect
|
||||
self.effectID = effect.ID if effect is not None else None
|
||||
self.active = False
|
||||
self.build()
|
||||
|
||||
@reconstructor
|
||||
def init(self):
|
||||
"""Initialize from the database"""
|
||||
self.__effect = None
|
||||
|
||||
if self.effectID:
|
||||
self.__effect = next((x for x in self.booster.item.effects.itervalues() if x.ID == self.effectID), None)
|
||||
if self.__effect is None:
|
||||
pyfalog.error("Effect (id: {0}) does not exist", self.effectID)
|
||||
return
|
||||
|
||||
self.build()
|
||||
|
||||
def build(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def effect(self):
|
||||
return self.__effect
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.__effect.getattr('displayName') or self.__effect.handlerName
|
||||
|
||||
@property
|
||||
def attrPrefix(self):
|
||||
return self.__effect.getattr('prefix')
|
||||
|
||||
@@ -49,6 +49,7 @@ class BoosterView(d.Display):
|
||||
"State",
|
||||
"attr:boosterness",
|
||||
"Base Name",
|
||||
"Side Effects",
|
||||
"Price",
|
||||
]
|
||||
|
||||
|
||||
64
gui/builtinContextMenus/boosterSideEffects.py
Normal file
64
gui/builtinContextMenus/boosterSideEffects.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
from gui.contextMenu import ContextMenu
|
||||
import gui.mainFrame
|
||||
import gui.globalEvents as GE
|
||||
from service.fit import Fit
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
class BoosterSideEffect(ContextMenu):
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.settings = ContextMenuSettings.getInstance()
|
||||
|
||||
def display(self, srcContext, selection):
|
||||
# if not self.settings.get('fighterAbilities'):
|
||||
# return False
|
||||
|
||||
if self.mainFrame.getActiveFit() is None or srcContext not in ("boosterItem"):
|
||||
return False
|
||||
|
||||
self.booster = selection[0]
|
||||
return True
|
||||
|
||||
def getText(self, itmContext, selection):
|
||||
return "Side Effects"
|
||||
|
||||
def addEffect(self, menu, ability):
|
||||
label = ability.name
|
||||
id = ContextMenu.nextID()
|
||||
self.effectIds[id] = ability
|
||||
menuItem = wx.MenuItem(menu, id, label, kind=wx.ITEM_CHECK)
|
||||
menu.Bind(wx.EVT_MENU, self.handleMode, menuItem)
|
||||
return menuItem
|
||||
|
||||
def getSubMenu(self, context, selection, rootMenu, i, pitem):
|
||||
msw = True if "wxMSW" in wx.PlatformInfo else False
|
||||
self.context = context
|
||||
self.effectIds = {}
|
||||
|
||||
sub = wx.Menu()
|
||||
|
||||
for effect in self.booster.sideEffects:
|
||||
if not effect.effect.isImplemented:
|
||||
continue
|
||||
menuItem = self.addEffect(rootMenu if msw else sub, effect)
|
||||
sub.AppendItem(menuItem)
|
||||
menuItem.Check(effect.active)
|
||||
|
||||
return sub
|
||||
|
||||
def handleMode(self, event):
|
||||
effect = self.effectIds[event.Id]
|
||||
if effect is False or effect not in self.booster.sideEffects:
|
||||
event.Skip()
|
||||
return
|
||||
|
||||
sFit = Fit.getInstance()
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
sFit.toggleBoosterSideEffect(fitID, effect)
|
||||
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
|
||||
|
||||
|
||||
BoosterSideEffect.register()
|
||||
@@ -1,2 +1,2 @@
|
||||
__all__ = ["ammo", "ammoIcon", "attributeDisplay", "baseIcon", "baseName",
|
||||
"capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc", "abilities"]
|
||||
"capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc", "abilities", "sideEffects"]
|
||||
|
||||
46
gui/builtinViewColumns/sideEffects.py
Normal file
46
gui/builtinViewColumns/sideEffects.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
from eos.saveddata.booster import Booster
|
||||
from gui.viewColumn import ViewColumn
|
||||
import gui.mainFrame
|
||||
|
||||
|
||||
class SideEffects(ViewColumn):
|
||||
name = "Side Effects"
|
||||
|
||||
def __init__(self, fittingView, params):
|
||||
ViewColumn.__init__(self, fittingView)
|
||||
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.columnText = "Active Side Effects"
|
||||
self.mask = wx.LIST_MASK_TEXT
|
||||
|
||||
def getText(self, stuff):
|
||||
if isinstance(stuff, Booster):
|
||||
active = [x.name for x in stuff.sideEffects if x.active]
|
||||
if len(active) == 0:
|
||||
return "None"
|
||||
return ", ".join(active)
|
||||
|
||||
|
||||
SideEffects.register()
|
||||
@@ -206,6 +206,7 @@ from gui.builtinContextMenus import ( # noqa: E402,F401
|
||||
metaSwap,
|
||||
implantSets,
|
||||
fighterAbilities,
|
||||
boosterSideEffects,
|
||||
commandFits,
|
||||
tabbedFits
|
||||
)
|
||||
|
||||
@@ -79,5 +79,6 @@ from gui.builtinViewColumns import ( # noqa: E402, F401
|
||||
misc,
|
||||
price,
|
||||
propertyDisplay,
|
||||
state
|
||||
state,
|
||||
sideEffects
|
||||
)
|
||||
|
||||
@@ -991,6 +991,13 @@ class Fit(object):
|
||||
eos.db.commit()
|
||||
self.recalc(fit)
|
||||
|
||||
def toggleBoosterSideEffect(self, fitID, sideEffect):
|
||||
pyfalog.debug("Toggling booster side effect for fit ID: {0}", fitID)
|
||||
fit = eos.db.getFit(fitID)
|
||||
sideEffect.active = not sideEffect.active
|
||||
eos.db.commit()
|
||||
self.recalc(fit)
|
||||
|
||||
def changeChar(self, fitID, charID):
|
||||
pyfalog.debug("Changing character ({0}) for fit ID: {1}", charID, fitID)
|
||||
if fitID is None or charID is None:
|
||||
|
||||
Reference in New Issue
Block a user