Implement drone mutation support with some exceptions
This commit is contained in:
@@ -118,7 +118,7 @@ from eos.db.gamedata import alphaClones, attribute, category, effect, group, ite
|
||||
pyfalog.debug('Importing saveddata DB scheme')
|
||||
# noinspection PyPep8
|
||||
from eos.db.saveddata import booster, cargo, character, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, \
|
||||
miscData, mutator, module, override, price, queries, skill, targetProfile, user
|
||||
miscData, mutatorMod, mutatorDrone, module, override, price, queries, skill, targetProfile, user
|
||||
|
||||
pyfalog.debug('Importing gamedata queries')
|
||||
# noinspection PyPep8
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Boolean, Column, Float, ForeignKey, Integer, String, Table
|
||||
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, Table
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import backref, deferred, mapper, relation, synonym
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
|
||||
18
eos/db/migrations/upgrade45.py
Normal file
18
eos/db/migrations/upgrade45.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""
|
||||
Migration 45
|
||||
|
||||
- Drone mutaplasmid support
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
try:
|
||||
saveddata_engine.execute("SELECT baseItemID FROM drones LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE drones ADD COLUMN baseItemID INTEGER;")
|
||||
try:
|
||||
saveddata_engine.execute("SELECT mutaplasmidID FROM drones LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE drones ADD COLUMN mutaplasmidID INTEGER;")
|
||||
@@ -1,7 +1,8 @@
|
||||
__all__ = [
|
||||
"character",
|
||||
"fit",
|
||||
"mutator",
|
||||
"mutatorMod",
|
||||
"mutatorDrone",
|
||||
"module",
|
||||
"user",
|
||||
"skill",
|
||||
|
||||
@@ -18,27 +18,35 @@
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, Float, ForeignKey, Boolean, DateTime
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
from sqlalchemy.orm import mapper, relation, synonym
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
import datetime
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.drone import Drone
|
||||
from eos.saveddata.fit import Fit
|
||||
from eos.saveddata.mutator import MutatorDrone
|
||||
|
||||
drones_table = Table("drones", saveddata_meta,
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
|
||||
Column("itemID", Integer, nullable=False),
|
||||
Column("baseItemID", Integer, nullable=True),
|
||||
Column("mutaplasmidID", Integer, nullable=True),
|
||||
Column("amount", Integer, nullable=False),
|
||||
Column("amountActive", Integer, nullable=False),
|
||||
Column("projected", Boolean, default=False),
|
||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
|
||||
Column("projectionRange", Float, nullable=True)
|
||||
)
|
||||
Column("projectionRange", Float, nullable=True))
|
||||
|
||||
|
||||
mapper(Drone, drones_table,
|
||||
properties={
|
||||
"owner": relation(Fit)
|
||||
}
|
||||
)
|
||||
"ID": synonym("groupID"),
|
||||
"owner": relation(Fit),
|
||||
"mutators": relation(
|
||||
MutatorDrone,
|
||||
backref="item",
|
||||
cascade="all,delete-orphan",
|
||||
collection_class=attribute_mapped_collection('attrID'))})
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, Float, ForeignKey, CheckConstraint, Boolean, DateTime
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
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
|
||||
from eos.saveddata.mutator import MutatorModule
|
||||
|
||||
modules_table = Table("modules", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
@@ -45,13 +45,12 @@ modules_table = Table("modules", saveddata_meta,
|
||||
Column("projectionRange", Float, nullable=True),
|
||||
CheckConstraint('("dummySlot" = NULL OR "itemID" = NULL) AND "dummySlot" != "itemID"'))
|
||||
|
||||
|
||||
mapper(Module, modules_table,
|
||||
properties={
|
||||
"owner": relation(Fit),
|
||||
"mutators": relation(
|
||||
Mutator,
|
||||
backref="module",
|
||||
MutatorModule,
|
||||
backref="item",
|
||||
cascade="all,delete-orphan",
|
||||
collection_class=attribute_mapped_collection('attrID')
|
||||
)
|
||||
})
|
||||
collection_class=attribute_mapped_collection('attrID'))})
|
||||
|
||||
@@ -23,13 +23,14 @@ from sqlalchemy import Column, DateTime, Float, ForeignKey, Integer, Table
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.mutator import Mutator
|
||||
from eos.saveddata.mutator import MutatorDrone
|
||||
|
||||
mutator_table = Table("mutators", saveddata_meta,
|
||||
Column("moduleID", Integer, ForeignKey("modules.ID"), primary_key=True, 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))
|
||||
mutatorDrones_table = Table(
|
||||
"mutatorsDrones", saveddata_meta,
|
||||
Column("groupID", Integer, ForeignKey("drones.groupID"), primary_key=True, 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)
|
||||
mapper(MutatorDrone, mutatorDrones_table)
|
||||
36
eos/db/saveddata/mutatorMod.py
Normal file
36
eos/db/saveddata/mutatorMod.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# ===============================================================================
|
||||
# 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/>.
|
||||
# ===============================================================================
|
||||
|
||||
import datetime
|
||||
|
||||
from sqlalchemy import Column, DateTime, Float, ForeignKey, Integer, Table
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.mutator import MutatorModule
|
||||
|
||||
mutatorMods_table = Table(
|
||||
"mutators", saveddata_meta,
|
||||
Column("moduleID", Integer, ForeignKey("modules.ID"), primary_key=True, 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(MutatorModule, mutatorMods_table)
|
||||
@@ -25,6 +25,8 @@ from sqlalchemy.orm import reconstructor, validates
|
||||
import eos.db
|
||||
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
||||
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
||||
from eos.saveddata.mutatedMixin import MutatedMixin, MutaError
|
||||
from eos.saveddata.mutator import MutatorDrone
|
||||
from eos.utils.cycles import CycleInfo
|
||||
from eos.utils.default import DEFAULT
|
||||
from eos.utils.stats import DmgTypes, RRTypes
|
||||
@@ -33,12 +35,13 @@ from eos.utils.stats import DmgTypes, RRTypes
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, MutatedMixin):
|
||||
MINING_ATTRIBUTES = ("miningAmount",)
|
||||
|
||||
def __init__(self, item):
|
||||
def __init__(self, item, baseItem=None, mutaplasmid=None):
|
||||
"""Initialize a drone from the program"""
|
||||
self.__item = item
|
||||
self._item = item
|
||||
self._mutaInit(baseItem=baseItem, mutaplasmid=mutaplasmid)
|
||||
|
||||
if self.isInvalid:
|
||||
raise ValueError("Passed item is not a Drone")
|
||||
@@ -53,14 +56,19 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
@reconstructor
|
||||
def init(self):
|
||||
"""Initialize a drone from the database and validate"""
|
||||
self.__item = None
|
||||
self._item = None
|
||||
|
||||
if self.itemID:
|
||||
self.__item = eos.db.getItem(self.itemID)
|
||||
if self.__item is None:
|
||||
self._item = eos.db.getItem(self.itemID)
|
||||
if self._item is None:
|
||||
pyfalog.error("Item (id: {0}) does not exist", self.itemID)
|
||||
return
|
||||
|
||||
try:
|
||||
self._mutaReconstruct()
|
||||
except MutaError:
|
||||
return
|
||||
|
||||
if self.isInvalid:
|
||||
pyfalog.error("Item (id: {0}) is not a Drone", self.itemID)
|
||||
return
|
||||
@@ -74,10 +82,13 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
self.__baseRRAmount = None
|
||||
self.__miningyield = None
|
||||
self.__itemModifiedAttributes = ModifiedAttributeDict()
|
||||
self.__itemModifiedAttributes.original = self.__item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self.__item.overrides
|
||||
|
||||
self.__itemModifiedAttributes.original = self._item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self._item.overrides
|
||||
self.__chargeModifiedAttributes = ModifiedAttributeDict()
|
||||
|
||||
self._mutaLoadMutators(mutatorClass=MutatorDrone)
|
||||
self.__itemModifiedAttributes.mutators = self.mutators
|
||||
|
||||
# pheonix todo: check the attribute itself, not the modified. this will always return 0 now.
|
||||
chargeID = self.getModifiedItemAttr("entityMissileTypeID", None)
|
||||
if chargeID is not None:
|
||||
@@ -96,11 +107,17 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
|
||||
@property
|
||||
def isInvalid(self):
|
||||
return self.__item is None or self.__item.category.name != "Drone"
|
||||
if self._item is None:
|
||||
return True
|
||||
if self._item.category.name != "Drone":
|
||||
return True
|
||||
if self._mutaIsInvalid:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def item(self):
|
||||
return self.__item
|
||||
return self._item
|
||||
|
||||
@property
|
||||
def charge(self):
|
||||
@@ -337,10 +354,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
effect.handler(fit, self, ("droneCharge",), projectionRange, effect=effect)
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
copy = Drone(self.item)
|
||||
copy = Drone(self.item, self.baseItem, self.mutaplasmid)
|
||||
copy.amount = self.amount
|
||||
copy.amountActive = self.amountActive
|
||||
copy.projectionRange = self.projectionRange
|
||||
self._mutaApplyMutators(mutatorClass=MutatorDrone, targetInstance=copy)
|
||||
return copy
|
||||
|
||||
def rebase(self, item):
|
||||
@@ -348,10 +366,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
amountActive = self.amountActive
|
||||
projectionRange = self.projectionRange
|
||||
|
||||
Drone.__init__(self, item)
|
||||
Drone.__init__(self, item, self.baseItem, self.mutaplasmid)
|
||||
self.amount = amount
|
||||
self.amountActive = amountActive
|
||||
self.projectionRange = projectionRange
|
||||
self._mutaApplyMutators(mutatorClass=MutatorDrone)
|
||||
|
||||
def fits(self, fit):
|
||||
fitDroneGroupLimits = set()
|
||||
|
||||
@@ -27,7 +27,8 @@ from eos.const import FittingHardpoint, FittingModuleState, FittingSlot
|
||||
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
||||
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
||||
from eos.saveddata.citadel import Citadel
|
||||
from eos.saveddata.mutator import Mutator
|
||||
from eos.saveddata.mutatedMixin import MutatedMixin, MutaError
|
||||
from eos.saveddata.mutator import MutatorModule
|
||||
from eos.utils.cycles import CycleInfo, CycleSequence
|
||||
from eos.utils.default import DEFAULT
|
||||
from eos.utils.float import floatUnerr
|
||||
@@ -61,7 +62,7 @@ ProjectedSystem = {
|
||||
}
|
||||
|
||||
|
||||
class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, MutatedMixin):
|
||||
"""An instance of this class represents a module together with its charge and modified attributes"""
|
||||
MINING_ATTRIBUTES = ("miningAmount",)
|
||||
SYSTEM_GROUPS = (
|
||||
@@ -72,21 +73,9 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
"""Initialize a module from the program"""
|
||||
|
||||
self.itemID = item.ID if item is not None else None
|
||||
self.baseItemID = baseItem.ID if baseItem is not None else None
|
||||
self.mutaplasmidID = mutaplasmid.ID if mutaplasmid is not None else None
|
||||
|
||||
if baseItem is not None:
|
||||
# we're working with a mutated module, need to get abyssal module loaded with the base attributes
|
||||
# Note: there may be a better way of doing this, such as a metho on this classe to convert(mutaplamid). This
|
||||
# will require a bit more research though, considering there has never been a need to "swap" out the item of a Module
|
||||
# before, and there may be assumptions taken with regards to the item never changing (pre-calculated / cached results, for example)
|
||||
self.__item = eos.db.getItemWithBaseItemAttribute(self.itemID, self.baseItemID)
|
||||
self.__baseItem = baseItem
|
||||
self.__mutaplasmid = mutaplasmid
|
||||
else:
|
||||
self.__item = item
|
||||
self.__baseItem = baseItem
|
||||
self.__mutaplasmid = mutaplasmid
|
||||
self._item = item
|
||||
self._mutaInit(baseItem=baseItem, mutaplasmid=mutaplasmid)
|
||||
|
||||
if item is not None and self.isInvalid:
|
||||
raise ValueError("Passed item is not a Module")
|
||||
@@ -101,27 +90,22 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
@reconstructor
|
||||
def init(self):
|
||||
"""Initialize a module from the database and validate"""
|
||||
self.__item = None
|
||||
self.__baseItem = None
|
||||
self._item = None
|
||||
self.__charge = None
|
||||
self.__mutaplasmid = None
|
||||
|
||||
# we need this early if module is invalid and returns early
|
||||
self.__slot = self.dummySlot
|
||||
|
||||
if self.itemID:
|
||||
self.__item = eos.db.getItem(self.itemID)
|
||||
if self.__item is None:
|
||||
self._item = eos.db.getItem(self.itemID)
|
||||
if self._item is None:
|
||||
pyfalog.error("Item (id: {0}) does not exist", self.itemID)
|
||||
return
|
||||
|
||||
if self.baseItemID:
|
||||
self.__item = eos.db.getItemWithBaseItemAttribute(self.itemID, self.baseItemID)
|
||||
self.__baseItem = eos.db.getItem(self.baseItemID)
|
||||
self.__mutaplasmid = eos.db.getMutaplasmid(self.mutaplasmidID)
|
||||
if self.__baseItem is None:
|
||||
pyfalog.error("Base Item (id: {0}) does not exist", self.itemID)
|
||||
return
|
||||
try:
|
||||
self._mutaReconstruct()
|
||||
except MutaError:
|
||||
return
|
||||
|
||||
if self.isInvalid:
|
||||
pyfalog.error("Item (id: {0}) is not a Module", self.itemID)
|
||||
@@ -149,21 +133,13 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
self.__chargeModifiedAttributes = ModifiedAttributeDict(parent=self)
|
||||
self.__slot = self.dummySlot # defaults to None
|
||||
|
||||
if self.__item:
|
||||
self.__itemModifiedAttributes.original = self.__item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self.__item.overrides
|
||||
self.__hardpoint = self.__calculateHardpoint(self.__item)
|
||||
self.__slot = self.calculateSlot(self.__item)
|
||||
|
||||
# Instantiate / remove mutators if this is a mutated module
|
||||
if self.__baseItem:
|
||||
for x in self.mutaplasmid.attributes:
|
||||
attr = self.item.attributes[x.name]
|
||||
id = attr.ID
|
||||
if id not in self.mutators: # create the mutator
|
||||
Mutator(self, attr, attr.value)
|
||||
# @todo: remove attributes that are no longer part of the mutaplasmid.
|
||||
if self._item:
|
||||
self.__itemModifiedAttributes.original = self._item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self._item.overrides
|
||||
self.__hardpoint = self.__calculateHardpoint(self._item)
|
||||
self.__slot = self.calculateSlot(self._item)
|
||||
|
||||
self._mutaLoadMutators(mutatorClass=MutatorModule)
|
||||
self.__itemModifiedAttributes.mutators = self.mutators
|
||||
|
||||
if self.__charge:
|
||||
@@ -198,28 +174,22 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
# todo: validate baseItem as well if it's set.
|
||||
if self.isEmpty:
|
||||
return False
|
||||
if self.__item is None:
|
||||
if self._item is None:
|
||||
return True
|
||||
if (
|
||||
self.__item.category.name not in ("Module", "Subsystem", "Structure Module")
|
||||
and self.__item.group.name not in self.SYSTEM_GROUPS
|
||||
self._item.category.name not in ("Module", "Subsystem", "Structure Module")
|
||||
and self._item.group.name not in self.SYSTEM_GROUPS
|
||||
):
|
||||
return True
|
||||
if (
|
||||
self.__item.category.name == "Structure Module"
|
||||
and self.__item.group.name == "Quantum Cores"
|
||||
self._item.category.name == "Structure Module"
|
||||
and self._item.group.name == "Quantum Cores"
|
||||
):
|
||||
return True
|
||||
if self.item.isAbyssal and not self.isMutated:
|
||||
return True
|
||||
if self.isMutated and not self.__mutaplasmid:
|
||||
if self._mutaIsInvalid:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def isMutated(self):
|
||||
return self.baseItemID and self.mutaplasmidID
|
||||
|
||||
@property
|
||||
def numCharges(self):
|
||||
return self.getNumCharges(self.charge)
|
||||
@@ -419,15 +389,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
|
||||
@property
|
||||
def item(self):
|
||||
return self.__item if self.__item != 0 else None
|
||||
|
||||
@property
|
||||
def baseItem(self):
|
||||
return self.__baseItem
|
||||
|
||||
@property
|
||||
def mutaplasmid(self):
|
||||
return self.__mutaplasmid
|
||||
return self._item if self._item != 0 else None
|
||||
|
||||
@property
|
||||
def charge(self):
|
||||
@@ -1098,9 +1060,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
copy.spoolType = self.spoolType
|
||||
copy.spoolAmount = self.spoolAmount
|
||||
copy.projectionRange = self.projectionRange
|
||||
|
||||
for x in self.mutators.values():
|
||||
Mutator(copy, x.attribute, x.value)
|
||||
self._mutaApplyMutators(mutatorClass=MutatorModule, targetInstance=copy)
|
||||
|
||||
return copy
|
||||
|
||||
@@ -1118,14 +1078,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
self.spoolType = spoolType
|
||||
self.spoolAmount = spoolAmount
|
||||
self.projectionRange = projectionRange
|
||||
for x in self.mutators.values():
|
||||
Mutator(self, x.attribute, x.value)
|
||||
self._mutaApplyMutators(mutatorClass=MutatorModule)
|
||||
|
||||
def __repr__(self):
|
||||
if self.item:
|
||||
return "Module(ID={}, name={}) at {}".format(
|
||||
self.item.ID, self.item.name, hex(id(self))
|
||||
)
|
||||
return "Module(ID={}, name={}) at {}".format(self.item.ID, self.item.name, hex(id(self)))
|
||||
else:
|
||||
return "EmptyModule() at {}".format(hex(id(self)))
|
||||
|
||||
|
||||
96
eos/saveddata/mutatedMixin.py
Normal file
96
eos/saveddata/mutatedMixin.py
Normal file
@@ -0,0 +1,96 @@
|
||||
# ===============================================================================
|
||||
# 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/>.
|
||||
# ===============================================================================
|
||||
|
||||
|
||||
import eos.db
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class MutaError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class MutatedMixin:
|
||||
|
||||
@property
|
||||
def isMutated(self):
|
||||
return self.baseItemID and self.mutaplasmidID
|
||||
|
||||
@property
|
||||
def baseItem(self):
|
||||
return self.__baseItem
|
||||
|
||||
@property
|
||||
def mutaplasmid(self):
|
||||
return self.__mutaplasmid
|
||||
|
||||
def _mutaInit(self, baseItem, mutaplasmid):
|
||||
self.baseItemID = baseItem.ID if baseItem is not None else None
|
||||
self.mutaplasmidID = mutaplasmid.ID if mutaplasmid is not None else None
|
||||
if baseItem is not None:
|
||||
# we're working with a mutated module, need to get abyssal module loaded with the base attributes
|
||||
# Note: there may be a better way of doing this, such as a metho on this classe to convert(mutaplamid). This
|
||||
# will require a bit more research though, considering there has never been a need to "swap" out the item of a Module
|
||||
# before, and there may be assumptions taken with regards to the item never changing (pre-calculated / cached results, for example)
|
||||
print('muta init', self, self._item.ID, self.baseItemID)
|
||||
self._item = eos.db.getItemWithBaseItemAttribute(self._item.ID, self.baseItemID)
|
||||
self.__baseItem = baseItem
|
||||
self.__mutaplasmid = mutaplasmid
|
||||
else:
|
||||
self.__baseItem = None
|
||||
self.__mutaplasmid = None
|
||||
|
||||
def _mutaReconstruct(self):
|
||||
self.__baseItem = None
|
||||
self.__mutaplasmid = None
|
||||
if self.baseItemID:
|
||||
self._item = eos.db.getItemWithBaseItemAttribute(self.itemID, self.baseItemID)
|
||||
self.__baseItem = eos.db.getItem(self.baseItemID)
|
||||
self.__mutaplasmid = eos.db.getMutaplasmid(self.mutaplasmidID)
|
||||
if self.__baseItem is None:
|
||||
pyfalog.error("Base Item (id: {0}) does not exist", self.itemID)
|
||||
raise MutaError
|
||||
|
||||
def _mutaLoadMutators(self, mutatorClass):
|
||||
# Instantiate / remove mutators if this is a mutated module
|
||||
if self.__baseItem:
|
||||
for x in self.mutaplasmid.attributes:
|
||||
attr = self.item.attributes[x.name]
|
||||
id = attr.ID
|
||||
if id not in self.mutators: # create the mutator
|
||||
mutatorClass(self, attr, attr.value)
|
||||
# @todo: remove attributes that are no longer part of the mutaplasmid.
|
||||
|
||||
@property
|
||||
def _mutaIsInvalid(self):
|
||||
if self.item.isAbyssal and not self.isMutated:
|
||||
return True
|
||||
if self.isMutated and not self.__mutaplasmid:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _mutaApplyMutators(self, mutatorClass, targetInstance=None):
|
||||
if targetInstance is None:
|
||||
targetInstance = self
|
||||
for x in self.mutators.values():
|
||||
mutatorClass(targetInstance, x.attribute, x.value)
|
||||
@@ -27,10 +27,10 @@ from eos.eqBase import EqBase
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class Mutator(EqBase):
|
||||
""" Mutators are the object that represent an attribute override on the module level, in conjunction with
|
||||
mutaplasmids. Each mutated module, when created, is instantiated with a list of these objects, dictated by the
|
||||
mutaplasmid that is used on the base module.
|
||||
class MutatorBase(EqBase):
|
||||
""" Mutators are the object that represent an attribute override on the eos item level, in conjunction with
|
||||
mutaplasmids. Each mutated item, when created, is instantiated with a list of these objects, dictated by the
|
||||
mutaplasmid that is used on the base item.
|
||||
|
||||
A note on the different attributes on this object:
|
||||
* attribute: points to the definition of the attribute from dgmattribs.
|
||||
@@ -40,13 +40,13 @@ class Mutator(EqBase):
|
||||
This could probably be cleaned up with smarter relationships, but whatever
|
||||
"""
|
||||
|
||||
def __init__(self, module, attr, value):
|
||||
# this needs to be above module assignment, as assigning the module will add it to the list and it via
|
||||
def __init__(self, item, attr, value):
|
||||
# this needs to be above item assignment, as assigning the item will add it to the list and it via
|
||||
# relationship and needs this set 4correctly
|
||||
self.attrID = attr.ID
|
||||
|
||||
self.module = module
|
||||
self.moduleID = module.ID
|
||||
self.item = item
|
||||
self.itemID = item.ID
|
||||
|
||||
self.__attr = attr
|
||||
self.build()
|
||||
@@ -67,20 +67,20 @@ class Mutator(EqBase):
|
||||
|
||||
def build(self):
|
||||
# try...except here to catch orphaned mutators. Pretty rare, only happens so far if hacking the database
|
||||
# But put it here to remove the module link if it happens, until a better solution can be developed
|
||||
# But put it here to remove the eos item link if it happens, until a better solution can be developed
|
||||
try:
|
||||
# dynamic attribute links to the Mutaplasmids attribute definition for this mutated definition
|
||||
self.dynamicAttribute = next(a for a in self.module.mutaplasmid.attributes if a.attributeID == self.attrID)
|
||||
self.dynamicAttribute = next(a for a in self.item.mutaplasmid.attributes if a.attributeID == self.attrID)
|
||||
# base attribute links to the base ite's attribute for this mutated definition (contains original, base value)
|
||||
self.baseAttribute = self.module.item.attributes[self.dynamicAttribute.name]
|
||||
self.baseAttribute = self.item.item.attributes[self.dynamicAttribute.name]
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
self.module = None
|
||||
self.item = None
|
||||
|
||||
@validates("value")
|
||||
def validator(self, key, val):
|
||||
""" Validates values as properly falling within the range of the modules' Mutaplasmid """
|
||||
""" Validates values as properly falling within the range of the items' Mutaplasmid """
|
||||
if self.baseValue == 0:
|
||||
return 0
|
||||
mod = val / self.baseValue
|
||||
@@ -99,7 +99,7 @@ class Mutator(EqBase):
|
||||
# @todo: need to test what happens:
|
||||
# 1) if an attribute is removed from the EVE database
|
||||
# 2) if a mutaplasmid does not have the attribute anymore
|
||||
# 3) if a mutaplasmid does not exist (in eve or on the module's item)
|
||||
# 3) if a mutaplasmid does not exist (in eve or on the pyfa item's item)
|
||||
# Can remove invalid ones in a SQLAlchemy collection class... eventually
|
||||
return self.__attr is None
|
||||
|
||||
@@ -139,3 +139,11 @@ class Mutator(EqBase):
|
||||
@property
|
||||
def attribute(self):
|
||||
return self.__attr
|
||||
|
||||
|
||||
class MutatorModule(MutatorBase):
|
||||
pass
|
||||
|
||||
|
||||
class MutatorDrone(MutatorBase):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user