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:
Ryan Holmes
2016-11-22 12:34:10 -05:00
24 changed files with 192 additions and 57 deletions

View File

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

View File

@@ -3,6 +3,7 @@
# Used by:
# Implants from group: Booster (12 of 47)
type = "boosterSideEffect"
activeByDefault = False
def handler(fit, booster, context):

View File

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

View File

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

View File

@@ -3,6 +3,7 @@
# Used by:
# Implants from group: Booster (12 of 47)
type = "boosterSideEffect"
activeByDefault = False
def handler(fit, booster, context):

View File

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

View File

@@ -3,6 +3,7 @@
# Used by:
# Implants named like: Blue Pill Booster (3 of 5)
type = "boosterSideEffect"
activeByDefault = False
def handler(fit, booster, context):

View File

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

View File

@@ -3,6 +3,7 @@
# Used by:
# Implants from group: Booster (12 of 47)
type = "boosterSideEffect"
activeByDefault = False
def handler(fit, booster, context):

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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