Ensure that owner fit is always visible from all fit items and their modified attribute map

Fixes some issues with some afflictions not shown/registered when fit has just been loaded
This commit is contained in:
DarkPhoenix
2019-04-17 15:35:15 +03:00
parent 53915eb956
commit 400bb10ed3
5 changed files with 43 additions and 27 deletions

View File

@@ -32516,7 +32516,7 @@ class Effect6871(BaseEffect):
# Get pilot sec status bonus directly here, instead of going through the intermediary effects
# via https://forums.eveonline.com/default.aspx?g=posts&t=515826
try:
bonus = max(0, min(50.0, (src.parent.character.secStatus * 10)))
bonus = max(0, min(50.0, (src.owner.character.secStatus * 10)))
except:
bonus = None

View File

@@ -65,8 +65,8 @@ class ModifiedAttributeDict(collections.MutableMapping):
pass
def __init__(self, fit=None, parent=None):
self.__fit = fit
self.parent = parent
self.fit = fit
# Stores original values of the entity
self.__original = None
# Modified values during calculations
@@ -101,6 +101,22 @@ class ModifiedAttributeDict(collections.MutableMapping):
self.__penalizedMultipliers.clear()
self.__postIncreases.clear()
@property
def fit(self):
# self.fit is usually set during fit calculations when the item is registered with the fit. However,
# under certain circumstances, an effect will not work as it will try to modify an item which has NOT
# yet been registered and thus has not had self.fit set. In this case, use the modules owner attribute
# to point to the correct fit. See GH Issue #434
if self.__fit is not None:
return self.__fit
if hasattr(self.parent, 'owner'):
return self.parent.owner
return None
@fit.setter
def fit(self, fit):
self.__fit = fit
@property
def original(self):
return self.__original
@@ -289,14 +305,7 @@ class ModifiedAttributeDict(collections.MutableMapping):
with the fit and thus get the correct affector. Returns skill level to
be used to modify modifier. See GH issue #101
"""
fit = self.fit
if not fit:
# self.fit is usually set during fit calculations when the item is registered with the fit. However,
# under certain circumstances, an effect will not work as it will try to modify an item which has NOT
# yet been registered and thus has not had self.fit set. In this case, use the modules owner attribute
# to point to the correct fit. See GH Issue #434
fit = self.parent.owner
skill = fit.character.getSkill(skillName)
skill = self.fit.character.getSkill(skillName)
self.__tmpModifier = skill
return skill.level
@@ -309,14 +318,15 @@ class ModifiedAttributeDict(collections.MutableMapping):
def __afflict(self, attributeName, operation, bonus, used=True):
"""Add modifier to list of things affecting current item"""
# Do nothing if no fit is assigned
if self.fit is None:
fit = self.fit
if fit is None:
return
# Create dictionary for given attribute and give it alias
if attributeName not in self.__affectedBy:
self.__affectedBy[attributeName] = {}
affs = self.__affectedBy[attributeName]
origin = self.fit.getOrigin()
fit = origin if origin and origin != self.fit else self.fit
origin = fit.getOrigin()
fit = origin if origin and origin != fit else fit
# If there's no set for current fit in dictionary, create it
if fit not in affs:
affs[fit] = []
@@ -328,7 +338,7 @@ class ModifiedAttributeDict(collections.MutableMapping):
modifier = self.__tmpModifier
self.__tmpModifier = None
else:
modifier = self.fit.getModifier()
modifier = fit.getModifier()
# Add current affliction to list
affs.append((modifier, operation, bonus, used))

View File

@@ -51,7 +51,7 @@ class Fit(object):
# use @mode.setter's to set __attr and IDs. This will set mode as well
self.ship = ship
if self.ship:
self.ship.parent = self
self.ship.owner = self
self.__modules = HandledModuleList()
self.__drones = HandledDroneCargoList()
@@ -103,9 +103,9 @@ class Fit(object):
if self.modeID and self.__ship:
item = eos.db.getItem(self.modeID)
# Don't need to verify if it's a proper item, as validateModeItem assures this
self.__mode = self.ship.validateModeItem(item)
self.__mode = self.ship.validateModeItem(item, owner=self)
else:
self.__mode = self.ship.validateModeItem(None)
self.__mode = self.ship.validateModeItem(None, owner=self)
self.build()
@@ -166,8 +166,12 @@ class Fit(object):
@mode.setter
def mode(self, mode):
if self.__mode is not None:
self.__mode.owner = None
self.__mode = mode
self.modeID = mode.item.ID if mode is not None else None
if mode is not None:
mode.owner = self
@property
def modifiedCoalesce(self):
@@ -200,11 +204,14 @@ class Fit(object):
@ship.setter
def ship(self, ship):
if self.__ship is not None:
self.__ship.owner = None
self.__ship = ship
self.shipID = ship.item.ID if ship is not None else None
if ship is not None:
ship.owner = self
# set mode of new ship
self.mode = self.ship.validateModeItem(None) if ship is not None else None
self.mode = self.ship.validateModeItem(None, owner=self) if ship is not None else None
# set fit attributes the same as ship
self.extraAttributes = self.ship.itemModifiedAttributes
@@ -500,7 +507,6 @@ class Fit(object):
continue
# This should always be a gang effect, otherwise it wouldn't be added to commandBonuses
# @todo: Check this
if effect.isType("gang"):
self.register(thing)

View File

@@ -22,17 +22,19 @@ from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut
class Mode(ItemAttrShortcut, HandledItem):
def __init__(self, item):
def __init__(self, item, owner=None):
if item.group.name != "Ship Modifiers":
raise ValueError(
'Passed item "%s" (category: (%s)) is not a Ship Modifier' % (item.name, item.category.name))
self.owner = owner
self.__item = item
self.__itemModifiedAttributes = ModifiedAttributeDict()
self.__itemModifiedAttributes.original = self.item.attributes
self.__itemModifiedAttributes.overrides = self.item.overrides
@property
def item(self):
return self.__item

View File

@@ -44,7 +44,7 @@ class Ship(ItemAttrShortcut, HandledItem):
# as None unless the Entosis effect sets it.
}
def __init__(self, item, parent=None):
def __init__(self, item, owner=None):
self.validate(item)
self.__item = item
@@ -57,9 +57,7 @@ class Ship(ItemAttrShortcut, HandledItem):
if "maximumRangeCap" in self.__itemModifiedAttributes.original:
cappingAttrKeyCache["maxTargetRange"] = "maximumRangeCap"
# there are occasions when we need to get to the parent fit of the ship, such as when we need the character
# skills for ship-role gang boosts (Titans)
self.parent = parent
self.owner = owner
self.commandBonus = 0
def validate(self, item):
@@ -102,7 +100,7 @@ class Ship(ItemAttrShortcut, HandledItem):
fit.register(self)
effect.handler(fit, self, ("ship",))
def validateModeItem(self, item):
def validateModeItem(self, item, owner=None):
""" Checks if provided item is a valid mode """
items = self.__modeItems
@@ -110,7 +108,7 @@ class Ship(ItemAttrShortcut, HandledItem):
# if we have items, then we are in a tactical destroyer and must have a mode
if item is None or item not in items:
# If provided item is invalid mode, force new one
return Mode(items[0])
return Mode(items[0], owner=owner)
return Mode(item)
return None