Start implementing support for mutaplasmids.

* There's a new table `mutators` that has an FK back to a module, and links to an attribute ID with it's new value
* Fixes an issue in the item state where the "base" value showed the literal base value for the attribute, regardless of override / mutators
* If there is an override and a mutated attribute, mutated value takes effect
This commit is contained in:
blitzmann
2018-05-24 01:26:49 -04:00
parent 33d4a8a691
commit fabf759aa7
8 changed files with 132 additions and 9 deletions

View File

@@ -77,7 +77,7 @@ sd_lock = threading.RLock()
from eos.db.gamedata import alphaClones, attribute, category, effect, group, icon, item, marketGroup, metaData, metaGroup, queries, traits, unit
# noinspection PyPep8
from eos.db.saveddata import booster, cargo, character, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, loadDefaultDatabaseValues, \
miscData, module, override, price, queries, skill, targetResists, user
miscData, mutator, module, override, price, queries, skill, targetResists, user
# Import queries
# noinspection PyPep8

View File

@@ -1,6 +1,7 @@
__all__ = [
"character",
"fit",
"mutator",
"module",
"user",
"skill",

View File

@@ -23,6 +23,7 @@ import datetime
from eos.db import saveddata_meta
from eos.saveddata.module import Module
from eos.saveddata.mutator import Mutator
from eos.saveddata.fit import Fit
modules_table = Table("modules", saveddata_meta,
@@ -39,4 +40,11 @@ modules_table = Table("modules", saveddata_meta,
CheckConstraint('("dummySlot" = NULL OR "itemID" = NULL) AND "dummySlot" != "itemID"'))
mapper(Module, modules_table,
properties={"owner": relation(Fit)})
properties={
"owner": relation(Fit),
"mutators": relation(
Mutator,
backref="module",
cascade="all,delete-orphan"
)
})

View File

@@ -0,0 +1,35 @@
# ===============================================================================
# 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 sqlalchemy import Table, Column, Integer, ForeignKey, Boolean, DateTime, Float
from sqlalchemy.orm import mapper
import datetime
from eos.db import saveddata_meta
from eos.saveddata.mutator import Mutator
mutator_table = Table("mutators", saveddata_meta,
Column("moduleID", Integer, ForeignKey("modules.ID"), nullable=False, index=True),
Column("attrID", Integer, primary_key=True, index=True),
Column("value", Float, nullable=False),
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
mapper(Mutator, mutator_table)

View File

@@ -33,6 +33,14 @@ class ItemAttrShortcut(object):
return return_value or default
def getBaseAttrValue(self, key, default=0):
'''
Gets base value in this order:
Mutated value > override value > attribute value
'''
return_value = self.itemModifiedAttributes.getOriginal(key)
return return_value or default
class ChargeAttrShortcut(object):
def getModifiedChargeAttr(self, key, default=0):
@@ -59,8 +67,10 @@ class ModifiedAttributeDict(collections.MutableMapping):
self.__modified = {}
# Affected by entities
self.__affectedBy = {}
# Overrides
# Overrides (per item)
self.__overrides = {}
# Mutators (per module)
self.__mutators = {}
# Dictionaries for various value modification types
self.__forced = {}
self.__preAssigns = {}
@@ -100,6 +110,14 @@ class ModifiedAttributeDict(collections.MutableMapping):
def overrides(self, val):
self.__overrides = val
@property
def mutators(self):
return {x.attr.name: x for x in self.__mutators}
@mutators.setter
def mutators(self, val):
self.__mutators = val
def __getitem__(self, key):
# Check if we have final calculated value
key_value = self.__modified.get(key)
@@ -128,14 +146,16 @@ class ModifiedAttributeDict(collections.MutableMapping):
del self.__intermediary[key]
def getOriginal(self, key, default=None):
val = None
if self.overrides_enabled and self.overrides:
val = self.overrides.get(key, None)
else:
val = None
val = self.overrides.get(key, val)
# mutators are overriden by overrides. x_x
val = self.mutators.get(key, val)
if val is None:
if self.original:
val = self.original.get(key, None)
val = self.original.get(key, val)
if val is None and val != default:
val = default

View File

@@ -109,7 +109,6 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
self.__charge = eos.db.getItem(self.chargeID)
self.build()
def build(self):
""" Builds internal module variables from both init's """
@@ -129,6 +128,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if self.__item:
self.__itemModifiedAttributes.original = self.__item.attributes
self.__itemModifiedAttributes.mutators = self.mutators
self.__itemModifiedAttributes.overrides = self.__item.overrides
self.__hardpoint = self.__calculateHardpoint(self.__item)
self.__slot = self.__calculateSlot(self.__item)

54
eos/saveddata/mutator.py Normal file
View File

@@ -0,0 +1,54 @@
# ===============================================================================
# Copyright (C) 2015 Ryan Holmes
#
# 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
import eos.db
from eos.eqBase import EqBase
pyfalog = Logger(__name__)
class Mutator(EqBase):
def __init__(self, stuff, attr, value):
self.moduleID = stuff.ID
self.attrID = attr.ID
self.__attr = attr
self.value = value
@reconstructor
def init(self):
self.__attr = None
self.__item = None
if self.attrID:
self.__attr = eos.db.getAttributeInfo(self.attrID)
if self.__attr is None:
pyfalog.error("Attribute (id: {0}) does not exist", self.attrID)
return
@property
def attr(self):
return self.__attr
@property
def item(self):
return self.__item

View File

@@ -174,7 +174,12 @@ class ItemParams(wx.Panel):
info = self.attrInfo.get(name)
att = self.attrValues[name]
valDefault = getattr(info, "value", None)
# If we're working with a stuff object, we should get the original value from our getBaseAttrValue function,
# which will return the value with respect to the effective base (with mutators / overrides in place)
valDefault = getattr(info, "value", None) # Get default value from attribute
if self.stuff is not None:
# if it's a stuff, overwrite default (with fallback to current value)
valDefault = self.stuff.getBaseAttrValue(name, valDefault)
valueDefault = valDefault if valDefault is not None else att
val = getattr(att, "value", None)