Skip to content

Commit f23d1e4

Browse files
authored
Merge pull request #2501 from StormDelay/master
New stats view: bombing resistance
2 parents ce6fd4b + e8e2201 commit f23d1e4

File tree

6 files changed

+179
-0
lines changed

6 files changed

+179
-0
lines changed

gui/builtinPreferenceViews/pyfaStatViewPreferences.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ def populatePanel(self, panel):
106106
rbSizerRow3.Add(self.rbOutgoing, 1, wx.TOP | wx.RIGHT, 5)
107107
self.rbOutgoing.Bind(wx.EVT_RADIOBOX, self.OnOutgoingChange)
108108

109+
self.rbBombing = wx.RadioBox(panel, -1, _t("Bombing"), wx.DefaultPosition, wx.DefaultSize, [_t('None'), _t('Minimal'), _t('Full')], 1,
110+
wx.RA_SPECIFY_COLS)
111+
# Disable minimal as we don't have a view for this yet
112+
self.rbBombing.EnableItem(1, False)
113+
self.rbBombing.SetSelection(self.settings.get('bombing'))
114+
rbSizerRow3.Add(self.rbBombing, 1, wx.TOP | wx.RIGHT, 5)
115+
self.rbBombing.Bind(wx.EVT_RADIOBOX, self.OnBombingChange)
116+
109117
mainSizer.Add(rbSizerRow3, 1, wx.ALL | wx.EXPAND, 0)
110118

111119
panel.SetSizer(mainSizer)
@@ -144,5 +152,7 @@ def OnDroneChange(self, event):
144152
def getImage(self):
145153
return BitmapLoader.getBitmap("settings_stats", "gui")
146154

155+
def OnBombingChange(self, event):
156+
self.settings.set('bombing', event.GetInt())
147157

148158
PFStatViewPref.register()

