From 48981460ab752b09f735817fe7f8b5b0c1e1eb64 Mon Sep 17 00:00:00 2001 From: DarkPhoenix Date: Mon, 29 Aug 2022 01:56:15 +0400 Subject: [PATCH] Add drone EHP and shield regen columns --- eos/saveddata/damagePattern.py | 12 ++-- eos/saveddata/drone.py | 25 +++++++ eos/saveddata/fighter.py | 25 +++++++ eos/saveddata/fit.py | 2 +- graphs/wrapper.py | 2 +- gui/builtinAdditionPanes/droneView.py | 2 + gui/builtinAdditionPanes/fighterView.py | 2 + gui/builtinViewColumns/droneEhp.py | 87 ++++++++++++++++++++++++ gui/builtinViewColumns/droneRegen.py | 81 ++++++++++++++++++++++ gui/viewColumn.py | 2 + imgs/gui/shieldPassive_small.png | Bin 0 -> 662 bytes service/port/shipstats.py | 2 +- 12 files changed, 233 insertions(+), 9 deletions(-) create mode 100644 gui/builtinViewColumns/droneEhp.py create mode 100644 gui/builtinViewColumns/droneRegen.py create mode 100644 imgs/gui/shieldPassive_small.png diff --git a/eos/saveddata/damagePattern.py b/eos/saveddata/damagePattern.py index 3a9357873..bd792e733 100644 --- a/eos/saveddata/damagePattern.py +++ b/eos/saveddata/damagePattern.py @@ -216,11 +216,11 @@ class DamagePattern: pattern.builtin = True cls._builtins[id] = pattern - def calculateEhp(self, fit): + def calculateEhp(self, item): ehp = {} for (type, attr) in (('shield', 'shieldCapacity'), ('armor', 'armorHP'), ('hull', 'hp')): - rawCapacity = fit.ship.getModifiedItemAttr(attr) - ehp[type] = self.effectivify(fit, rawCapacity, type) + rawCapacity = item.getModifiedItemAttr(attr) + ehp[type] = self.effectivify(item, rawCapacity, type) return ehp @@ -236,10 +236,10 @@ class DamagePattern: ereps = {} for field in tankInfo: if field in typeMap: - ereps[field] = self.effectivify(fit, tankInfo[field], typeMap[field]) + ereps[field] = self.effectivify(fit.ship, tankInfo[field], typeMap[field]) return ereps - def effectivify(self, fit, amount, type): + def effectivify(self, item, amount, type): type = type if type != "hull" else "" totalDamage = sum((self.emAmount, self.thermalAmount, self.kineticAmount, self.explosiveAmount)) specificDivider = 0 @@ -248,7 +248,7 @@ class DamagePattern: attrName = "%s%sDamageResonance" % (type, damageType.capitalize()) attrName = attrName[0].lower() + attrName[1:] - resonance = fit.ship.getModifiedItemAttr(attrName) + resonance = item.getModifiedItemAttr(attrName) damage = getattr(self, "%sAmount" % damageType) specificDivider += damage / float(totalDamage or 1) * resonance diff --git a/eos/saveddata/drone.py b/eos/saveddata/drone.py index 93c037bbd..cdefc1799 100644 --- a/eos/saveddata/drone.py +++ b/eos/saveddata/drone.py @@ -82,6 +82,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu self.__baseRRAmount = None self.__miningYield = None self.__miningWaste = None + self.__ehp = None self.__itemModifiedAttributes = ModifiedAttributeDict() self.__itemModifiedAttributes.original = self._item.attributes self.__itemModifiedAttributes.overrides = self._item.overrides @@ -287,6 +288,29 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu if delay is not None and speed is not None: return delay / 1000.0 * speed + @property + def hp(self): + hp = {} + for (type, attr) in (('shield', 'shieldCapacity'), ('armor', 'armorHP'), ('hull', 'hp')): + hp[type] = self.getModifiedItemAttr(attr) + + return hp + + @property + def ehp(self): + if self.__ehp is None: + if self.owner is None or self.owner.damagePattern is None: + ehp = self.hp + else: + ehp = self.owner.damagePattern.calculateEhp(self) + self.__ehp = ehp + return self.__ehp + + def calculateShieldRecharge(self): + capacity = self.getModifiedItemAttr("shieldCapacity") + rechargeRate = self.getModifiedItemAttr("shieldRechargeRate") / 1000.0 + return 10 / rechargeRate * math.sqrt(0.25) * (1 - math.sqrt(0.25)) * capacity + # Had to add this to match the falloff property in modules.py # Fscking ship scanners. If you find any other falloff attributes, # Put them in the attrs tuple. @@ -318,6 +342,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu self.__baseRRAmount = None self.__miningYield = None self.__miningWaste = None + self.__ehp = None self.itemModifiedAttributes.clear() self.chargeModifiedAttributes.clear() diff --git a/eos/saveddata/fighter.py b/eos/saveddata/fighter.py index 2192aaeea..012e0b8ce 100644 --- a/eos/saveddata/fighter.py +++ b/eos/saveddata/fighter.py @@ -96,6 +96,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): self.__charge = None self.__baseVolley = None self.__miningyield = None + self.__ehp = None self.__itemModifiedAttributes = ModifiedAttributeDict() self.__chargeModifiedAttributes = ModifiedAttributeDict() @@ -345,6 +346,29 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if falloff is not None: return falloff + @property + def hp(self): + hp = {} + for (type, attr) in (('shield', 'shieldCapacity'), ('armor', 'armorHP'), ('hull', 'hp')): + hp[type] = self.getModifiedItemAttr(attr) + + return hp + + @property + def ehp(self): + if self.__ehp is None: + if self.owner is None or self.owner.damagePattern is None: + ehp = self.hp + else: + ehp = self.owner.damagePattern.calculateEhp(self) + self.__ehp = ehp + return self.__ehp + + def calculateShieldRecharge(self): + capacity = self.getModifiedItemAttr("shieldCapacity") + rechargeRate = self.getModifiedItemAttr("shieldRechargeRate") / 1000.0 + return 10 / rechargeRate * math.sqrt(0.25) * (1 - math.sqrt(0.25)) * capacity + @validates("ID", "itemID", "chargeID", "amount") def validator(self, key, val): map = { @@ -361,6 +385,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): def clear(self): self.__baseVolley = None self.__miningyield = None + self.__ehp = None self.itemModifiedAttributes.clear() self.chargeModifiedAttributes.clear() [x.clear() for x in self.abilities] diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 700643ec9..64d8de84c 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -1469,7 +1469,7 @@ class Fit: if self.damagePattern is None: ehp = self.hp else: - ehp = self.damagePattern.calculateEhp(self) + ehp = self.damagePattern.calculateEhp(self.ship) self.__ehp = ehp return self.__ehp diff --git a/graphs/wrapper.py b/graphs/wrapper.py index 566d3a1c4..5d8992391 100644 --- a/graphs/wrapper.py +++ b/graphs/wrapper.py @@ -199,7 +199,7 @@ def _getAutoResists(fit): armorHp = hpData['armor'] hullHp = hpData['hull'] uniformDamagePattern = DamagePattern(emAmount=25, thermalAmount=25, kineticAmount=25, explosiveAmount=25) - ehpData = uniformDamagePattern.calculateEhp(fit) + ehpData = uniformDamagePattern.calculateEhp(fit.ship) shieldEhp = ehpData['shield'] armorEhp = ehpData['armor'] hullEhp = ehpData['hull'] diff --git a/gui/builtinAdditionPanes/droneView.py b/gui/builtinAdditionPanes/droneView.py index 209f7fc00..f8db01b7c 100644 --- a/gui/builtinAdditionPanes/droneView.py +++ b/gui/builtinAdditionPanes/droneView.py @@ -66,6 +66,8 @@ class DroneView(Display): "Max Range", "Miscellanea", "attr:maxVelocity", + "Drone HP", + "Drone Regen", "Price", ] diff --git a/gui/builtinAdditionPanes/fighterView.py b/gui/builtinAdditionPanes/fighterView.py index ccb92c5e1..40279b9bf 100644 --- a/gui/builtinAdditionPanes/fighterView.py +++ b/gui/builtinAdditionPanes/fighterView.py @@ -151,6 +151,8 @@ class FighterDisplay(d.Display): # "Max Range", # "Miscellanea", "attr:maxVelocity", + "Drone HP", + "Drone Regen", "Fighter Abilities", "Price", ] diff --git a/gui/builtinViewColumns/droneEhp.py b/gui/builtinViewColumns/droneEhp.py new file mode 100644 index 000000000..865e03a60 --- /dev/null +++ b/gui/builtinViewColumns/droneEhp.py @@ -0,0 +1,87 @@ +# ============================================================================= +# Copyright (C) 2010 Diego Duclos +# +# This file is part of pyfa. +# +# pyfa is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pyfa 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pyfa. If not, see . +# ============================================================================= + +# noinspection PyPackageRequirements +import wx + +import gui.mainFrame +from eos.saveddata.drone import Drone +from eos.saveddata.fighter import Fighter +from service.attribute import Attribute +from gui.viewColumn import ViewColumn +from gui.bitmap_loader import BitmapLoader +from gui.utils.numberFormatter import formatAmount + + +_t = wx.GetTranslation + + +class DroneEhpColumn(ViewColumn): + name = "Drone HP" + + def __init__(self, fittingView, params=None): + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + if params is None: + params = {"showIcon": True, "displayName": False} + + ViewColumn.__init__(self, fittingView) + + sAttr = Attribute.getInstance() + info = sAttr.getAttributeInfo("shieldCapacity") + self.info = info + if params["showIcon"]: + iconFile = info.iconID + if iconFile: + self.imageId = fittingView.imageList.GetImageIndex(iconFile, "icons") + self.bitmap = BitmapLoader.getBitmap(iconFile, "icons") + else: + self.imageId = -1 + self.mask = wx.LIST_MASK_IMAGE + else: + self.imageId = -1 + + if params["displayName"] or self.imageId == -1: + self.columnText = info.displayName if info.displayName != "" else info.name + self.mask |= wx.LIST_MASK_TEXT + + def getText(self, stuff): + if not isinstance(stuff, (Drone, Fighter)): + return "" + if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective: + ehp = sum(stuff.ehp.values()) + else: + ehp = sum(stuff.hp.values()) + return formatAmount(ehp, 3, 0, 9) + + def getImageId(self, mod): + return -1 + + def getParameters(self): + return ("displayName", bool, False), ("showIcon", bool, True) + + def getToolTip(self, stuff): + if not isinstance(stuff, (Drone, Fighter)): + return "" + if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective: + return _t("Effective HP") + else: + return _t("HP") + + +DroneEhpColumn.register() diff --git a/gui/builtinViewColumns/droneRegen.py b/gui/builtinViewColumns/droneRegen.py new file mode 100644 index 000000000..4fba6a2c5 --- /dev/null +++ b/gui/builtinViewColumns/droneRegen.py @@ -0,0 +1,81 @@ +# ============================================================================= +# Copyright (C) 2010 Diego Duclos +# +# This file is part of pyfa. +# +# pyfa is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pyfa 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pyfa. If not, see . +# ============================================================================= + +# noinspection PyPackageRequirements +import wx + +import gui.mainFrame +from eos.saveddata.drone import Drone +from eos.saveddata.fighter import Fighter +from gui.viewColumn import ViewColumn +from gui.bitmap_loader import BitmapLoader +from gui.utils.numberFormatter import formatAmount + + +_t = wx.GetTranslation + + +class DroneRegenColumn(ViewColumn): + name = "Drone Regen" + + def __init__(self, fittingView, params=None): + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + if params is None: + params = {"showIcon": True, "displayName": False} + + ViewColumn.__init__(self, fittingView) + + if params["showIcon"]: + self.imageId = fittingView.imageList.GetImageIndex("shieldPassive_small", "gui") + self.bitmap = BitmapLoader.getBitmap("shieldPassive_small", "gui") + self.mask = wx.LIST_MASK_IMAGE + else: + self.imageId = -1 + + if params["displayName"] or self.imageId == -1: + self.columnText = _("Misc data") + self.mask |= wx.LIST_MASK_TEXT + + def getText(self, stuff): + if not isinstance(stuff, (Drone, Fighter)): + return "" + regen = stuff.calculateShieldRecharge() + if ( + self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective + and stuff.owner and stuff.owner.damagePattern is not None + ): + regen = stuff.owner.damagePattern.effectivify(stuff, regen, 'shield') + return '{}/s'.format(formatAmount(regen, 3, 0, 9)) + + def getImageId(self, mod): + return -1 + + def getParameters(self): + return ("displayName", bool, False), ("showIcon", bool, True) + + def getToolTip(self, stuff): + if not isinstance(stuff, (Drone, Fighter)): + return "" + if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective: + return _t("Effective Shield Regeneration") + else: + return _t("Shield Regeneration") + + +DroneRegenColumn.register() diff --git a/gui/viewColumn.py b/gui/viewColumn.py index 43bed258c..0c904fa27 100644 --- a/gui/viewColumn.py +++ b/gui/viewColumn.py @@ -78,6 +78,8 @@ from gui.builtinViewColumns import ( # noqa: E402, F401 baseName, capacitorUse, dampScanRes, + droneEhp, + droneRegen, graphColor, graphLightness, graphLineStyle, diff --git a/imgs/gui/shieldPassive_small.png b/imgs/gui/shieldPassive_small.png new file mode 100644 index 0000000000000000000000000000000000000000..65a205f0ecfb1e4473440489abf3ba341357a4c3 GIT binary patch literal 662 zcmV;H0%`q;P)?)XWs!yl4@D4>bcihJ574AbA#@R= zQ$>P_QACuXNiQy?B9*$jo9Mct&c4j-{AOq8*TI8iLI-=`d-?KwKk((@A&fC>MjSS& z{|}fCk8-f0IeomHvCTFTZGNJkh7d z69dDe6Cukoo7emK^^4f#SCN@@6}gV0iei@tIak8$LJEc6GSr^G;{V*=S2H^PJ?O36 zlQ?$t$Qqy=;Qfqwj-P7qtFjDcn#kL=AMTnZwJzunCkvO8!D0m9s z;VK{-0xXZNn@Ph$LB@iS(x7V;JGX6zyTps9Pdd{r?d@S^SOR!Xq?GEM2w)$8n*inj zEuG0|@s%hHnu3-}!!QhR`T_=DK8BmjZmHc}?nFEu5)#R{&*uY202~5v7Jv%dEc3d; zvDs-*RYfee3@vS-t+NZB{1ifwWa81Q;R%>D<8(OKA2E6W+yTcv(flrFsefcXGK1*i zJXGDlxx)uA@L|MgYVG=FTiI?x$gfBw@^_340510S&fJ{}HJ((IOQl8fL6;~>DLpIS zy8rxRHmP?Iuy?wyXCz4i0Fd=%vKfOzmI=+$0`SsSB~V<>^MY$I_;W}QgfOMlCWNdV wFvd0<+qR)73dCHI5JH4NAh4m2Y_`t70b$WB`1bY!W&i*H07*qoM6N<$g2Wj!asU7T literal 0 HcmV?d00001 diff --git a/service/port/shipstats.py b/service/port/shipstats.py index 0f4108ba5..fc2f67d04 100644 --- a/service/port/shipstats.py +++ b/service/port/shipstats.py @@ -36,7 +36,7 @@ def tankSection(fit): ehp.append(sum(ehp)) ehpStr = [formatAmount(ehpVal, 3, 0, 9) for ehpVal in ehp] resists = {tankType: [1 - fit.ship.getModifiedItemAttr(s) for s in resonanceNames[tankType]] for tankType in tankTypes} - ehpAgainstDamageType = [sum(pattern.calculateEhp(fit).values()) for pattern in damagePatterns] + ehpAgainstDamageType = [sum(pattern.calculateEhp(fit.ship).values()) for pattern in damagePatterns] ehpAgainstDamageTypeStr = [formatAmount(ehpVal, 3, 0, 9) for ehpVal in ehpAgainstDamageType] # not used for now. maybe will be improved later