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')
|
pyfalog.debug('Importing saveddata DB scheme')
|
||||||
# noinspection PyPep8
|
# noinspection PyPep8
|
||||||
from eos.db.saveddata import booster, cargo, character, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, \
|
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')
|
pyfalog.debug('Importing gamedata queries')
|
||||||
# noinspection PyPep8
|
# noinspection PyPep8
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
# 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.ext.associationproxy import association_proxy
|
||||||
from sqlalchemy.orm import backref, deferred, mapper, relation, synonym
|
from sqlalchemy.orm import backref, deferred, mapper, relation, synonym
|
||||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
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__ = [
|
__all__ = [
|
||||||
"character",
|
"character",
|
||||||
"fit",
|
"fit",
|
||||||
"mutator",
|
"mutatorMod",
|
||||||
|
"mutatorDrone",
|
||||||
"module",
|
"module",
|
||||||
"user",
|
"user",
|
||||||
"skill",
|
"skill",
|
||||||
|
|||||||
@@ -18,27 +18,35 @@
|
|||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
|
|
||||||
from sqlalchemy import Table, Column, Integer, Float, ForeignKey, Boolean, DateTime
|
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
|
import datetime
|
||||||
|
|
||||||
from eos.db import saveddata_meta
|
from eos.db import saveddata_meta
|
||||||
from eos.saveddata.drone import Drone
|
from eos.saveddata.drone import Drone
|
||||||
from eos.saveddata.fit import Fit
|
from eos.saveddata.fit import Fit
|
||||||
|
from eos.saveddata.mutator import MutatorDrone
|
||||||
|
|
||||||
drones_table = Table("drones", saveddata_meta,
|
drones_table = Table("drones", saveddata_meta,
|
||||||
Column("groupID", Integer, primary_key=True),
|
Column("groupID", Integer, primary_key=True),
|
||||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
|
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
|
||||||
Column("itemID", Integer, nullable=False),
|
Column("itemID", Integer, nullable=False),
|
||||||
|
Column("baseItemID", Integer, nullable=True),
|
||||||
|
Column("mutaplasmidID", Integer, nullable=True),
|
||||||
Column("amount", Integer, nullable=False),
|
Column("amount", Integer, nullable=False),
|
||||||
Column("amountActive", Integer, nullable=False),
|
Column("amountActive", Integer, nullable=False),
|
||||||
Column("projected", Boolean, default=False),
|
Column("projected", Boolean, default=False),
|
||||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
||||||
Column("modified", DateTime, nullable=True, onupdate=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,
|
mapper(Drone, drones_table,
|
||||||
properties={
|
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 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 import relation, mapper
|
||||||
|
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from eos.db import saveddata_meta
|
from eos.db import saveddata_meta
|
||||||
from eos.saveddata.module import Module
|
from eos.saveddata.module import Module
|
||||||
from eos.saveddata.mutator import Mutator
|
|
||||||
from eos.saveddata.fit import Fit
|
from eos.saveddata.fit import Fit
|
||||||
|
from eos.saveddata.mutator import MutatorModule
|
||||||
|
|
||||||
modules_table = Table("modules", saveddata_meta,
|
modules_table = Table("modules", saveddata_meta,
|
||||||
Column("ID", Integer, primary_key=True),
|
Column("ID", Integer, primary_key=True),
|
||||||
@@ -45,13 +45,12 @@ modules_table = Table("modules", saveddata_meta,
|
|||||||
Column("projectionRange", Float, nullable=True),
|
Column("projectionRange", Float, nullable=True),
|
||||||
CheckConstraint('("dummySlot" = NULL OR "itemID" = NULL) AND "dummySlot" != "itemID"'))
|
CheckConstraint('("dummySlot" = NULL OR "itemID" = NULL) AND "dummySlot" != "itemID"'))
|
||||||
|
|
||||||
|
|
||||||
mapper(Module, modules_table,
|
mapper(Module, modules_table,
|
||||||
properties={
|
properties={
|
||||||
"owner": relation(Fit),
|
"owner": relation(Fit),
|
||||||
"mutators": relation(
|
"mutators": relation(
|
||||||
Mutator,
|
MutatorModule,
|
||||||
backref="module",
|
backref="item",
|
||||||
cascade="all,delete-orphan",
|
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 sqlalchemy.orm import mapper
|
||||||
|
|
||||||
from eos.db import saveddata_meta
|
from eos.db import saveddata_meta
|
||||||
from eos.saveddata.mutator import Mutator
|
from eos.saveddata.mutator import MutatorDrone
|
||||||
|
|
||||||
mutator_table = Table("mutators", saveddata_meta,
|
mutatorDrones_table = Table(
|
||||||
Column("moduleID", Integer, ForeignKey("modules.ID"), primary_key=True, index=True),
|
"mutatorsDrones", saveddata_meta,
|
||||||
Column("attrID", Integer, primary_key=True, index=True),
|
Column("groupID", Integer, ForeignKey("drones.groupID"), primary_key=True, index=True),
|
||||||
Column("value", Float, nullable=False),
|
Column("attrID", Integer, primary_key=True, index=True),
|
||||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
Column("value", Float, nullable=False),
|
||||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
|
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
|
import eos.db
|
||||||
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
||||||
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
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.cycles import CycleInfo
|
||||||
from eos.utils.default import DEFAULT
|
from eos.utils.default import DEFAULT
|
||||||
from eos.utils.stats import DmgTypes, RRTypes
|
from eos.utils.stats import DmgTypes, RRTypes
|
||||||
@@ -33,12 +35,13 @@ from eos.utils.stats import DmgTypes, RRTypes
|
|||||||
pyfalog = Logger(__name__)
|
pyfalog = Logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, MutatedMixin):
|
||||||
MINING_ATTRIBUTES = ("miningAmount",)
|
MINING_ATTRIBUTES = ("miningAmount",)
|
||||||
|
|
||||||
def __init__(self, item):
|
def __init__(self, item, baseItem=None, mutaplasmid=None):
|
||||||
"""Initialize a drone from the program"""
|
"""Initialize a drone from the program"""
|
||||||
self.__item = item
|
self._item = item
|
||||||
|
self._mutaInit(baseItem=baseItem, mutaplasmid=mutaplasmid)
|
||||||
|
|
||||||
if self.isInvalid:
|
if self.isInvalid:
|
||||||
raise ValueError("Passed item is not a Drone")
|
raise ValueError("Passed item is not a Drone")
|
||||||
@@ -53,14 +56,19 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
@reconstructor
|
@reconstructor
|
||||||
def init(self):
|
def init(self):
|
||||||
"""Initialize a drone from the database and validate"""
|
"""Initialize a drone from the database and validate"""
|
||||||
self.__item = None
|
self._item = None
|
||||||
|
|
||||||
if self.itemID:
|
if self.itemID:
|
||||||
self.__item = eos.db.getItem(self.itemID)
|
self._item = eos.db.getItem(self.itemID)
|
||||||
if self.__item is None:
|
if self._item is None:
|
||||||
pyfalog.error("Item (id: {0}) does not exist", self.itemID)
|
pyfalog.error("Item (id: {0}) does not exist", self.itemID)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._mutaReconstruct()
|
||||||
|
except MutaError:
|
||||||
|
return
|
||||||
|
|
||||||
if self.isInvalid:
|
if self.isInvalid:
|
||||||
pyfalog.error("Item (id: {0}) is not a Drone", self.itemID)
|
pyfalog.error("Item (id: {0}) is not a Drone", self.itemID)
|
||||||
return
|
return
|
||||||
@@ -74,10 +82,13 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
self.__baseRRAmount = None
|
self.__baseRRAmount = None
|
||||||
self.__miningyield = None
|
self.__miningyield = None
|
||||||
self.__itemModifiedAttributes = ModifiedAttributeDict()
|
self.__itemModifiedAttributes = ModifiedAttributeDict()
|
||||||
self.__itemModifiedAttributes.original = self.__item.attributes
|
self.__itemModifiedAttributes.original = self._item.attributes
|
||||||
self.__itemModifiedAttributes.overrides = self.__item.overrides
|
self.__itemModifiedAttributes.overrides = self._item.overrides
|
||||||
|
|
||||||
self.__chargeModifiedAttributes = ModifiedAttributeDict()
|
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.
|
# pheonix todo: check the attribute itself, not the modified. this will always return 0 now.
|
||||||
chargeID = self.getModifiedItemAttr("entityMissileTypeID", None)
|
chargeID = self.getModifiedItemAttr("entityMissileTypeID", None)
|
||||||
if chargeID is not None:
|
if chargeID is not None:
|
||||||
@@ -96,11 +107,17 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def isInvalid(self):
|
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
|
@property
|
||||||
def item(self):
|
def item(self):
|
||||||
return self.__item
|
return self._item
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def charge(self):
|
def charge(self):
|
||||||
@@ -337,10 +354,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
effect.handler(fit, self, ("droneCharge",), projectionRange, effect=effect)
|
effect.handler(fit, self, ("droneCharge",), projectionRange, effect=effect)
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
copy = Drone(self.item)
|
copy = Drone(self.item, self.baseItem, self.mutaplasmid)
|
||||||
copy.amount = self.amount
|
copy.amount = self.amount
|
||||||
copy.amountActive = self.amountActive
|
copy.amountActive = self.amountActive
|
||||||
copy.projectionRange = self.projectionRange
|
copy.projectionRange = self.projectionRange
|
||||||
|
self._mutaApplyMutators(mutatorClass=MutatorDrone, targetInstance=copy)
|
||||||
return copy
|
return copy
|
||||||
|
|
||||||
def rebase(self, item):
|
def rebase(self, item):
|
||||||
@@ -348,10 +366,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
amountActive = self.amountActive
|
amountActive = self.amountActive
|
||||||
projectionRange = self.projectionRange
|
projectionRange = self.projectionRange
|
||||||
|
|
||||||
Drone.__init__(self, item)
|
Drone.__init__(self, item, self.baseItem, self.mutaplasmid)
|
||||||
self.amount = amount
|
self.amount = amount
|
||||||
self.amountActive = amountActive
|
self.amountActive = amountActive
|
||||||
self.projectionRange = projectionRange
|
self.projectionRange = projectionRange
|
||||||
|
self._mutaApplyMutators(mutatorClass=MutatorDrone)
|
||||||
|
|
||||||
def fits(self, fit):
|
def fits(self, fit):
|
||||||
fitDroneGroupLimits = set()
|
fitDroneGroupLimits = set()
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ from eos.const import FittingHardpoint, FittingModuleState, FittingSlot
|
|||||||
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
||||||
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
||||||
from eos.saveddata.citadel import Citadel
|
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.cycles import CycleInfo, CycleSequence
|
||||||
from eos.utils.default import DEFAULT
|
from eos.utils.default import DEFAULT
|
||||||
from eos.utils.float import floatUnerr
|
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"""
|
"""An instance of this class represents a module together with its charge and modified attributes"""
|
||||||
MINING_ATTRIBUTES = ("miningAmount",)
|
MINING_ATTRIBUTES = ("miningAmount",)
|
||||||
SYSTEM_GROUPS = (
|
SYSTEM_GROUPS = (
|
||||||
@@ -72,21 +73,9 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
"""Initialize a module from the program"""
|
"""Initialize a module from the program"""
|
||||||
|
|
||||||
self.itemID = item.ID if item is not None else None
|
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:
|
self._item = item
|
||||||
# we're working with a mutated module, need to get abyssal module loaded with the base attributes
|
self._mutaInit(baseItem=baseItem, mutaplasmid=mutaplasmid)
|
||||||
# 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
|
|
||||||
|
|
||||||
if item is not None and self.isInvalid:
|
if item is not None and self.isInvalid:
|
||||||
raise ValueError("Passed item is not a Module")
|
raise ValueError("Passed item is not a Module")
|
||||||
@@ -101,27 +90,22 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
@reconstructor
|
@reconstructor
|
||||||
def init(self):
|
def init(self):
|
||||||
"""Initialize a module from the database and validate"""
|
"""Initialize a module from the database and validate"""
|
||||||
self.__item = None
|
self._item = None
|
||||||
self.__baseItem = None
|
|
||||||
self.__charge = None
|
self.__charge = None
|
||||||
self.__mutaplasmid = None
|
|
||||||
|
|
||||||
# we need this early if module is invalid and returns early
|
# we need this early if module is invalid and returns early
|
||||||
self.__slot = self.dummySlot
|
self.__slot = self.dummySlot
|
||||||
|
|
||||||
if self.itemID:
|
if self.itemID:
|
||||||
self.__item = eos.db.getItem(self.itemID)
|
self._item = eos.db.getItem(self.itemID)
|
||||||
if self.__item is None:
|
if self._item is None:
|
||||||
pyfalog.error("Item (id: {0}) does not exist", self.itemID)
|
pyfalog.error("Item (id: {0}) does not exist", self.itemID)
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.baseItemID:
|
try:
|
||||||
self.__item = eos.db.getItemWithBaseItemAttribute(self.itemID, self.baseItemID)
|
self._mutaReconstruct()
|
||||||
self.__baseItem = eos.db.getItem(self.baseItemID)
|
except MutaError:
|
||||||
self.__mutaplasmid = eos.db.getMutaplasmid(self.mutaplasmidID)
|
return
|
||||||
if self.__baseItem is None:
|
|
||||||
pyfalog.error("Base Item (id: {0}) does not exist", self.itemID)
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.isInvalid:
|
if self.isInvalid:
|
||||||
pyfalog.error("Item (id: {0}) is not a Module", self.itemID)
|
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.__chargeModifiedAttributes = ModifiedAttributeDict(parent=self)
|
||||||
self.__slot = self.dummySlot # defaults to None
|
self.__slot = self.dummySlot # defaults to None
|
||||||
|
|
||||||
if self.__item:
|
if self._item:
|
||||||
self.__itemModifiedAttributes.original = self.__item.attributes
|
self.__itemModifiedAttributes.original = self._item.attributes
|
||||||
self.__itemModifiedAttributes.overrides = self.__item.overrides
|
self.__itemModifiedAttributes.overrides = self._item.overrides
|
||||||
self.__hardpoint = self.__calculateHardpoint(self.__item)
|
self.__hardpoint = self.__calculateHardpoint(self._item)
|
||||||
self.__slot = self.calculateSlot(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.
|
|
||||||
|
|
||||||
|
self._mutaLoadMutators(mutatorClass=MutatorModule)
|
||||||
self.__itemModifiedAttributes.mutators = self.mutators
|
self.__itemModifiedAttributes.mutators = self.mutators
|
||||||
|
|
||||||
if self.__charge:
|
if self.__charge:
|
||||||
@@ -198,28 +174,22 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
# todo: validate baseItem as well if it's set.
|
# todo: validate baseItem as well if it's set.
|
||||||
if self.isEmpty:
|
if self.isEmpty:
|
||||||
return False
|
return False
|
||||||
if self.__item is None:
|
if self._item is None:
|
||||||
return True
|
return True
|
||||||
if (
|
if (
|
||||||
self.__item.category.name not in ("Module", "Subsystem", "Structure Module")
|
self._item.category.name not in ("Module", "Subsystem", "Structure Module")
|
||||||
and self.__item.group.name not in self.SYSTEM_GROUPS
|
and self._item.group.name not in self.SYSTEM_GROUPS
|
||||||
):
|
):
|
||||||
return True
|
return True
|
||||||
if (
|
if (
|
||||||
self.__item.category.name == "Structure Module"
|
self._item.category.name == "Structure Module"
|
||||||
and self.__item.group.name == "Quantum Cores"
|
and self._item.group.name == "Quantum Cores"
|
||||||
):
|
):
|
||||||
return True
|
return True
|
||||||
if self.item.isAbyssal and not self.isMutated:
|
if self._mutaIsInvalid:
|
||||||
return True
|
|
||||||
if self.isMutated and not self.__mutaplasmid:
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@property
|
|
||||||
def isMutated(self):
|
|
||||||
return self.baseItemID and self.mutaplasmidID
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def numCharges(self):
|
def numCharges(self):
|
||||||
return self.getNumCharges(self.charge)
|
return self.getNumCharges(self.charge)
|
||||||
@@ -419,15 +389,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def item(self):
|
def item(self):
|
||||||
return self.__item if self.__item != 0 else None
|
return self._item if self._item != 0 else None
|
||||||
|
|
||||||
@property
|
|
||||||
def baseItem(self):
|
|
||||||
return self.__baseItem
|
|
||||||
|
|
||||||
@property
|
|
||||||
def mutaplasmid(self):
|
|
||||||
return self.__mutaplasmid
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def charge(self):
|
def charge(self):
|
||||||
@@ -1098,9 +1060,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
copy.spoolType = self.spoolType
|
copy.spoolType = self.spoolType
|
||||||
copy.spoolAmount = self.spoolAmount
|
copy.spoolAmount = self.spoolAmount
|
||||||
copy.projectionRange = self.projectionRange
|
copy.projectionRange = self.projectionRange
|
||||||
|
self._mutaApplyMutators(mutatorClass=MutatorModule, targetInstance=copy)
|
||||||
for x in self.mutators.values():
|
|
||||||
Mutator(copy, x.attribute, x.value)
|
|
||||||
|
|
||||||
return copy
|
return copy
|
||||||
|
|
||||||
@@ -1118,14 +1078,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
|||||||
self.spoolType = spoolType
|
self.spoolType = spoolType
|
||||||
self.spoolAmount = spoolAmount
|
self.spoolAmount = spoolAmount
|
||||||
self.projectionRange = projectionRange
|
self.projectionRange = projectionRange
|
||||||
for x in self.mutators.values():
|
self._mutaApplyMutators(mutatorClass=MutatorModule)
|
||||||
Mutator(self, x.attribute, x.value)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.item:
|
if self.item:
|
||||||
return "Module(ID={}, name={}) at {}".format(
|
return "Module(ID={}, name={}) at {}".format(self.item.ID, self.item.name, hex(id(self)))
|
||||||
self.item.ID, self.item.name, hex(id(self))
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return "EmptyModule() at {}".format(hex(id(self)))
|
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__)
|
pyfalog = Logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Mutator(EqBase):
|
class MutatorBase(EqBase):
|
||||||
""" Mutators are the object that represent an attribute override on the module level, in conjunction with
|
""" Mutators are the object that represent an attribute override on the eos item level, in conjunction with
|
||||||
mutaplasmids. Each mutated module, when created, is instantiated with a list of these objects, dictated by the
|
mutaplasmids. Each mutated item, when created, is instantiated with a list of these objects, dictated by the
|
||||||
mutaplasmid that is used on the base module.
|
mutaplasmid that is used on the base item.
|
||||||
|
|
||||||
A note on the different attributes on this object:
|
A note on the different attributes on this object:
|
||||||
* attribute: points to the definition of the attribute from dgmattribs.
|
* 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
|
This could probably be cleaned up with smarter relationships, but whatever
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, module, attr, value):
|
def __init__(self, item, attr, value):
|
||||||
# this needs to be above module assignment, as assigning the module will add it to the list and it via
|
# 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
|
# relationship and needs this set 4correctly
|
||||||
self.attrID = attr.ID
|
self.attrID = attr.ID
|
||||||
|
|
||||||
self.module = module
|
self.item = item
|
||||||
self.moduleID = module.ID
|
self.itemID = item.ID
|
||||||
|
|
||||||
self.__attr = attr
|
self.__attr = attr
|
||||||
self.build()
|
self.build()
|
||||||
@@ -67,20 +67,20 @@ class Mutator(EqBase):
|
|||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
# try...except here to catch orphaned mutators. Pretty rare, only happens so far if hacking the database
|
# 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:
|
try:
|
||||||
# dynamic attribute links to the Mutaplasmids attribute definition for this mutated definition
|
# 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)
|
# 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):
|
except (KeyboardInterrupt, SystemExit):
|
||||||
raise
|
raise
|
||||||
except:
|
except:
|
||||||
self.module = None
|
self.item = None
|
||||||
|
|
||||||
@validates("value")
|
@validates("value")
|
||||||
def validator(self, key, val):
|
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:
|
if self.baseValue == 0:
|
||||||
return 0
|
return 0
|
||||||
mod = val / self.baseValue
|
mod = val / self.baseValue
|
||||||
@@ -99,7 +99,7 @@ class Mutator(EqBase):
|
|||||||
# @todo: need to test what happens:
|
# @todo: need to test what happens:
|
||||||
# 1) if an attribute is removed from the EVE database
|
# 1) if an attribute is removed from the EVE database
|
||||||
# 2) if a mutaplasmid does not have the attribute anymore
|
# 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
|
# Can remove invalid ones in a SQLAlchemy collection class... eventually
|
||||||
return self.__attr is None
|
return self.__attr is None
|
||||||
|
|
||||||
@@ -139,3 +139,11 @@ class Mutator(EqBase):
|
|||||||
@property
|
@property
|
||||||
def attribute(self):
|
def attribute(self):
|
||||||
return self.__attr
|
return self.__attr
|
||||||
|
|
||||||
|
|
||||||
|
class MutatorModule(MutatorBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MutatorDrone(MutatorBase):
|
||||||
|
pass
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ from gui.builtinContextMenus import itemAmountChange
|
|||||||
from gui.builtinContextMenus import itemProjectionRange
|
from gui.builtinContextMenus import itemProjectionRange
|
||||||
from gui.builtinContextMenus import droneSplitStack
|
from gui.builtinContextMenus import droneSplitStack
|
||||||
from gui.builtinContextMenus import itemVariationChange
|
from gui.builtinContextMenus import itemVariationChange
|
||||||
from gui.builtinContextMenus import moduleMutations
|
from gui.builtinContextMenus import itemMutations
|
||||||
from gui.builtinContextMenus import moduleFill
|
from gui.builtinContextMenus import moduleFill
|
||||||
from gui.builtinContextMenus import moduleMutatedExport
|
from gui.builtinContextMenus import moduleMutatedExport
|
||||||
from gui.builtinContextMenus import skillAffectors
|
from gui.builtinContextMenus import skillAffectors
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
# noinspection PyPackageRequirements
|
import re
|
||||||
|
|
||||||
|
# noinspection PyPackageRequirements
|
||||||
import wx
|
import wx
|
||||||
|
|
||||||
import gui.mainFrame
|
import gui.mainFrame
|
||||||
from gui.contextMenu import ContextMenuSingle
|
from gui.contextMenu import ContextMenuSingle
|
||||||
from gui.fitCommands import GuiConvertMutatedLocalModuleCommand, GuiRevertMutatedLocalModuleCommand
|
from gui.fitCommands import (
|
||||||
|
GuiConvertMutatedLocalModuleCommand, GuiRevertMutatedLocalModuleCommand,
|
||||||
|
GuiConvertMutatedLocalDroneCommand, GuiRevertMutatedLocalDroneCommand)
|
||||||
from service.fit import Fit
|
from service.fit import Fit
|
||||||
|
|
||||||
_t = wx.GetTranslation
|
_t = wx.GetTranslation
|
||||||
|
|
||||||
|
|
||||||
class ChangeModuleMutation(ContextMenuSingle):
|
class ChangeItemMutation(ContextMenuSingle):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||||
@@ -18,10 +21,10 @@ class ChangeModuleMutation(ContextMenuSingle):
|
|||||||
|
|
||||||
def display(self, callingWindow, srcContext, mainItem):
|
def display(self, callingWindow, srcContext, mainItem):
|
||||||
|
|
||||||
if srcContext != "fittingModule" or self.mainFrame.getActiveFit() is None:
|
if srcContext not in ("fittingModule", "droneItem") or self.mainFrame.getActiveFit() is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if mainItem is None or mainItem.isEmpty:
|
if mainItem is None or getattr(mainItem, 'isEmpty', False):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if len(mainItem.item.mutaplasmids) == 0 and not mainItem.isMutated:
|
if len(mainItem.item.mutaplasmids) == 0 and not mainItem.isMutated:
|
||||||
@@ -44,10 +47,13 @@ class ChangeModuleMutation(ContextMenuSingle):
|
|||||||
|
|
||||||
for item in mainItem.item.mutaplasmids:
|
for item in mainItem.item.mutaplasmids:
|
||||||
label = item.item.name
|
label = item.item.name
|
||||||
keywords = ('Decayed', 'Gravid', 'Unstable', 'Exigent', 'Radical')
|
keywords = ('Decayed', 'Gravid', 'Unstable', 'Radical')
|
||||||
for kw in keywords:
|
for kw in keywords:
|
||||||
if item.item.name.startswith(f'{kw} '):
|
if item.item.name.startswith(f'{kw} '):
|
||||||
label = kw
|
label = kw
|
||||||
|
m = re.match('(?P<mutagrade>\S+) (?P<dronetype>\S+) Drone (?P<mutatype>\S+) Mutaplasmid', label)
|
||||||
|
if m:
|
||||||
|
label = '{} {}'.format(m.group('mutagrade'), m.group('mutatype'))
|
||||||
id = ContextMenuSingle.nextID()
|
id = ContextMenuSingle.nextID()
|
||||||
self.eventIDs[id] = (item, mainItem)
|
self.eventIDs[id] = (item, mainItem)
|
||||||
mItem = wx.MenuItem(menu, id, label)
|
mItem = wx.MenuItem(menu, id, label)
|
||||||
@@ -57,13 +63,17 @@ class ChangeModuleMutation(ContextMenuSingle):
|
|||||||
return sub
|
return sub
|
||||||
|
|
||||||
def handleMenu(self, event):
|
def handleMenu(self, event):
|
||||||
mutaplasmid, mod = self.eventIDs[event.Id]
|
mutaplasmid, item = self.eventIDs[event.Id]
|
||||||
fitID = self.mainFrame.getActiveFit()
|
fitID = self.mainFrame.getActiveFit()
|
||||||
fit = Fit.getInstance().getFit(fitID)
|
fit = Fit.getInstance().getFit(fitID)
|
||||||
if mod in fit.modules:
|
if item in fit.modules:
|
||||||
position = fit.modules.index(mod)
|
position = fit.modules.index(item)
|
||||||
self.mainFrame.command.Submit(GuiConvertMutatedLocalModuleCommand(
|
self.mainFrame.command.Submit(GuiConvertMutatedLocalModuleCommand(
|
||||||
fitID=fitID, position=position, mutaplasmid=mutaplasmid))
|
fitID=fitID, position=position, mutaplasmid=mutaplasmid))
|
||||||
|
elif item in fit.drones:
|
||||||
|
position = fit.drones.index(item)
|
||||||
|
self.mainFrame.command.Submit(GuiConvertMutatedLocalDroneCommand(
|
||||||
|
fitID=fitID, position=position, mutaplasmid=mutaplasmid))
|
||||||
|
|
||||||
def activate(self, callingWindow, fullContext, mainItem, i):
|
def activate(self, callingWindow, fullContext, mainItem, i):
|
||||||
fitID = self.mainFrame.getActiveFit()
|
fitID = self.mainFrame.getActiveFit()
|
||||||
@@ -72,9 +82,13 @@ class ChangeModuleMutation(ContextMenuSingle):
|
|||||||
position = fit.modules.index(mainItem)
|
position = fit.modules.index(mainItem)
|
||||||
self.mainFrame.command.Submit(GuiRevertMutatedLocalModuleCommand(
|
self.mainFrame.command.Submit(GuiRevertMutatedLocalModuleCommand(
|
||||||
fitID=fitID, position=position))
|
fitID=fitID, position=position))
|
||||||
|
elif mainItem in fit.drones:
|
||||||
|
position = fit.drones.index(mainItem)
|
||||||
|
self.mainFrame.command.Submit(GuiRevertMutatedLocalDroneCommand(
|
||||||
|
fitID=fitID, position=position))
|
||||||
|
|
||||||
def getBitmap(self, callingWindow, context, mainItem):
|
def getBitmap(self, callingWindow, context, mainItem):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
ChangeModuleMutation.register()
|
ChangeItemMutation.register()
|
||||||
@@ -355,4 +355,5 @@ class ItemParams(wx.Panel):
|
|||||||
fvalue = roundDec(value, digits)
|
fvalue = roundDec(value, digits)
|
||||||
else:
|
else:
|
||||||
fvalue = value
|
fvalue = value
|
||||||
return "%s %s" % (fvalue, unit)
|
unitSuffix = f' {unit}' if unit is not None else ''
|
||||||
|
return f'{fvalue}{unitSuffix}'
|
||||||
|
|||||||
@@ -18,22 +18,22 @@ _t = wx.GetTranslation
|
|||||||
|
|
||||||
class ItemMutatorPanel(wx.Panel):
|
class ItemMutatorPanel(wx.Panel):
|
||||||
|
|
||||||
def __init__(self, parent, mod):
|
def __init__(self, parent, stuff):
|
||||||
wx.Panel.__init__(self, parent)
|
wx.Panel.__init__(self, parent)
|
||||||
self.stuff = mod
|
self.stuff = stuff
|
||||||
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
|
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
|
||||||
|
|
||||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
|
||||||
headerSizer = wx.BoxSizer(wx.HORIZONTAL)
|
headerSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
headerSizer.AddStretchSpacer()
|
headerSizer.AddStretchSpacer()
|
||||||
itemIcon = BitmapLoader.getStaticBitmap(mod.item.iconID, self, "icons")
|
itemIcon = BitmapLoader.getStaticBitmap(stuff.item.iconID, self, "icons")
|
||||||
if itemIcon is not None:
|
if itemIcon is not None:
|
||||||
headerSizer.Add(itemIcon, 0, 0, 0)
|
headerSizer.Add(itemIcon, 0, 0, 0)
|
||||||
mutaIcon = BitmapLoader.getStaticBitmap(mod.mutaplasmid.item.iconID, self, "icons")
|
mutaIcon = BitmapLoader.getStaticBitmap(stuff.mutaplasmid.item.iconID, self, "icons")
|
||||||
if mutaIcon is not None:
|
if mutaIcon is not None:
|
||||||
headerSizer.Add(mutaIcon, 0, wx.LEFT, 0)
|
headerSizer.Add(mutaIcon, 0, wx.LEFT, 0)
|
||||||
sourceItemShort = "{} {}".format(mod.mutaplasmid.item.name.split(" ")[0], mod.baseItem.name)
|
sourceItemShort = "{} {}".format(stuff.mutaplasmid.item.name.split(" ")[0], stuff.baseItem.name)
|
||||||
sourceItemText = wx.StaticText(self, wx.ID_ANY, sourceItemShort)
|
sourceItemText = wx.StaticText(self, wx.ID_ANY, sourceItemShort)
|
||||||
font = parent.GetFont()
|
font = parent.GetFont()
|
||||||
font.SetWeight(wx.BOLD)
|
font.SetWeight(wx.BOLD)
|
||||||
@@ -43,7 +43,7 @@ class ItemMutatorPanel(wx.Panel):
|
|||||||
mainSizer.Add(headerSizer, 0, wx.ALL | wx.EXPAND, 5)
|
mainSizer.Add(headerSizer, 0, wx.ALL | wx.EXPAND, 5)
|
||||||
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND, 0)
|
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND, 0)
|
||||||
|
|
||||||
self.mutaList = ItemMutatorList(self, mod)
|
self.mutaList = ItemMutatorList(self, stuff)
|
||||||
mainSizer.Add(self.mutaList, 1, wx.EXPAND | wx.ALL, 0)
|
mainSizer.Add(self.mutaList, 1, wx.EXPAND | wx.ALL, 0)
|
||||||
|
|
||||||
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND, 0)
|
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND, 0)
|
||||||
@@ -68,13 +68,13 @@ class ItemMutatorPanel(wx.Panel):
|
|||||||
|
|
||||||
class ItemMutatorList(wx.ScrolledWindow):
|
class ItemMutatorList(wx.ScrolledWindow):
|
||||||
|
|
||||||
def __init__(self, parent, mod):
|
def __init__(self, parent, stuff):
|
||||||
wx.ScrolledWindow.__init__(self, parent)
|
wx.ScrolledWindow.__init__(self, parent)
|
||||||
self.SetScrollRate(0, 15)
|
self.SetScrollRate(0, 15)
|
||||||
self.carryingFitID = gui.mainFrame.MainFrame.getInstance().getActiveFit()
|
self.carryingFitID = gui.mainFrame.MainFrame.getInstance().getActiveFit()
|
||||||
self.initialMutations = {}
|
self.initialMutations = {}
|
||||||
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||||
self.mod = mod
|
self.stuff = stuff
|
||||||
self.timer = None
|
self.timer = None
|
||||||
self.isModified = False
|
self.isModified = False
|
||||||
|
|
||||||
@@ -91,9 +91,8 @@ class ItemMutatorList(wx.ScrolledWindow):
|
|||||||
('Damage Control', 'duration'): True,
|
('Damage Control', 'duration'): True,
|
||||||
('Siege Module', 'siegeLocalLogisticsDurationBonus'): False
|
('Siege Module', 'siegeLocalLogisticsDurationBonus'): False
|
||||||
}
|
}
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
for m in sorted(mod.mutators.values(), key=lambda x: x.attribute.displayName):
|
for m in sorted(stuff.mutators.values(), key=lambda x: x.attribute.displayName):
|
||||||
if m.baseValue == 0:
|
if m.baseValue == 0:
|
||||||
continue
|
continue
|
||||||
if not first:
|
if not first:
|
||||||
@@ -102,10 +101,10 @@ class ItemMutatorList(wx.ScrolledWindow):
|
|||||||
|
|
||||||
self.initialMutations[m.attrID] = m.value
|
self.initialMutations[m.attrID] = m.value
|
||||||
|
|
||||||
highIsGood = higOverrides.get((mod.item.group.name, m.attribute.name), m.highIsGood)
|
highIsGood = higOverrides.get((stuff.item.group.name, m.attribute.name), m.highIsGood)
|
||||||
# Format: [raw value, modifier applied to base raw value, display value]
|
# Format: [raw value, modifier applied to base raw value, display value]
|
||||||
range1 = (m.minValue, m.attribute.unit.SimplifyValue(m.minValue))
|
range1 = (m.minValue, self._simplifyValue(m, m.minValue))
|
||||||
range2 = (m.maxValue, m.attribute.unit.SimplifyValue(m.maxValue))
|
range2 = (m.maxValue, self._simplifyValue(m, m.maxValue))
|
||||||
|
|
||||||
# minValue/maxValue do not always correspond to min/max, because these are
|
# minValue/maxValue do not always correspond to min/max, because these are
|
||||||
# just base value multiplied by minMod/maxMod, and in case base is negative
|
# just base value multiplied by minMod/maxMod, and in case base is negative
|
||||||
@@ -148,11 +147,11 @@ class ItemMutatorList(wx.ScrolledWindow):
|
|||||||
|
|
||||||
headingSizer.Add(displayName, 3, wx.ALL | wx.EXPAND, 0)
|
headingSizer.Add(displayName, 3, wx.ALL | wx.EXPAND, 0)
|
||||||
|
|
||||||
worseVal = ItemParams.FormatValue(*m.attribute.unit.PreformatValue(worseRange[0]), rounding='dec')
|
worseVal = ItemParams.FormatValue(*self._preformatValue(m, worseRange[0]), rounding='dec')
|
||||||
worseText = wx.StaticText(self, wx.ID_ANY, worseVal)
|
worseText = wx.StaticText(self, wx.ID_ANY, worseVal)
|
||||||
worseText.SetForegroundColour(badColor)
|
worseText.SetForegroundColour(badColor)
|
||||||
|
|
||||||
betterVal = ItemParams.FormatValue(*m.attribute.unit.PreformatValue(betterRange[0]), rounding='dec')
|
betterVal = ItemParams.FormatValue(*self._preformatValue(m, betterRange[0]), rounding='dec')
|
||||||
betterText = wx.StaticText(self, wx.ID_ANY, betterVal)
|
betterText = wx.StaticText(self, wx.ID_ANY, betterVal)
|
||||||
betterText.SetForegroundColour(goodColor)
|
betterText.SetForegroundColour(goodColor)
|
||||||
|
|
||||||
@@ -163,23 +162,38 @@ class ItemMutatorList(wx.ScrolledWindow):
|
|||||||
sizer.Add(headingSizer, 0, wx.ALL | wx.EXPAND, 5)
|
sizer.Add(headingSizer, 0, wx.ALL | wx.EXPAND, 5)
|
||||||
|
|
||||||
slider = AttributeSlider(parent=self,
|
slider = AttributeSlider(parent=self,
|
||||||
baseValue=m.attribute.unit.SimplifyValue(sliderBaseValue),
|
baseValue=self._simplifyValue(m, sliderBaseValue),
|
||||||
minValue=displayMinRange[1],
|
minValue=displayMinRange[1],
|
||||||
maxValue=displayMaxRange[1],
|
maxValue=displayMaxRange[1],
|
||||||
inverse=displayMaxRange is worseRange)
|
inverse=displayMaxRange is worseRange)
|
||||||
slider.SetValue(m.attribute.unit.SimplifyValue(m.value), False)
|
slider.SetValue(self._simplifyValue(m, m.value), False)
|
||||||
slider.Bind(EVT_VALUE_CHANGED, self.changeMutatedValue)
|
slider.Bind(EVT_VALUE_CHANGED, self.changeMutatedValue)
|
||||||
self.event_mapping[slider] = m
|
self.event_mapping[slider] = m
|
||||||
sizer.Add(slider, 0, wx.RIGHT | wx.LEFT | wx.EXPAND, 10)
|
sizer.Add(slider, 0, wx.RIGHT | wx.LEFT | wx.EXPAND, 10)
|
||||||
|
|
||||||
self.SetSizer(sizer)
|
self.SetSizer(sizer)
|
||||||
|
|
||||||
|
def _simplifyValue(self, mutator, value):
|
||||||
|
if mutator.attribute.unit is None:
|
||||||
|
return value
|
||||||
|
return mutator.attribute.unit.SimplifyValue(value)
|
||||||
|
|
||||||
|
def _complicateValue(self, mutator, value):
|
||||||
|
if mutator.attribute.unit is None:
|
||||||
|
return value
|
||||||
|
return mutator.attribute.unit.ComplicateValue(value)
|
||||||
|
|
||||||
|
def _preformatValue(self, mutator, value):
|
||||||
|
if mutator.attribute.unit is None:
|
||||||
|
return value, None
|
||||||
|
return mutator.attribute.unit.PreformatValue(value)
|
||||||
|
|
||||||
def changeMutatedValue(self, evt):
|
def changeMutatedValue(self, evt):
|
||||||
if evt.AffectsModifiedFlag:
|
if evt.AffectsModifiedFlag:
|
||||||
self.isModified = True
|
self.isModified = True
|
||||||
m = self.event_mapping[evt.Object]
|
m = self.event_mapping[evt.Object]
|
||||||
value = evt.Value
|
value = evt.Value
|
||||||
value = m.attribute.unit.ComplicateValue(value)
|
value = self._complicateValue(m, value)
|
||||||
sFit = Fit.getInstance()
|
sFit = Fit.getInstance()
|
||||||
|
|
||||||
sFit.changeMutatedValuePrelim(m, value)
|
sFit.changeMutatedValuePrelim(m, value)
|
||||||
@@ -198,7 +212,7 @@ class ItemMutatorList(wx.ScrolledWindow):
|
|||||||
sFit = Fit.getInstance()
|
sFit = Fit.getInstance()
|
||||||
for slider, m in self.event_mapping.items():
|
for slider, m in self.event_mapping.items():
|
||||||
value = sFit.changeMutatedValuePrelim(m, m.baseValue)
|
value = sFit.changeMutatedValuePrelim(m, m.baseValue)
|
||||||
value = m.attribute.unit.SimplifyValue(value)
|
value = self._simplifyValue(m, value)
|
||||||
slider.SetValue(value, affect_modified_flag=False)
|
slider.SetValue(value, affect_modified_flag=False)
|
||||||
evt.Skip()
|
evt.Skip()
|
||||||
|
|
||||||
@@ -208,7 +222,7 @@ class ItemMutatorList(wx.ScrolledWindow):
|
|||||||
for slider, m in self.event_mapping.items():
|
for slider, m in self.event_mapping.items():
|
||||||
value = random.uniform(m.minValue, m.maxValue)
|
value = random.uniform(m.minValue, m.maxValue)
|
||||||
value = sFit.changeMutatedValuePrelim(m, value)
|
value = sFit.changeMutatedValuePrelim(m, value)
|
||||||
value = m.attribute.unit.SimplifyValue(value)
|
value = self._simplifyValue(m, value)
|
||||||
slider.SetValue(value, affect_modified_flag=False)
|
slider.SetValue(value, affect_modified_flag=False)
|
||||||
evt.Skip()
|
evt.Skip()
|
||||||
|
|
||||||
@@ -218,7 +232,7 @@ class ItemMutatorList(wx.ScrolledWindow):
|
|||||||
for slider, m in self.event_mapping.items():
|
for slider, m in self.event_mapping.items():
|
||||||
if m.attrID in self.initialMutations:
|
if m.attrID in self.initialMutations:
|
||||||
value = sFit.changeMutatedValuePrelim(m, self.initialMutations[m.attrID])
|
value = sFit.changeMutatedValuePrelim(m, self.initialMutations[m.attrID])
|
||||||
value = m.attribute.unit.SimplifyValue(value)
|
value = self._simplifyValue(m, value)
|
||||||
slider.SetValue(value, affect_modified_flag=False)
|
slider.SetValue(value, affect_modified_flag=False)
|
||||||
evt.Skip()
|
evt.Skip()
|
||||||
|
|
||||||
@@ -226,14 +240,14 @@ class ItemMutatorList(wx.ScrolledWindow):
|
|||||||
# Submit mutation changes
|
# Submit mutation changes
|
||||||
sFit = Fit.getInstance()
|
sFit = Fit.getInstance()
|
||||||
fit = sFit.getFit(self.carryingFitID)
|
fit = sFit.getFit(self.carryingFitID)
|
||||||
if self.mod in fit.modules:
|
if self.stuff in fit.modules:
|
||||||
if self.isModified:
|
if self.isModified:
|
||||||
currentMutation = {}
|
currentMutation = {}
|
||||||
for slider, m in self.event_mapping.items():
|
for slider, m in self.event_mapping.items():
|
||||||
# Sliders may have more up-to-date info than mutator in case we changed
|
# Sliders may have more up-to-date info than mutator in case we changed
|
||||||
# value in slider and without confirming it, decided to close window
|
# value in slider and without confirming it, decided to close window
|
||||||
value = slider.GetValue()
|
value = slider.GetValue()
|
||||||
value = m.attribute.unit.ComplicateValue(value)
|
value = self._complicateValue(m, value)
|
||||||
if value != m.value:
|
if value != m.value:
|
||||||
value = sFit.changeMutatedValuePrelim(m, value)
|
value = sFit.changeMutatedValuePrelim(m, value)
|
||||||
currentMutation[m.attrID] = value
|
currentMutation[m.attrID] = value
|
||||||
@@ -242,7 +256,7 @@ class ItemMutatorList(wx.ScrolledWindow):
|
|||||||
mainFrame = gui.mainFrame.MainFrame.getInstance()
|
mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||||
mainFrame.getCommandForFit(self.carryingFitID).Submit(cmd.GuiChangeLocalModuleMutationCommand(
|
mainFrame.getCommandForFit(self.carryingFitID).Submit(cmd.GuiChangeLocalModuleMutationCommand(
|
||||||
fitID=self.carryingFitID,
|
fitID=self.carryingFitID,
|
||||||
position=fit.modules.index(self.mod),
|
position=fit.modules.index(self.stuff),
|
||||||
mutation=currentMutation,
|
mutation=currentMutation,
|
||||||
oldMutation=self.initialMutations))
|
oldMutation=self.initialMutations))
|
||||||
for slider in self.event_mapping:
|
for slider in self.event_mapping:
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ from .gui.localDrone.changeAmount import GuiChangeLocalDroneAmountCommand
|
|||||||
from .gui.localDrone.changeMetas import GuiChangeLocalDroneMetasCommand
|
from .gui.localDrone.changeMetas import GuiChangeLocalDroneMetasCommand
|
||||||
from .gui.localDrone.clone import GuiCloneLocalDroneCommand
|
from .gui.localDrone.clone import GuiCloneLocalDroneCommand
|
||||||
from .gui.localDrone.imprt import GuiImportLocalDronesCommand
|
from .gui.localDrone.imprt import GuiImportLocalDronesCommand
|
||||||
|
from .gui.localDrone.mutatedConvert import GuiConvertMutatedLocalDroneCommand
|
||||||
|
from .gui.localDrone.mutatedRevert import GuiRevertMutatedLocalDroneCommand
|
||||||
from .gui.localDrone.remove import GuiRemoveLocalDronesCommand
|
from .gui.localDrone.remove import GuiRemoveLocalDronesCommand
|
||||||
from .gui.localDrone.stackSplit import GuiSplitLocalDroneStackCommand
|
from .gui.localDrone.stackSplit import GuiSplitLocalDroneStackCommand
|
||||||
from .gui.localDrone.stacksMerge import GuiMergeLocalDroneStacksCommand
|
from .gui.localDrone.stacksMerge import GuiMergeLocalDroneStacksCommand
|
||||||
|
|||||||
65
gui/fitCommands/gui/localDrone/mutatedConvert.py
Normal file
65
gui/fitCommands/gui/localDrone/mutatedConvert.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import math
|
||||||
|
|
||||||
|
import wx
|
||||||
|
|
||||||
|
import eos.db
|
||||||
|
import gui.mainFrame
|
||||||
|
from gui import globalEvents as GE
|
||||||
|
from gui.fitCommands.calc.drone.localAdd import CalcAddLocalDroneCommand
|
||||||
|
from gui.fitCommands.calc.drone.localRemove import CalcRemoveLocalDroneCommand
|
||||||
|
from gui.fitCommands.helpers import DroneInfo, InternalCommandHistory
|
||||||
|
from service.fit import Fit
|
||||||
|
|
||||||
|
|
||||||
|
class GuiConvertMutatedLocalDroneCommand(wx.Command):
|
||||||
|
|
||||||
|
def __init__(self, fitID, position, mutaplasmid):
|
||||||
|
wx.Command.__init__(self, True, 'Convert Local Drone to Mutated')
|
||||||
|
self.internalHistory = InternalCommandHistory()
|
||||||
|
self.fitID = fitID
|
||||||
|
self.position = position
|
||||||
|
self.itemID = mutaplasmid.resultingItem.ID
|
||||||
|
self.mutaplasmidID = mutaplasmid.ID
|
||||||
|
|
||||||
|
def Do(self):
|
||||||
|
sFit = Fit.getInstance()
|
||||||
|
fit = sFit.getFit(self.fitID)
|
||||||
|
try:
|
||||||
|
drone = fit.drones[self.position]
|
||||||
|
except IndexError:
|
||||||
|
return False
|
||||||
|
if drone.isMutated:
|
||||||
|
return False
|
||||||
|
info = DroneInfo(
|
||||||
|
amount=drone.amount,
|
||||||
|
amountActive=drone.amountActive,
|
||||||
|
itemID=self.itemID,
|
||||||
|
baseItemID=drone.item.ID,
|
||||||
|
mutaplasmidID=self.mutaplasmidID,
|
||||||
|
mutations={})
|
||||||
|
cmdRemove = CalcRemoveLocalDroneCommand(
|
||||||
|
fitID=self.fitID,
|
||||||
|
position=self.position,
|
||||||
|
amount=math.inf)
|
||||||
|
cmdAdd = CalcAddLocalDroneCommand(
|
||||||
|
fitID=self.fitID,
|
||||||
|
droneInfo=info,
|
||||||
|
forceNewStack=True,
|
||||||
|
ignoreRestrictions=True)
|
||||||
|
success = self.internalHistory.submitBatch(cmdRemove, cmdAdd)
|
||||||
|
eos.db.flush()
|
||||||
|
sFit.recalc(self.fitID)
|
||||||
|
sFit.fill(self.fitID)
|
||||||
|
eos.db.commit()
|
||||||
|
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
|
||||||
|
return success
|
||||||
|
|
||||||
|
def Undo(self):
|
||||||
|
success = self.internalHistory.undoAll()
|
||||||
|
eos.db.flush()
|
||||||
|
sFit = Fit.getInstance()
|
||||||
|
sFit.recalc(self.fitID)
|
||||||
|
sFit.fill(self.fitID)
|
||||||
|
eos.db.commit()
|
||||||
|
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
|
||||||
|
return success
|
||||||
60
gui/fitCommands/gui/localDrone/mutatedRevert.py
Normal file
60
gui/fitCommands/gui/localDrone/mutatedRevert.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import math
|
||||||
|
|
||||||
|
import wx
|
||||||
|
|
||||||
|
import eos.db
|
||||||
|
import gui.mainFrame
|
||||||
|
from gui import globalEvents as GE
|
||||||
|
from gui.fitCommands.calc.drone.localAdd import CalcAddLocalDroneCommand
|
||||||
|
from gui.fitCommands.calc.drone.localRemove import CalcRemoveLocalDroneCommand
|
||||||
|
from gui.fitCommands.helpers import DroneInfo, InternalCommandHistory
|
||||||
|
from service.fit import Fit
|
||||||
|
|
||||||
|
|
||||||
|
class GuiRevertMutatedLocalDroneCommand(wx.Command):
|
||||||
|
|
||||||
|
def __init__(self, fitID, position):
|
||||||
|
wx.Command.__init__(self, True, 'Revert Local Drone from Mutated')
|
||||||
|
self.internalHistory = InternalCommandHistory()
|
||||||
|
self.fitID = fitID
|
||||||
|
self.position = position
|
||||||
|
|
||||||
|
def Do(self):
|
||||||
|
sFit = Fit.getInstance()
|
||||||
|
fit = sFit.getFit(self.fitID)
|
||||||
|
try:
|
||||||
|
drone = fit.drones[self.position]
|
||||||
|
except IndexError:
|
||||||
|
return False
|
||||||
|
if not drone.isMutated:
|
||||||
|
return False
|
||||||
|
info = DroneInfo(
|
||||||
|
amount=drone.amount,
|
||||||
|
amountActive=drone.amountActive,
|
||||||
|
itemID=drone.baseItemID)
|
||||||
|
cmdRemove = CalcRemoveLocalDroneCommand(
|
||||||
|
fitID=self.fitID,
|
||||||
|
position=self.position,
|
||||||
|
amount=math.inf)
|
||||||
|
cmdAdd = CalcAddLocalDroneCommand(
|
||||||
|
fitID=self.fitID,
|
||||||
|
droneInfo=info,
|
||||||
|
forceNewStack=True,
|
||||||
|
ignoreRestrictions=True)
|
||||||
|
success = self.internalHistory.submitBatch(cmdRemove, cmdAdd)
|
||||||
|
eos.db.flush()
|
||||||
|
sFit.recalc(self.fitID)
|
||||||
|
sFit.fill(self.fitID)
|
||||||
|
eos.db.commit()
|
||||||
|
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
|
||||||
|
return success
|
||||||
|
|
||||||
|
def Undo(self):
|
||||||
|
success = self.internalHistory.undoAll()
|
||||||
|
eos.db.flush()
|
||||||
|
sFit = Fit.getInstance()
|
||||||
|
sFit.recalc(self.fitID)
|
||||||
|
sFit.fill(self.fitID)
|
||||||
|
eos.db.commit()
|
||||||
|
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
|
||||||
|
return success
|
||||||
@@ -21,7 +21,10 @@ class GuiConvertMutatedLocalModuleCommand(wx.Command):
|
|||||||
def Do(self):
|
def Do(self):
|
||||||
sFit = Fit.getInstance()
|
sFit = Fit.getInstance()
|
||||||
fit = sFit.getFit(self.fitID)
|
fit = sFit.getFit(self.fitID)
|
||||||
mod = fit.modules[self.position]
|
try:
|
||||||
|
mod = fit.modules[self.position]
|
||||||
|
except IndexError:
|
||||||
|
return False
|
||||||
if mod.isEmpty:
|
if mod.isEmpty:
|
||||||
return False
|
return False
|
||||||
if mod.isMutated:
|
if mod.isMutated:
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ class GuiRevertMutatedLocalModuleCommand(wx.Command):
|
|||||||
def Do(self):
|
def Do(self):
|
||||||
sFit = Fit.getInstance()
|
sFit = Fit.getInstance()
|
||||||
fit = sFit.getFit(self.fitID)
|
fit = sFit.getFit(self.fitID)
|
||||||
mod = fit.modules[self.position]
|
try:
|
||||||
|
mod = fit.modules[self.position]
|
||||||
|
except IndexError:
|
||||||
|
return False
|
||||||
if mod.isEmpty:
|
if mod.isEmpty:
|
||||||
return False
|
return False
|
||||||
if not mod.isMutated:
|
if not mod.isMutated:
|
||||||
|
|||||||
@@ -158,8 +158,11 @@ class ModuleInfo:
|
|||||||
|
|
||||||
class DroneInfo:
|
class DroneInfo:
|
||||||
|
|
||||||
def __init__(self, itemID, amount, amountActive):
|
def __init__(self, amount, amountActive, itemID, baseItemID=None, mutaplasmidID=None, mutations=None):
|
||||||
self.itemID = itemID
|
self.itemID = itemID
|
||||||
|
self.baseItemID = baseItemID
|
||||||
|
self.mutaplasmidID = mutaplasmidID
|
||||||
|
self.mutations = mutations
|
||||||
self.amount = amount
|
self.amount = amount
|
||||||
self.amountActive = amountActive
|
self.amountActive = amountActive
|
||||||
|
|
||||||
@@ -170,22 +173,40 @@ class DroneInfo:
|
|||||||
info = cls(
|
info = cls(
|
||||||
itemID=drone.itemID,
|
itemID=drone.itemID,
|
||||||
amount=drone.amount,
|
amount=drone.amount,
|
||||||
amountActive=drone.amountActive)
|
amountActive=drone.amountActive,
|
||||||
|
baseItemID=drone.baseItemID,
|
||||||
|
mutaplasmidID=drone.mutaplasmidID,
|
||||||
|
mutations={m.attrID: m.value for m in drone.mutators.values()})
|
||||||
return info
|
return info
|
||||||
|
|
||||||
def toDrone(self):
|
def toDrone(self):
|
||||||
item = Market.getInstance().getItem(self.itemID, eager=('attributes', 'group.category'))
|
mkt = Market.getInstance()
|
||||||
|
item = mkt.getItem(self.itemID, eager=('attributes', 'group.category'))
|
||||||
|
if self.baseItemID and self.mutaplasmidID:
|
||||||
|
baseItem = mkt.getItem(self.baseItemID, eager=('attributes', 'group.category'))
|
||||||
|
mutaplasmid = eos.db.getDynamicItem(self.mutaplasmidID)
|
||||||
|
else:
|
||||||
|
baseItem = None
|
||||||
|
mutaplasmid = None
|
||||||
try:
|
try:
|
||||||
drone = Drone(item)
|
drone = Drone(item, baseItem=baseItem, mutaplasmid=mutaplasmid)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pyfalog.warning('Invalid item: {}'.format(self.itemID))
|
pyfalog.warning('Invalid item: {}'.format(self.itemID))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if self.mutations is not None:
|
||||||
|
for attrID, mutator in drone.mutators.items():
|
||||||
|
if attrID in self.mutations:
|
||||||
|
mutator.value = self.mutations[attrID]
|
||||||
|
|
||||||
drone.amount = self.amount
|
drone.amount = self.amount
|
||||||
drone.amountActive = self.amountActive
|
drone.amountActive = self.amountActive
|
||||||
return drone
|
return drone
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return makeReprStr(self, ['itemID', 'amount', 'amountActive'])
|
return makeReprStr(self, [
|
||||||
|
'itemID', 'amount', 'amountActive',
|
||||||
|
'baseItemID', 'mutaplasmidID', 'mutations'])
|
||||||
|
|
||||||
|
|
||||||
class FighterInfo:
|
class FighterInfo:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import wx
|
|||||||
|
|
||||||
import config
|
import config
|
||||||
import gui.mainFrame
|
import gui.mainFrame
|
||||||
|
from eos.saveddata.drone import Drone
|
||||||
from eos.saveddata.module import Module
|
from eos.saveddata.module import Module
|
||||||
from gui.auxWindow import AuxiliaryFrame
|
from gui.auxWindow import AuxiliaryFrame
|
||||||
from gui.bitmap_loader import BitmapLoader
|
from gui.bitmap_loader import BitmapLoader
|
||||||
@@ -165,7 +166,7 @@ class ItemStatsContainer(wx.Panel):
|
|||||||
self.traits = ItemTraits(self.nbContainer, stuff, item)
|
self.traits = ItemTraits(self.nbContainer, stuff, item)
|
||||||
self.nbContainer.AddPage(self.traits, _t("Traits"))
|
self.nbContainer.AddPage(self.traits, _t("Traits"))
|
||||||
|
|
||||||
if isinstance(stuff, Module) and stuff.isMutated:
|
if isinstance(stuff, (Module, Drone)) and stuff.isMutated:
|
||||||
self.mutator = ItemMutatorPanel(self.nbContainer, stuff)
|
self.mutator = ItemMutatorPanel(self.nbContainer, stuff)
|
||||||
self.nbContainer.AddPage(self.mutator, _t("Mutations"))
|
self.nbContainer.AddPage(self.mutator, _t("Mutations"))
|
||||||
|
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ class Fit:
|
|||||||
return fits
|
return fits
|
||||||
|
|
||||||
def changeMutatedValuePrelim(self, mutator, value):
|
def changeMutatedValuePrelim(self, mutator, value):
|
||||||
pyfalog.debug("Changing mutated value for {} / {}: {} => {}".format(mutator.module, mutator.module.mutaplasmid, mutator.value, value))
|
pyfalog.debug("Changing mutated value for {} / {}: {} => {}".format(mutator.item, mutator.item.mutaplasmid, mutator.value, value))
|
||||||
if mutator.value != value:
|
if mutator.value != value:
|
||||||
mutator.value = value
|
mutator.value = value
|
||||||
eos.db.flush()
|
eos.db.flush()
|
||||||
|
|||||||
Reference in New Issue
Block a user