gui/builtinStatsViews/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
"targetingMiscViewMinimal",
1010
"priceViewFull",
1111
"priceViewMinimal",
12+
"bombingViewFull",
1213
]
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# =============================================================================
2+
# Copyright (C) 2010 Diego Duclos
3+
#
4+
# This file is part of pyfa.
5+
#
6+
# pyfa is free software: you can redistribute it and/or modify
7+
# it under the terms of the GNU General Public License as published by
8+
# the Free Software Foundation, either version 3 of the License, or
9+
# (at your option) any later version.
10+
#
11+
# pyfa is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
18+
# =============================================================================
19+
20+
# noinspection PyPackageRequirements
21+
import wx
22+
import math
23+
24+
import gui.mainFrame
25+
from gui.bitmap_loader import BitmapLoader
26+
from gui.statsView import StatsView
27+
from eos.const import FittingModuleState
28+
from service.market import Market
29+
30+
_t = wx.GetTranslation
31+
32+
33+
class BombingViewFull(StatsView):
34+
name = "bombingViewFull"
35+
36+
def __init__(self, parent):
37+
StatsView.__init__(self)
38+
self.parent = parent
39+
self._cachedValues = []
40+
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
41+
42+
def getHeaderText(self, fit):
43+
return _t("Bombing")
44+
45+
def getTextExtentW(self, text):
46+
width, height = self.parent.GetTextExtent(text)
47+
return width
48+
49+
def populatePanel(self, contentPanel, headerPanel):
50+
contentSizer = contentPanel.GetSizer()
51+
self.panel = contentPanel
52+
53+
self.headerPanel = headerPanel
54+
55+
# Display table
56+
sizerBombing = wx.FlexGridSizer(7, 5, 0, 0)
57+
for i in range(4):
58+
sizerBombing.AddGrowableCol(i + 1)
59+
contentSizer.Add(sizerBombing, 0, wx.EXPAND, 0)
60+
61+
# first row is for icons
62+
bitmap = BitmapLoader.getStaticBitmap("skill_big", contentPanel, "gui")
63+
tooltip = wx.ToolTip(_t("Covert Ops level"))
64+
bitmap.SetToolTip(tooltip)
65+
sizerBombing.Add(bitmap, 0, wx.ALIGN_CENTER)
66+
toolTipText = {
67+
"em": _t("Electron Bomb"),
68+
"thermal": _t("Scorch Bomb"),
69+
"kinetic": _t("Concussion Bomb"),
70+
"explosive": _t("Shrapnel Bomb")
71+
}
72+
for damageType in ("em", "thermal", "kinetic", "explosive"):
73+
bitmap = BitmapLoader.getStaticBitmap("%s_big" % damageType, contentPanel, "gui")
74+
tooltip = wx.ToolTip(toolTipText[damageType])
75+
bitmap.SetToolTip(tooltip)
76+
sizerBombing.Add(bitmap, 0, wx.ALIGN_CENTER)
77+
78+
# the other rows are for each possible level of Covert Ops skill
79+
for covertLevel in ("0", "1", "2", "3", "4", "5"):
80+
label = wx.StaticText(contentPanel, wx.ID_ANY, "%s" % covertLevel)
81+
tooltip = wx.ToolTip(_t("Covert Ops level"))
82+
label.SetToolTip(tooltip)
83+
sizerBombing.Add(label, 0, wx.ALIGN_CENTER)
84+
85+
for damageType in ("em", "thermal", "kinetic", "explosive"):
86+
label = wx.StaticText(contentPanel, wx.ID_ANY, "0.0")
87+
setattr(self, "labelDamagetypeCovertlevel%s%s" % (damageType.capitalize(), covertLevel), label)
88+
sizerBombing.Add(label, 0, wx.ALIGN_CENTER)
89+
90+
def refreshPanel(self, fit):
91+
# If we did anything interesting, we'd update our labels to reflect the new fit's stats here
92+
if fit is None:
93+
return
94+
95+
mkt = Market.getInstance()
96+
emBomb = mkt.getItem(27920)
97+
thermalBomb = mkt.getItem(27916)
98+
kineticBomb = mkt.getItem(27912)
99+
explosiveBomb = mkt.getItem(27918)
100+
environementBombDamageModifier = 1.0
101+
102+
# list all environmental effects affecting bomb damage
103+
relevantEffects = [
104+
'Class 6 Red Giant Effects',
105+
'Class 5 Red Giant Effects',
106+
'Class 4 Red Giant Effects',
107+
'Class 3 Red Giant Effects',
108+
'Class 2 Red Giant Effects',
109+
'Class 1 Red Giant Effects',
110+
]
111+
for effect in fit.projectedModules:
112+
if effect.state == FittingModuleState.ONLINE and effect.fullName in relevantEffects:
113+
# note: despite the name, smartbombDamageMultiplier applies to the damage of launched bombs
114+
environementBombDamageModifier = environementBombDamageModifier *\
115+
effect.item.attributes['smartbombDamageMultiplier'].value
116+
117+
# signature radius of the current fit to calculate the application of bombs
118+
shipSigRadius = fit.ship.getModifiedItemAttr('signatureRadius')
119+
120+
# get the raw values for all hp layers
121+
hullHP = fit.ship.getModifiedItemAttr('hp')
122+
armorHP = fit.ship.getModifiedItemAttr('armorHP')
123+
shieldHP = fit.ship.getModifiedItemAttr('shieldCapacity')
124+
125+
# we calculate the total ehp for pure damage of all types based on raw hp and resonance (resonance= 1-resistance)
126+
emEhp = hullHP / fit.ship.getModifiedItemAttr('emDamageResonance') +\
127+
armorHP / fit.ship.getModifiedItemAttr('armorEmDamageResonance') +\
128+
shieldHP / fit.ship.getModifiedItemAttr('shieldEmDamageResonance')
129+
thermalEhp = hullHP / fit.ship.getModifiedItemAttr('thermalDamageResonance') +\
130+
armorHP / fit.ship.getModifiedItemAttr('armorThermalDamageResonance') +\
131+
shieldHP / fit.ship.getModifiedItemAttr('shieldThermalDamageResonance')
132+
kineticEhp = hullHP / fit.ship.getModifiedItemAttr('kineticDamageResonance') +\
133+
armorHP / fit.ship.getModifiedItemAttr('armorKineticDamageResonance') +\
134+
shieldHP / fit.ship.getModifiedItemAttr('shieldKineticDamageResonance')
135+
explosiveEhp = hullHP / fit.ship.getModifiedItemAttr('explosiveDamageResonance') +\
136+
armorHP / fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance') +\
137+
shieldHP / fit.ship.getModifiedItemAttr('shieldExplosiveDamageResonance')
138+
139+
# updates the labels for each combination of covert op level and damage type
140+
for covertLevel in ("0", "1", "2", "3", "4", "5"):
141+
covertOpsBombDamageModifier = 1 + 0.05 * int(covertLevel)
142+
for damageType, ehp, bomber, bomb in (("em", emEhp, "Purifier", emBomb),
143+
("thermal", thermalEhp, "Nemesis", thermalBomb),
144+
("kinetic", kineticEhp, "Manticore", kineticBomb),
145+
("explosive", explosiveEhp, "Hound", explosiveBomb)):
146+
baseBombDamage = (bomb.attributes['emDamage'].value + bomb.attributes['thermalDamage'].value +
147+
bomb.attributes['kineticDamage'].value + bomb.attributes['explosiveDamage'].value)
148+
appliedBombDamage = baseBombDamage * covertOpsBombDamageModifier * environementBombDamageModifier * \
149+
(min(bomb.attributes['signatureRadius'].value, shipSigRadius) /
150+
bomb.attributes['signatureRadius'].value)
151+
label = getattr(self, "labelDamagetypeCovertlevel%s%s" % (damageType.capitalize(), covertLevel))
152+
label.SetLabel("{:.1f}".format(math.ceil((ehp / appliedBombDamage) * 10) / 10))
153+
if covertLevel is not "0":
154+
label.SetToolTip("Number of %s to kill a %s using a %s "
155+
"with Covert Ops level %s" % (bomb.customName, fit.name, bomber, covertLevel))
156+
else:
157+
label.SetToolTip("Number of %s to kill a %s with Covert Ops level %s" %
158+
(bomb.customName, fit.name, covertLevel))
159+
160+
161+
self.panel.Layout()
162+
self.headerPanel.Layout()
163+
164+
165+
BombingViewFull.register()

gui/statsPane.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class StatsPane(wx.Panel):
4444
"capacitor",
4545
"targetingMisc",
4646
"price",
47+
"bombing",
4748
]
4849

4950
# Don't have these....yet....

gui/statsView.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,5 @@ def refreshPanel(self, fit):
5555
priceViewMinimal,
5656
outgoingViewFull,
5757
outgoingViewMinimal,
58+
bombingViewFull,
5859
)

service/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ def __init__(self):
422422
"miningyield" : 2,
423423
"drones" : 2,
424424
"outgoing" : 2,
425+
"bombing" : 0,
425426
}
426427

427428
self.serviceStatViewDefaultSettings = SettingsProvider.getInstance().getSettings("pyfaServiceStatViewSettings", serviceStatViewDefaultSettings)

0 commit comments

Comments
 (0)