Merge branch 'EffectTest' of https://github.com/Ebag333/Pyfa into Ebag333-EffectTest
Conflicts: eos/saveddata/fit.py eos/saveddata/module.py
This commit is contained in:
@@ -31,6 +31,7 @@ boosters_table = Table("boosters", saveddata_meta,
|
||||
Column("active", Boolean),
|
||||
)
|
||||
|
||||
# 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))
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# Used by:
|
||||
# Implants from group: Booster (12 of 47)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# Implants named like: Mindflood Booster (3 of 4)
|
||||
# Implants named like: Sooth Sayer Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# Implants named like: Blue Pill Booster (3 of 5)
|
||||
# Implants named like: Exile Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# Used by:
|
||||
# Implants from group: Booster (12 of 47)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# Implants named like: Exile Booster (3 of 4)
|
||||
# Implants named like: Mindflood Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# Used by:
|
||||
# Implants named like: Blue Pill Booster (3 of 5)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# Implants named like: Crash Booster (3 of 4)
|
||||
# Implants named like: X Instinct Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# Used by:
|
||||
# Implants from group: Booster (12 of 47)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# Implants named like: Drop Booster (3 of 4)
|
||||
# Implants named like: X Instinct Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# Implants named like: Mindflood Booster (3 of 4)
|
||||
# Implants named like: Sooth Sayer Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# Implants named like: Exile Booster (3 of 4)
|
||||
# Implants named like: Frentix Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
activeByDefault = False
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
|
||||
@@ -83,6 +83,40 @@ class Effect(EqBase):
|
||||
|
||||
return self.__runTime
|
||||
|
||||
@property
|
||||
def activeByDefault(self):
|
||||
"""
|
||||
The state that this effect should be be in.
|
||||
This property is also automaticly fetched from effects/<effectName>.py if the file exists.
|
||||
the possible values are:
|
||||
None, True, False
|
||||
|
||||
If this is not set:
|
||||
We simply assume that missing/none = True, and set it accordingly
|
||||
(much as we set runTime to Normalif not otherwise set).
|
||||
Nearly all effect files will fall under this category.
|
||||
|
||||
If this is set to True:
|
||||
We would enable it anyway, but hey, it's double enabled.
|
||||
No effect files are currently configured this way (and probably will never be).
|
||||
|
||||
If this is set to False:
|
||||
Basically we simply skip adding the effect to the effect handler when the effect is called,
|
||||
much as if the run time didn't match or other criteria failed.
|
||||
"""
|
||||
if not self.__generated:
|
||||
self.__generateHandler()
|
||||
|
||||
return self.__activeByDefault
|
||||
|
||||
@activeByDefault.setter
|
||||
def activeByDefault(self, value):
|
||||
"""
|
||||
Just assign the input values to the activeByDefault attribute.
|
||||
You *could* do something more interesting here if you wanted.
|
||||
"""
|
||||
self.__activeByDefault = value
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
"""
|
||||
@@ -133,6 +167,11 @@ class Effect(EqBase):
|
||||
except AttributeError:
|
||||
self.__runTime = "normal"
|
||||
|
||||
try:
|
||||
self.__activeByDefault = getattr(effectModule, "activeByDefault")
|
||||
except AttributeError:
|
||||
self.__activeByDefault = True
|
||||
|
||||
try:
|
||||
t = getattr(effectModule, "type")
|
||||
except AttributeError:
|
||||
@@ -143,6 +182,7 @@ class Effect(EqBase):
|
||||
except (ImportError, AttributeError) as e:
|
||||
self.__handler = effectDummy
|
||||
self.__runTime = "normal"
|
||||
self.__activeByDefault = True
|
||||
self.__type = None
|
||||
except Exception as e:
|
||||
traceback.print_exc(e)
|
||||
|
||||
@@ -64,13 +64,18 @@ class Booster(HandledItem, ItemAttrShortcut):
|
||||
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)
|
||||
'''
|
||||
|
||||
# Legacy booster side effect code, disabling as not currently implemented
|
||||
'''
|
||||
def iterSideEffects(self):
|
||||
return self.__sideEffects.__iter__()
|
||||
|
||||
@@ -80,6 +85,7 @@ class Booster(HandledItem, ItemAttrShortcut):
|
||||
return sideEffect
|
||||
|
||||
raise KeyError("SideEffect with %s as name not found" % name)
|
||||
'''
|
||||
|
||||
@property
|
||||
def itemModifiedAttributes(self):
|
||||
@@ -112,12 +118,17 @@ class Booster(HandledItem, ItemAttrShortcut):
|
||||
if not self.active:
|
||||
return
|
||||
for effect in self.item.effects.itervalues():
|
||||
if effect.runTime == runTime and effect.isType("passive"):
|
||||
if effect.runTime == runTime and \
|
||||
(effect.isType("passive") or effect.isType("boosterSideEffect")) and \
|
||||
effect.activeByDefault:
|
||||
effect.handler(fit, self, ("booster",))
|
||||
|
||||
# Legacy booster code, not fully implemented
|
||||
'''
|
||||
for sideEffect in self.iterSideEffects():
|
||||
if sideEffect.active and sideEffect.effect.runTime == runTime:
|
||||
sideEffect.effect.handler(fit, self, ("boosterSideEffect",))
|
||||
'''
|
||||
|
||||
@validates("ID", "itemID", "ammoID", "active")
|
||||
def validator(self, key, val):
|
||||
@@ -135,46 +146,52 @@ class Booster(HandledItem, ItemAttrShortcut):
|
||||
def __deepcopy__(self, memo):
|
||||
copy = Booster(self.item)
|
||||
copy.active = self.active
|
||||
|
||||
# Legacy booster side effect code, disabling as not currently implemented
|
||||
'''
|
||||
origSideEffects = list(self.iterSideEffects())
|
||||
copySideEffects = list(copy.iterSideEffects())
|
||||
i = 0
|
||||
while i < len(origSideEffects):
|
||||
copySideEffects[i].active = origSideEffects[i].active
|
||||
i += 1
|
||||
'''
|
||||
|
||||
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
|
||||
|
||||
class SideEffect(object):
|
||||
def __init__(self, owner):
|
||||
self.__owner = owner
|
||||
self.__active = False
|
||||
self.__effect = None
|
||||
@property
|
||||
def active(self):
|
||||
return self.__active
|
||||
|
||||
@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))
|
||||
|
||||
@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)
|
||||
|
||||
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
|
||||
|
||||
self.__active = active
|
||||
@property
|
||||
def effect(self):
|
||||
return self.__effect
|
||||
|
||||
@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")
|
||||
|
||||
@effect.setter
|
||||
def effect(self, effect):
|
||||
if not hasattr(effect, "handler"):
|
||||
raise TypeError("Need an effect with a handler")
|
||||
|
||||
self.__effect = effect
|
||||
self.__effect = effect
|
||||
'''
|
||||
@@ -335,8 +335,10 @@ class Skill(HandledItem):
|
||||
return
|
||||
|
||||
for effect in item.effects.itervalues():
|
||||
if effect.runTime == runTime and effect.isType("passive") and \
|
||||
(not fit.isStructure or effect.isType("structure")):
|
||||
if effect.runTime == runTime and \
|
||||
effect.isType("passive") and \
|
||||
(not fit.isStructure or effect.isType("structure")) and \
|
||||
effect.activeByDefault:
|
||||
try:
|
||||
effect.handler(fit, self, ("skill",))
|
||||
except AttributeError:
|
||||
|
||||
@@ -232,6 +232,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
|
||||
for effect in self.item.effects.itervalues():
|
||||
if effect.runTime == runTime and \
|
||||
effect.activeByDefault and \
|
||||
((projected is True and effect.isType("projected")) or
|
||||
projected is False and effect.isType("passive")):
|
||||
# See GH issue #765
|
||||
@@ -245,7 +246,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
|
||||
if self.charge:
|
||||
for effect in self.charge.effects.itervalues():
|
||||
if effect.runTime == runTime:
|
||||
if effect.runTime == runTime and effect.activeByDefault:
|
||||
effect.handler(fit, self, ("droneCharge",))
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
|
||||
@@ -270,6 +270,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
if ability.active:
|
||||
effect = ability.effect
|
||||
if effect.runTime == runTime and \
|
||||
effect.activeByDefault and \
|
||||
((projected and effect.isType("projected")) or not projected):
|
||||
if ability.grouped:
|
||||
effect.handler(fit, self, context)
|
||||
|
||||
@@ -462,6 +462,8 @@ class Fit(object):
|
||||
|
||||
context = ("commandRun", thing.__class__.__name__.lower())
|
||||
if isinstance(thing, Module):
|
||||
# This should always be a gang effect, otherwise it wouldn't be added to commandBonuses
|
||||
# @todo: Check this
|
||||
if effect.isType("gang"):
|
||||
# todo: ensure that these are run with the module is active only
|
||||
context += ("commandRun",)
|
||||
|
||||
@@ -93,7 +93,7 @@ class Implant(HandledItem, ItemAttrShortcut):
|
||||
if not self.active:
|
||||
return
|
||||
for effect in self.item.effects.itervalues():
|
||||
if effect.runTime == runTime and effect.isType("passive"):
|
||||
if effect.runTime == runTime and effect.isType("passive") and effect.activeByDefault:
|
||||
effect.handler(fit, self, ("implant",))
|
||||
|
||||
@validates("fitID", "itemID", "active")
|
||||
|
||||
@@ -51,5 +51,5 @@ class Mode(ItemAttrShortcut, HandledItem):
|
||||
def calculateModifiedAttributes(self, fit, runTime, forceProjected=False):
|
||||
if self.item:
|
||||
for effect in self.item.effects.itervalues():
|
||||
if effect.runTime == runTime:
|
||||
if effect.runTime == runTime and effect.activeByDefault:
|
||||
effect.handler(fit, self, context=("module",))
|
||||
|
||||
@@ -625,6 +625,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
if not projected or (self.projected and not forceProjected) or gang:
|
||||
for effect in self.charge.effects.itervalues():
|
||||
if effect.runTime == runTime and \
|
||||
effect.activeByDefault and \
|
||||
(effect.isType("offline") or
|
||||
(effect.isType("passive") and self.state >= State.ONLINE) or
|
||||
(effect.isType("active") and self.state >= State.ACTIVE)) and \
|
||||
@@ -645,19 +646,18 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
if effect.runTime == runTime and \
|
||||
effect.isType("overheat") \
|
||||
and not forceProjected \
|
||||
and effect.activeByDefault \
|
||||
and ((gang and effect.isType("gang")) or not gang):
|
||||
effect.handler(fit, self, context)
|
||||
|
||||
for effect in self.item.effects.itervalues():
|
||||
if effect.runTime == runTime and \
|
||||
effect.activeByDefault and \
|
||||
(effect.isType("offline") or
|
||||
(effect.isType("passive") and self.state >= State.ONLINE) or
|
||||
(effect.isType("active") and self.state >= State.ACTIVE))\
|
||||
and ((projected and effect.isType("projected")) or not projected)\
|
||||
and ((gang and effect.isType("gang")) or not gang):
|
||||
thing = effect.isType("gang")
|
||||
if gang:
|
||||
pass
|
||||
effect.handler(fit, self, context)
|
||||
|
||||
@property
|
||||
|
||||
@@ -82,7 +82,9 @@ class Ship(ItemAttrShortcut, HandledItem):
|
||||
if forceProjected:
|
||||
return
|
||||
for effect in self.item.effects.itervalues():
|
||||
if effect.runTime == runTime and effect.isType("passive"):
|
||||
if effect.runTime == runTime and \
|
||||
effect.isType("passive") and \
|
||||
effect.activeByDefault:
|
||||
# Ships have effects that utilize the level of a skill as an
|
||||
# additional operator to the modifier. These are defined in
|
||||
# the effect itself, and these skillbooks are registered when
|
||||
|
||||
@@ -34,7 +34,8 @@ from eos.saveddata.fighter import Fighter
|
||||
from eos.saveddata.cargo import Cargo
|
||||
from eos.saveddata.implant import Implant
|
||||
from eos.saveddata.implantSet import ImplantSet
|
||||
from eos.saveddata.booster import SideEffect
|
||||
# Legacy booster side effect code, disabling as not currently implemented
|
||||
# from eos.saveddata.booster import SideEffect
|
||||
from eos.saveddata.booster import Booster
|
||||
from eos.saveddata.fit import Fit, ImplantLocation
|
||||
from eos.saveddata.mode import Mode
|
||||
|
||||
@@ -740,31 +740,44 @@ class ItemRequirements ( wx.Panel ):
|
||||
|
||||
class ItemEffects (wx.Panel):
|
||||
def __init__(self, parent, stuff, item):
|
||||
wx.Panel.__init__ (self, parent)
|
||||
mainSizer = wx.BoxSizer( wx.VERTICAL )
|
||||
wx.Panel.__init__(self, parent)
|
||||
self.item = item
|
||||
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
self.effectList = AutoListCtrl(self, wx.ID_ANY,
|
||||
style =
|
||||
#wx.LC_HRULES |
|
||||
#wx.LC_NO_HEADER |
|
||||
wx.LC_REPORT |wx.LC_SINGLE_SEL |wx.LC_VRULES |wx.NO_BORDER)
|
||||
mainSizer.Add( self.effectList, 1, wx.ALL|wx.EXPAND, 0 )
|
||||
self.SetSizer( mainSizer )
|
||||
style=
|
||||
# wx.LC_HRULES |
|
||||
# wx.LC_NO_HEADER |
|
||||
wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
|
||||
mainSizer.Add(self.effectList, 1, wx.ALL | wx.EXPAND, 0)
|
||||
self.SetSizer(mainSizer)
|
||||
|
||||
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnClick, self.effectList)
|
||||
if config.debug:
|
||||
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnClick, self.effectList)
|
||||
self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnRightClick, self.effectList)
|
||||
|
||||
self.PopulateList()
|
||||
|
||||
def PopulateList(self):
|
||||
|
||||
self.effectList.InsertColumn(0,"Name")
|
||||
self.effectList.InsertColumn(1,"Implemented")
|
||||
self.effectList.InsertColumn(1,"Active")
|
||||
self.effectList.InsertColumn(2, "Type")
|
||||
if config.debug:
|
||||
self.effectList.InsertColumn(2,"ID")
|
||||
self.effectList.InsertColumn(3, "Run Time")
|
||||
self.effectList.InsertColumn(4,"ID")
|
||||
|
||||
#self.effectList.SetColumnWidth(0,385)
|
||||
|
||||
self.effectList.setResizeColumn(0)
|
||||
self.effectList.SetColumnWidth(1,50)
|
||||
self.effectList.SetColumnWidth(2, 80)
|
||||
if config.debug:
|
||||
self.effectList.SetColumnWidth(3, 65)
|
||||
self.effectList.SetColumnWidth(4, 40)
|
||||
|
||||
self.effectList.SetColumnWidth(1,100)
|
||||
|
||||
item = self.item
|
||||
effects = item.effects
|
||||
names = list(effects.iterkeys())
|
||||
names.sort()
|
||||
@@ -772,19 +785,55 @@ class ItemEffects (wx.Panel):
|
||||
for name in names:
|
||||
index = self.effectList.InsertStringItem(sys.maxint, name)
|
||||
|
||||
try:
|
||||
implemented = "Yes" if effects[name].isImplemented else "No"
|
||||
except:
|
||||
implemented = "Erroneous"
|
||||
if effects[name].isImplemented:
|
||||
if effects[name].activeByDefault:
|
||||
activeByDefault = "Yes"
|
||||
else:
|
||||
activeByDefault = "No"
|
||||
else:
|
||||
activeByDefault = ""
|
||||
|
||||
self.effectList.SetStringItem(index, 1, implemented)
|
||||
effectTypeText = ""
|
||||
if effects[name].type:
|
||||
for effectType in effects[name].type:
|
||||
effectTypeText += effectType + " "
|
||||
pass
|
||||
|
||||
if effects[name].runTime and effects[name].isImplemented:
|
||||
effectRunTime = str(effects[name].runTime)
|
||||
else:
|
||||
effectRunTime = ""
|
||||
|
||||
self.effectList.SetStringItem(index, 1, activeByDefault)
|
||||
self.effectList.SetStringItem(index, 2, effectTypeText)
|
||||
if config.debug:
|
||||
self.effectList.SetStringItem(index, 2, str(effects[name].ID))
|
||||
self.effectList.SetStringItem(index, 3, effectRunTime)
|
||||
self.effectList.SetStringItem(index, 4, str(effects[name].ID))
|
||||
|
||||
self.effectList.RefreshRows()
|
||||
self.Layout()
|
||||
|
||||
def OnClick(self, event):
|
||||
"""
|
||||
Debug use: toggle effects on/off.
|
||||
Affects *ALL* items that use that effect.
|
||||
Is not stateful. Will reset if Pyfa is closed and reopened.
|
||||
"""
|
||||
|
||||
try:
|
||||
activeByDefault = getattr(self.item.effects[event.GetText()], "activeByDefault")
|
||||
if activeByDefault:
|
||||
setattr(self.item.effects[event.GetText()], "activeByDefault", False)
|
||||
else:
|
||||
setattr(self.item.effects[event.GetText()], "activeByDefault", True)
|
||||
|
||||
except AttributeError:
|
||||
# Attribute doesn't exist, do nothing
|
||||
pass
|
||||
|
||||
self.RefreshValues(event)
|
||||
|
||||
def OnRightClick(self, event):
|
||||
"""
|
||||
Debug use: open effect file with default application.
|
||||
If effect file does not exist, create it
|
||||
@@ -804,6 +853,14 @@ class ItemEffects (wx.Panel):
|
||||
import subprocess
|
||||
subprocess.call(["xdg-open", file])
|
||||
|
||||
def RefreshValues(self, event):
|
||||
self.Freeze()
|
||||
self.effectList.ClearAll()
|
||||
self.PopulateList()
|
||||
self.effectList.RefreshRows()
|
||||
self.Layout()
|
||||
self.Thaw()
|
||||
event.Skip()
|
||||
|
||||
###########################################################################
|
||||
## Class ItemAffectedBy
|
||||
|
||||
Reference in New Issue
Block a user