diff --git a/gui/builtinItemStatsViews/itemSkills.py b/gui/builtinItemStatsViews/itemSkills.py new file mode 100644 index 000000000..4612ab3ac --- /dev/null +++ b/gui/builtinItemStatsViews/itemSkills.py @@ -0,0 +1,186 @@ +# noinspection PyPackageRequirements +import wx +import itertools + +import gui.mainFrame +from eos.saveddata.character import Skill +from eos.saveddata.fighter import Fighter as es_Fighter +from eos.saveddata.module import Module as es_Module +from eos.saveddata.ship import Ship +from gui.utils.clipboard import toClipboard +from gui.utils.numberFormatter import formatAmount +from service.fit import Fit + +_t = wx.GetTranslation + + +class ItemSkills(wx.Panel): + def __init__(self, parent, stuff, item): + wx.Panel.__init__(self, parent) + self.stuff = stuff + self.item = item + + mainSizer = wx.BoxSizer(wx.HORIZONTAL) + + leftPanel = wx.Panel(self) + leftSizer = wx.BoxSizer(wx.VERTICAL) + leftPanel.SetSizer(leftSizer) + + header = wx.StaticText(leftPanel, wx.ID_ANY, _t("Components")) + font = header.GetFont() + font.SetWeight(wx.FONTWEIGHT_BOLD) + header.SetFont(font) + leftSizer.Add(header, 0, wx.ALL, 5) + + self.checkboxes = {} + components = [ + ("Ship", "ship"), + ("Modules", "modules"), + ("Drones", "drones"), + ("Fighters", "fighters"), + ("Cargo", "cargo"), + ("Implants", "appliedImplants"), + ("Boosters", "boosters"), + ] + + for label, key in components: + cb = wx.CheckBox(leftPanel, wx.ID_ANY, label) + cb.SetValue(True) + cb.Bind(wx.EVT_CHECKBOX, self.onCheckboxChange) + self.checkboxes[key] = cb + leftSizer.Add(cb, 0, wx.ALL, 2) + + leftSizer.AddStretchSpacer() + + mainSizer.Add(leftPanel, 0, wx.EXPAND | wx.ALL, 5) + + rightPanel = wx.Panel(self) + rightSizer = wx.BoxSizer(wx.VERTICAL) + rightPanel.SetSizer(rightSizer) + + headerRight = wx.StaticText(rightPanel, wx.ID_ANY, _t("Skills")) + fontRight = headerRight.GetFont() + fontRight.SetWeight(wx.FONTWEIGHT_BOLD) + headerRight.SetFont(fontRight) + rightSizer.Add(headerRight, 0, wx.ALL, 5) + + self.skillsText = wx.TextCtrl(rightPanel, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_DONTWRAP) + font = wx.Font(9, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) + self.skillsText.SetFont(font) + rightSizer.Add(self.skillsText, 1, wx.EXPAND | wx.ALL, 5) + + mainSizer.Add(rightPanel, 1, wx.EXPAND | wx.ALL, 5) + + self.SetSizer(mainSizer) + + self.nbContainer = parent if isinstance(parent, wx.Notebook) else None + if self.nbContainer: + self.nbContainer.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onTabChanged) + + self.updateSkills() + + def onCheckboxChange(self, event): + self.updateSkills() + self._copyToClipboard() + + def updateSkills(self): + fitID = gui.mainFrame.MainFrame.getInstance().getActiveFit() + if fitID is None: + self.skillsText.SetValue("") + self._updateCheckboxStates(None) + return + + sFit = Fit.getInstance() + fit = sFit.getFit(fitID) + if fit is None: + self.skillsText.SetValue("") + self._updateCheckboxStates(None) + return + + if not fit.calculated: + fit.calculate() + + self._updateCheckboxStates(fit) + + char = fit.character + skillsMap = {} + + items = [] + if self.checkboxes["ship"].GetValue(): + items.append(fit.ship) + if self.checkboxes["modules"].GetValue(): + items.extend(fit.modules) + if self.checkboxes["drones"].GetValue(): + items.extend(fit.drones) + if self.checkboxes["fighters"].GetValue(): + items.extend(fit.fighters) + if self.checkboxes["cargo"].GetValue(): + items.extend(fit.cargo) + if self.checkboxes["appliedImplants"].GetValue(): + items.extend(fit.appliedImplants) + if self.checkboxes["boosters"].GetValue(): + items.extend(fit.boosters) + + for thing in items: + self._collectAffectingSkills(thing, char, skillsMap) + + skillsList = "" + for skillName in sorted(skillsMap): + charLevel = skillsMap[skillName] + for level in range(1, charLevel + 1): + skillsList += "%s %d\n" % (skillName, level) + + self.skillsText.SetValue(skillsList) + self._copyToClipboard() + + def _copyToClipboard(self): + skillsText = self.skillsText.GetValue() + if skillsText: + toClipboard(skillsText) + + def onTabChanged(self, event): + if self.nbContainer: + pageIndex = self.nbContainer.FindPage(self) + if pageIndex != -1 and event.GetSelection() == pageIndex: + self.updateSkills() + event.Skip() + + def _updateCheckboxStates(self, fit): + if fit is None: + for cb in self.checkboxes.values(): + cb.Enable(False) + return + + self.checkboxes["ship"].Enable(True) + self.checkboxes["modules"].Enable(len(fit.modules) > 0) + self.checkboxes["drones"].Enable(len(fit.drones) > 0) + self.checkboxes["fighters"].Enable(len(fit.fighters) > 0) + self.checkboxes["cargo"].Enable(len(fit.cargo) > 0) + self.checkboxes["appliedImplants"].Enable(len(fit.appliedImplants) > 0) + self.checkboxes["boosters"].Enable(len(fit.boosters) > 0) + + def _collectAffectingSkills(self, thing, char, skillsMap): + for attr in ("item", "charge"): + if attr == "charge" and isinstance(thing, es_Fighter): + continue + subThing = getattr(thing, attr, None) + if subThing is None: + continue + if isinstance(thing, es_Fighter) and attr == "charge": + continue + + if attr == "charge": + cont = getattr(thing, "chargeModifiedAttributes", None) + else: + cont = getattr(thing, "itemModifiedAttributes", None) + + if cont is not None: + for attrName in cont.iterAfflictions(): + for fit, afflictors in cont.getAfflictions(attrName).items(): + for afflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors: + if isinstance(afflictor, Skill) and afflictor.character == char: + skillName = afflictor.item.name + if skillName not in skillsMap: + skillsMap[skillName] = afflictor.level + elif skillsMap[skillName] < afflictor.level: + skillsMap[skillName] = afflictor.level diff --git a/gui/itemStats.py b/gui/itemStats.py index 6377d6f8d..4ed178762 100644 --- a/gui/itemStats.py +++ b/gui/itemStats.py @@ -24,6 +24,7 @@ import config import gui.mainFrame from eos.saveddata.drone import Drone from eos.saveddata.module import Module +from eos.saveddata.ship import Ship from gui.auxWindow import AuxiliaryFrame from gui.bitmap_loader import BitmapLoader from gui.builtinItemStatsViews.itemAffectedBy import ItemAffectedBy @@ -35,6 +36,7 @@ from gui.builtinItemStatsViews.itemEffects import ItemEffects from gui.builtinItemStatsViews.itemMutator import ItemMutatorPanel from gui.builtinItemStatsViews.itemProperties import ItemProperties from gui.builtinItemStatsViews.itemRequirements import ItemRequirements +from gui.builtinItemStatsViews.itemSkills import ItemSkills from gui.builtinItemStatsViews.itemTraits import ItemTraits from service.market import Market @@ -156,6 +158,8 @@ class ItemStatsContainer(wx.Panel): def __init__(self, parent, stuff, item, context=None): wx.Panel.__init__(self, parent) sMkt = Market.getInstance() + self.stuff = stuff + self.context = context mainSizer = wx.BoxSizer(wx.VERTICAL) @@ -196,6 +200,10 @@ class ItemStatsContainer(wx.Panel): self.affectedby = ItemAffectedBy(self.nbContainer, stuff, item) self.nbContainer.AddPage(self.affectedby, _t("Affected by")) + if stuff is not None and isinstance(stuff, Ship): + self.skills = ItemSkills(self.nbContainer, stuff, item) + self.nbContainer.AddPage(self.skills, _t("Skills")) + if config.debug: self.properties = ItemProperties(self.nbContainer, stuff, item, context) self.nbContainer.AddPage(self.properties, _t("Properties"))