Compare commits

...

54 Commits

Author SHA1 Message Date
DarkPhoenix
52d6c452c7 Bump version 2025-05-27 14:02:25 +02:00
DarkPhoenix
fb3721ace5 Update static data to 2920056 2025-05-27 14:01:23 +02:00
DarkPhoenix
b1f048ac93 Add support for ihub system-wide effects 2025-05-24 14:25:21 +02:00
DarkPhoenix
73b3e347fb Hardcode sov upgrade buffs onto their carrying items 2025-05-24 11:28:56 +02:00
DarkPhoenix
6090d748d2 Add sov upgrade buffs 2025-05-24 10:27:49 +02:00
DarkPhoenix
5e37b5ef77 Bump version 2025-05-24 04:00:06 +02:00
DarkPhoenix
78bb5e7cc0 Add effects for new ships 2025-05-24 03:40:32 +02:00
DarkPhoenix
96c248f477 Update effects for existing ships 2025-05-24 03:14:56 +02:00
DarkPhoenix
696b195bb5 Update icons 2025-05-24 02:41:25 +02:00
DarkPhoenix
b0fa8f1b8c Fix civilian missile launcher in graph 2025-05-24 02:38:28 +02:00
DarkPhoenix
6e173551ed Update RR stacking constant 2025-05-24 02:10:16 +02:00
DarkPhoenix
2fccc7487b Update static data and effects 2025-05-24 02:07:21 +02:00
DarkPhoenix
2f5b674b75 Make "fill cargo" context menu disablable 2025-05-24 01:24:40 +02:00
DarkPhoenix
80ced86ace Put bombing view before prices 2025-05-24 01:18:45 +02:00
DarkPhoenix
de93777f99 Fix comparison to string 2025-05-24 01:14:57 +02:00
Anton Vorobyov
f23d1e4921 Merge pull request #2501 from StormDelay/master
New stats view: bombing resistance
2025-05-24 01:13:52 +02:00
StormDelay
e8e22017cd Merge branch 'pyfa-org:master' into master 2025-05-20 18:33:48 +02:00
StormDelay
e79f97964a Bombing: always round up the number of bomb to the higher first decimal place to avoid misleading display i.e. 7.03 displays 7.1 and not 7.0 2025-05-20 18:30:08 +02:00
StormDelay
138e7cd706 Changed visibility of Bombing panel to None by default 2025-05-20 14:35:37 +02:00
Anton Vorobyov
ce6fd4bd3a Merge pull request #2673 from NicolasKion/master
Add "Fill cargo" feature to item context menu
2025-05-17 02:40:37 +02:00
Nicolas Kion
6e4ca641d7 Allow usage of existing item to fill cargo 2025-05-11 20:28:12 +02:00
Nicolas Kion
46c6381cd9 Add "Fill cargo" menu item 2025-05-11 20:28:02 +02:00
DarkPhoenix
126105cd0d Bump version 2025-04-15 16:41:19 +02:00
DarkPhoenix
fedaa70d9d Update icons 2025-04-15 16:40:56 +02:00
DarkPhoenix
d1707a0dca Update effects 2025-04-15 16:38:48 +02:00
DarkPhoenix
9065d348d3 Update static data 2025-04-15 16:16:22 +02:00
DarkPhoenix
602916c23f Bump version 2025-03-26 16:44:24 +01:00
DarkPhoenix
0d43a8a4c3 Update static data 2025-03-26 16:44:01 +01:00
DarkPhoenix
1e6431a8b3 Update ESI endpoint version 2025-03-26 15:36:53 +01:00
DarkPhoenix
b6067ff0a2 Force publish metenox service 2025-03-18 08:57:55 +01:00
DarkPhoenix
89e426815d Update static data 2025-03-13 12:13:09 +01:00
DarkPhoenix
cf0e88495d Bump version 2025-03-13 12:00:52 +01:00
DarkPhoenix
7c67f18be5 Add drifter incursion beacons 2025-03-13 11:57:09 +01:00
DarkPhoenix
9ab7e0dbac Add trig victory effects 2025-03-13 11:44:24 +01:00
DarkPhoenix
7e92b58c62 Add support for insurgency suppression bonus 2025-03-13 11:28:57 +01:00
DarkPhoenix
9c519b878e Remove debugging stuff 2025-03-12 16:54:41 +01:00
DarkPhoenix
bb07dd8553 Debugging 2025-03-12 16:49:14 +01:00
DarkPhoenix
60555e72d8 Debugging 2025-03-12 16:41:28 +01:00
DarkPhoenix
a457d1d629 Debugging 2025-03-12 16:23:35 +01:00
DarkPhoenix
0e62b29028 Debugging 2025-03-12 16:16:21 +01:00
DarkPhoenix
8a0cb156b2 Debugging 2025-03-12 16:07:26 +01:00
DarkPhoenix
654f8ed7f5 Install requests as a dependency for one of build scripts 2025-03-12 15:37:26 +01:00
DarkPhoenix
cfa927dcd0 Run booster side effect penalties in late stage 2025-03-12 15:20:00 +01:00
DarkPhoenix
4383481a5f Bump version 2025-03-12 15:02:32 +01:00
DarkPhoenix
22063842f9 Add new eos effects 2025-03-12 14:57:14 +01:00
DarkPhoenix
0e5d29a8f9 Update effects 2025-03-12 14:19:45 +01:00
DarkPhoenix
5ee16476dc Update icons 2025-03-12 14:00:09 +01:00
DarkPhoenix
2abb73eab8 Update static data to 2842658 2025-03-12 13:51:22 +01:00
DarkPhoenix
547d8be21e Add debugging functions 2025-03-05 10:32:26 +01:00
DarkPhoenix
b6d8582867 Fix standup fighter export 2025-01-13 23:27:26 +01:00
StormDelay
370cb7eae6 Merge branch 'master' into master 2023-05-23 17:37:09 +02:00
StormDelay
d883935d8c Pulls bomb damage and application from the item statistics and look for Red Giant wormhole effects in the effects applied to the fit 2023-04-08 01:11:43 +02:00
StormDelay
235ca94dba Bombing stat view: added Skill icon for the first column of the table, fixed tooltips to better clarify the information displayed 2023-04-05 21:14:43 +02:00
StormDelay
2dabfe4c79 Created new view for the stats panel that displays a table of the number of damage bomb required to kill the ship, depending on the type of bomb and the covert op skill level of the bomber. 2023-04-05 04:30:01 +02:00
415 changed files with 59869 additions and 19412 deletions

View File

@@ -25,6 +25,7 @@ for:
before_build:
# Prepare pyfa data
- sh: find locale/ -type f -name "*.po" -exec msgen "{}" -o "{}" \;
- sh: pyenv global system
- sh: python3 -B scripts/compile_lang.py
- sh: python3 -B scripts/dump_crowdin_progress.py
- sh: python3 -B db_update.py

View File

@@ -141,6 +141,7 @@ def update_db():
(row['typeName_en-us'].startswith('Civilian') and "Shuttle" not in row['typeName_en-us'])
or row['typeName_en-us'] == 'Capsule'
or row['groupID'] == 4033 # destructible effect beacons
or row['typeID'] == 82941 # Metenox service
or re.match(r'AIR .+Booster.*', row['typeName_en-us'])
):
row['published'] = True
@@ -601,7 +602,7 @@ def update_db():
eos.gamedata.Item.name.like('%mutated%'),
eos.gamedata.Item.name.like('%_PLACEHOLDER%'),
# Drifter weapons are published for some reason
eos.gamedata.Item.name.in_(('Lux Kontos', 'Lux Xiphos'))
eos.gamedata.Item.name.in_(('Lux Kontos', 'Lux Xiphos', 'Lux Ballistra', 'Lux Kopis'))
)).all():
if 'Asteroid Mining Crystal' in item.name:
continue
@@ -642,15 +643,66 @@ def update_db():
else:
attr.value = value
def _hardcodeEffects(typeID, effectMap):
def _hardcodeEffects(typeID, effectMap, clearEffects=True):
item = eos.db.gamedata_session.query(eos.gamedata.Item).filter(eos.gamedata.Item.ID == typeID).one()
item.effects.clear()
if clearEffects:
item.effects.clear()
for effectID, effectName in effectMap.items():
effect = eos.gamedata.Effect()
effect.effectID = effectID
effect.effectName = effectName
try:
effect = eos.db.gamedata_session.query(eos.gamedata.Effect).filter(eos.gamedata.Effect.ID == effectID).one()
except sqlalchemy.orm.exc.NoResultFound:
effect = eos.gamedata.Effect()
effect.effectID = effectID
effect.effectName = effectName
item.effects[effectName] = effect
def hardcodeSuppressionTackleRange():
beaconTypeID = 79839
attrMap = {
'warfareBuff1ID': 2405,
'warfareBuff1Value': 10}
effectMap = {100000: 'pyfaCustomSuppressionTackleRange'}
_hardcodeAttribs(beaconTypeID, attrMap)
_hardcodeEffects(beaconTypeID, effectMap)
eos.db.gamedata_session.flush()
def hardcodeSovUpgradeBuffs():
typeBuffMap = {
# Gamma
87815: {
'warfareBuff1ID': 2433,
'warfareBuff1Value': 5,
'warfareBuff2ID': 2434,
'warfareBuff2Value': 10,
'warfareBuff3ID': 2441,
'warfareBuff3Value': 5},
# Plasma
87949: {
'warfareBuff1ID': 2442,
'warfareBuff1Value': 5,
'warfareBuff2ID': 2435,
'warfareBuff2Value': 5,
'warfareBuff3ID': 2436,
'warfareBuff3Value': 10},
# Electric
87950: {
'warfareBuff1ID': 2437,
'warfareBuff1Value': -25,
'warfareBuff2ID': 2438,
'warfareBuff2Value': 25},
# Exotic
87951: {
'warfareBuff1ID': 2440,
'warfareBuff1Value': 2,
'warfareBuff2ID': 2439,
'warfareBuff2Value': 25}}
effectMap = {100001: 'pyfaCustomSovUpgradeBuffEffect'}
for typeID, attrMap in typeBuffMap.items():
_hardcodeAttribs(typeID, attrMap)
_hardcodeEffects(typeID, effectMap, clearEffects=False)
eos.db.gamedata_session.flush()
def hardcodeShapash():
shapashTypeID = 1000000
_copyItem(srcName='Utu', tgtTypeID=shapashTypeID, tgtName='Shapash')
@@ -794,8 +846,8 @@ def update_db():
_hardcodeAttribs(cybeleTypeID, attrMap)
_hardcodeEffects(cybeleTypeID, effectMap)
# hardcodeShapash()
# hardcodeCybele()
hardcodeSuppressionTackleRange()
hardcodeSovUpgradeBuffs()
eos.db.gamedata_session.commit()
eos.db.gamedata_engine.execute('VACUUM')

File diff suppressed because it is too large Load Diff

View File

@@ -890,6 +890,42 @@ class Fit:
lambda mod: mod.item.group.name == "Stasis Web",
"maxRange", value, stackingPenalties=True)
# Sov upgrades buffs
if warfareBuffID == 2433: # Sov System Modifier Shield HP Bonus
self.ship.boostItemAttr("shieldCapacity", value)
if warfareBuffID == 2434: # Sov System Modifier Capacitor Capacity Bonus
self.ship.boostItemAttr("capacitorCapacity", value)
if warfareBuffID == 2435: # Sov System Modifier Armor HP Bonus
self.ship.boostItemAttr("armorHP", value)
if warfareBuffID == 2436: # Sov System Modifier Overheating Bonus - Includes Ewar
for attr in (
'overloadDurationBonus', 'overloadRofBonus', 'overloadSelfDurationBonus',
'overloadHardeningBonus', 'overloadDamageModifier', 'overloadRangeBonus',
'overloadSpeedFactorBonus', 'overloadECMStrengthBonus', 'overloadECCMStrenghtBonus',
'overloadArmorDamageAmount', 'overloadShieldBonus', 'overloadTrackingModuleStrengthBonus',
'overloadSensorModuleStrengthBonus', 'overloadPainterStrengthBonus',
):
self.modules.filteredItemBoost(lambda mod: attr in mod.itemModifiedAttributes, attr, value)
if warfareBuffID == 2437: # Sov System Modifier Capacitor Recharge Bonus
self.ship.boostItemAttr("rechargeRate", value)
if warfareBuffID == 2438: # Sov System Modifier Targeting and DScan Range Bonus
self.ship.boostItemAttr("maxTargetRange", value)
self.ship.boostItemAttr("maxDirectionalScanRange", value)
if warfareBuffID == 2439: # Sov System Modifier Scan Resolution Bonus
self.ship.boostItemAttr("scanResolution", value)
if warfareBuffID == 2440: # Sov System Modifier Warp Speed Addition
self.ship.increaseItemAttr('warpSpeedMultiplier', value)
if warfareBuffID == 2441: # Sov System Modifier Shield Booster Bonus
self.modules.filteredItemBoost(
lambda mod: (mod.item.requiresSkill("Shield Operation")
or mod.item.requiresSkill("Capital Shield Operation")),
"shieldBonus", value, stackingPenalties=True)
if warfareBuffID == 2442: # Sov System Modifier Armor Repairer Bonus
self.modules.filteredItemBoost(
lambda mod: (mod.item.requiresSkill("Repair Systems")
or mod.item.requiresSkill("Capital Repair Systems")),
"armorDamageAmount", value, stackingPenalties=True)
del self.commandBonuses[warfareBuffID]
def __resetDependentCalcs(self):
@@ -1820,7 +1856,7 @@ class Fit:
# That's right, for considerations of RR diminishing returns cycle time is rounded this way
totalRaw += amount / int(cycleTime)
RR_ADDITION = 7000
RR_MULTIPLIER = 10
RR_MULTIPLIER = 20
appliedRr = 0
for amount, cycleTime in rrList:
rrps = amount / int(cycleTime)

View File

@@ -66,8 +66,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
"""An instance of this class represents a module together with its charge and modified attributes"""
MINING_ATTRIBUTES = ("miningAmount",)
SYSTEM_GROUPS = (
"Effect Beacon", "MassiveEnvironments", "Abyssal Hazards",
"Non-Interactable Object", "Destructible Effect Beacon")
"Effect Beacon", "MassiveEnvironments", "Abyssal Hazards", "Non-Interactable Object",
"Destructible Effect Beacon", "Sovereignty Hub System Effect Generator Upgrades")
def __init__(self, item, baseItem=None, mutaplasmid=None):
"""Initialize a module from the program"""

View File

@@ -58,7 +58,8 @@ def getApplicationPerKey(src, tgt, atkSpeed, atkAngle, distance, tgtSpeed, tgtAn
tgtSigRadius=tgtSigRadius)
else:
applicationMap[mod] = 0
elif mod.hardpoint == FittingHardpoint.MISSILE:
# Missile launcher or civilian missile launcher
elif mod.hardpoint == FittingHardpoint.MISSILE or mod.item.ID == 32461:
# FoF missiles can shoot beyond lock range
if inLockRange or (mod.charge is not None and 'fofMissileLaunching' in mod.charge.effects):
applicationMap[mod] = getLauncherMult(

View File

@@ -36,6 +36,7 @@ from gui.builtinContextMenus import skillAffectors
from gui.builtinContextMenus import itemFill
from gui.builtinContextMenus import droneAddStack
from gui.builtinContextMenus import cargoAdd
from gui.builtinContextMenus import cargoFill
from gui.builtinContextMenus import cargoAddAmmo
from gui.builtinContextMenus import itemProject
from gui.builtinContextMenus import ammoToDmgPattern

View File

@@ -0,0 +1,68 @@
import wx
import gui.fitCommands as cmd
import gui.mainFrame
from gui.contextMenu import ContextMenuSingle
from service.fit import Fit
from eos.saveddata.cargo import Cargo
_t = wx.GetTranslation
class FillCargoWithItem(ContextMenuSingle):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, callingWindow, srcContext, mainItem):
if srcContext not in ("marketItemGroup", "marketItemMisc", "cargoItem"):
return False
if mainItem is None:
return False
if self.mainFrame.getActiveFit() is None:
return False
if srcContext in ("marketItemGroup", "marketItemMisc"):
if not (mainItem.isCharge or mainItem.isCommodity):
return False
return True
def getText(self, callingWindow, itmContext, mainItem):
return _t("Fill Cargo With {0}").format(itmContext)
def activate(self, callingWindow, fullContext, mainItem, i):
fitID = self.mainFrame.getActiveFit()
fit = Fit.getInstance().getFit(fitID)
if isinstance(mainItem, Cargo):
itemVolume = mainItem.item.attributes['volume'].value
itemID = mainItem.itemID
else:
itemVolume = mainItem.attributes['volume'].value
itemID = int(mainItem.ID)
if itemVolume is None or itemVolume <= 0:
return
# Calculate how many items can fit in the cargo
cargoCapacity = fit.ship.getModifiedItemAttr("capacity")
currentCargoVolume = fit.cargoBayUsed
availableVolume = cargoCapacity - currentCargoVolume
if availableVolume <= 0:
return
# Calculate maximum amount that can fit
maxAmount = int(availableVolume / itemVolume)
if maxAmount <= 0:
return
# Add the items to cargo
command = cmd.GuiAddCargoCommand(fitID=fitID, itemID=itemID, amount=maxAmount)
if self.mainFrame.command.Submit(command):
self.mainFrame.additionsPane.select("Cargo", focus=False)
FillCargoWithItem.register()

View File

@@ -123,9 +123,12 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
data.groups[_t('Abyssal Weather')] = self.getAbyssalWeather()
data.groups[_t('Sansha Incursion')] = self.getEffectBeacons(
_t('ContextMenu|ProjectedEffectManipulation|Sansha Incursion'))
data.groups[_t('Drifter Incursion')] = self.getDrifterIncursion()
data.groups[_t('Triglavian Invasion')] = self.getInvasionBeacons()
# data.groups[_t('Pirate Insurgency')] = self.getEffectBeacons(
# _t('ContextMenu|ProjectedEffectManipulation|Insurgency'))
data.groups[_t('Pirate Insurgency')] = self.getEffectBeacons(
_t('ContextMenu|ProjectedEffectManipulation|Insurgency'),
extra_garbage=(_t('ContextMenu|ProjectedEffectManipulation|Beacon'),))
data.groups[_t('IHub Upgrades')] = self.getIHubEffects()
return data
def getEffectBeacons(self, *groups, extra_garbage=()):
@@ -176,7 +179,6 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
container.append(Entry(beacon.ID, beaconname, shortname))
# Break loop on 1st result
break
data.sort()
return data
def getAbyssalWeather(self):
@@ -218,34 +220,42 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
subsubdata.items.append(Entry(beacon.ID, beacon.customName, beacon.customName))
subdata.sort()
# PVP weather
data.items.append(Entry(49766, _t('PvP Weather'), _t('PvP Weather')))
return data
def getDestructibleBeacons(self):
data = Group()
sMkt = Market.getInstance()
for item in sMkt.getItemsByGroup(sMkt.getGroup('Destructible Effect Beacon')):
if not item.isType('projected'):
continue
data.items.append(Entry(item.ID, item.name, item.name))
data.sort()
def getDrifterIncursion(self):
data = self.getEffectBeacons(_t('ContextMenu|ProjectedEffectManipulation|Drifter Incursion'))
# Drifter Crisis
item = Market.getInstance().getItem(87294)
data.items.append(Entry(item.ID, item.name, item.name))
return data
def getInvasionBeacons(self):
data = self.getDestructibleBeacons()
data = Group()
# Trig Minor Victory
item = Market.getInstance().getItem(87177)
data.items.append(Entry(item.ID, item.name, item.name))
# Trig Final Liminality
item = Market.getInstance().getItem(87164)
data.items.append(Entry(item.ID, item.name, item.name))
# Turnur weather
item = Market.getInstance().getItem(74002)
data.items.append(Entry(item.ID, item.name, item.name))
return data
def getInsurgencyBeacons(self):
data = self.getDestructibleBeacons()
# Suppression Interdiction Range Beacon
item = Market.getInstance().getItem(79839)
data.items.append(Entry(item.ID, item.name, item.name))
def getIHubEffects(self):
data = Group()
# Electric
item = Market.getInstance().getItem(87950)
data.items.append(Entry(item.ID, item.name, _t('Electric')))
# Plasma
item = Market.getInstance().getItem(87949)
data.items.append(Entry(item.ID, item.name, _t('Plasma')))
# Exotic
item = Market.getInstance().getItem(87951)
data.items.append(Entry(item.ID, item.name, _t('Exotic')))
# Gamma
item = Market.getInstance().getItem(87815)
data.items.append(Entry(item.ID, item.name, _t('Gamma')))
return data
AddEnvironmentEffect.register()

View File

@@ -68,22 +68,27 @@ class PFContextMenuPref(PreferenceView):
rbSizerRow2.Add(self.rbBox5, 1, wx.ALL, 5)
self.rbBox5.Bind(wx.EVT_RADIOBOX, self.OnSetting5Change)
self.rbBox6 = wx.RadioBox(panel, -1, _t("Spoolup"), wx.DefaultPosition, wx.DefaultSize, [_t('Disabled'), _t('Enabled')], 1, wx.RA_SPECIFY_COLS)
self.rbBox6.SetSelection(self.settings.get('spoolup'))
rbSizerRow2.Add(self.rbBox6, 1, wx.ALL, 5)
self.rbBox6.Bind(wx.EVT_RADIOBOX, self.OnSetting6Change)
mainSizer.Add(rbSizerRow2, 1, wx.ALL | wx.EXPAND, 0)
# Row 3
rbSizerRow3 = wx.BoxSizer(wx.HORIZONTAL)
self.rbBox6 = wx.RadioBox(panel, -1, _t("Spoolup"), wx.DefaultPosition, wx.DefaultSize, [_t('Disabled'), _t('Enabled')], 1, wx.RA_SPECIFY_COLS)
self.rbBox6.SetSelection(self.settings.get('spoolup'))
rbSizerRow3.Add(self.rbBox6, 1, wx.ALL, 5)
self.rbBox6.Bind(wx.EVT_RADIOBOX, self.OnSetting6Change)
self.rbBox7 = wx.RadioBox(panel, -1, _t("Additions Panel Copy/Paste"), wx.DefaultPosition, wx.DefaultSize, [_t('Disabled'), _t('Enabled')], 1,
wx.RA_SPECIFY_COLS)
self.rbBox7.SetSelection(self.settings.get('additionsCopyPaste'))
rbSizerRow3.Add(self.rbBox7, 1, wx.ALL, 5)
self.rbBox7.Bind(wx.EVT_RADIOBOX, self.OnSetting7Change)
self.rbBox8 = wx.RadioBox(panel, -1, _t("Fill cargo with"), wx.DefaultPosition, wx.DefaultSize, [_t('Disabled'), _t('Enabled')], 1, wx.RA_SPECIFY_COLS)
self.rbBox8.SetSelection(self.settings.get('cargoFill'))
rbSizerRow3.Add(self.rbBox8, 1, wx.ALL, 5)
self.rbBox8.Bind(wx.EVT_RADIOBOX, self.OnSetting8Change)
mainSizer.Add(rbSizerRow3, 1, wx.ALL | wx.EXPAND, 0)
panel.SetSizer(mainSizer)
@@ -110,6 +115,9 @@ class PFContextMenuPref(PreferenceView):
def OnSetting7Change(self, event):
self.settings.set('additionsCopyPaste', event.GetInt())
def OnSetting8Change(self, event):
self.settings.set('cargoFill', event.GetInt())
def getImage(self):
return BitmapLoader.getBitmap("settings_menu", "gui")

View File

@@ -106,6 +106,14 @@ class PFStatViewPref(PreferenceView):
rbSizerRow3.Add(self.rbOutgoing, 1, wx.TOP | wx.RIGHT, 5)
self.rbOutgoing.Bind(wx.EVT_RADIOBOX, self.OnOutgoingChange)
self.rbBombing = wx.RadioBox(panel, -1, _t("Bombing"), wx.DefaultPosition, wx.DefaultSize, [_t('None'), _t('Minimal'), _t('Full')], 1,
wx.RA_SPECIFY_COLS)
# Disable minimal as we don't have a view for this yet
self.rbBombing.EnableItem(1, False)
self.rbBombing.SetSelection(self.settings.get('bombing'))
rbSizerRow3.Add(self.rbBombing, 1, wx.TOP | wx.RIGHT, 5)
self.rbBombing.Bind(wx.EVT_RADIOBOX, self.OnBombingChange)
mainSizer.Add(rbSizerRow3, 1, wx.ALL | wx.EXPAND, 0)
panel.SetSizer(mainSizer)
@@ -144,5 +152,7 @@ class PFStatViewPref(PreferenceView):
def getImage(self):
return BitmapLoader.getBitmap("settings_stats", "gui")
def OnBombingChange(self, event):
self.settings.set('bombing', event.GetInt())
PFStatViewPref.register()

View File

@@ -7,6 +7,7 @@ __all__ = [
"outgoingViewFull",
"outgoingViewMinimal",
"targetingMiscViewMinimal",
"bombingViewFull",
"priceViewFull",
"priceViewMinimal",
]

View File

@@ -0,0 +1,165 @@
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import math
import gui.mainFrame
from gui.bitmap_loader import BitmapLoader
from gui.statsView import StatsView
from eos.const import FittingModuleState
from service.market import Market
_t = wx.GetTranslation
class BombingViewFull(StatsView):
name = "bombingViewFull"
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
self._cachedValues = []
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getHeaderText(self, fit):
return _t("Bombing")
def getTextExtentW(self, text):
width, height = self.parent.GetTextExtent(text)
return width
def populatePanel(self, contentPanel, headerPanel):
contentSizer = contentPanel.GetSizer()
self.panel = contentPanel
self.headerPanel = headerPanel
# Display table
sizerBombing = wx.FlexGridSizer(7, 5, 0, 0)
for i in range(4):
sizerBombing.AddGrowableCol(i + 1)
contentSizer.Add(sizerBombing, 0, wx.EXPAND, 0)
# first row is for icons
bitmap = BitmapLoader.getStaticBitmap("skill_big", contentPanel, "gui")
tooltip = wx.ToolTip(_t("Covert Ops level"))
bitmap.SetToolTip(tooltip)
sizerBombing.Add(bitmap, 0, wx.ALIGN_CENTER)
toolTipText = {
"em": _t("Electron Bomb"),
"thermal": _t("Scorch Bomb"),
"kinetic": _t("Concussion Bomb"),
"explosive": _t("Shrapnel Bomb")
}
for damageType in ("em", "thermal", "kinetic", "explosive"):
bitmap = BitmapLoader.getStaticBitmap("%s_big" % damageType, contentPanel, "gui")
tooltip = wx.ToolTip(toolTipText[damageType])
bitmap.SetToolTip(tooltip)
sizerBombing.Add(bitmap, 0, wx.ALIGN_CENTER)
# the other rows are for each possible level of Covert Ops skill
for covertLevel in ("0", "1", "2", "3", "4", "5"):
label = wx.StaticText(contentPanel, wx.ID_ANY, "%s" % covertLevel)
tooltip = wx.ToolTip(_t("Covert Ops level"))
label.SetToolTip(tooltip)
sizerBombing.Add(label, 0, wx.ALIGN_CENTER)
for damageType in ("em", "thermal", "kinetic", "explosive"):
label = wx.StaticText(contentPanel, wx.ID_ANY, "0.0")
setattr(self, "labelDamagetypeCovertlevel%s%s" % (damageType.capitalize(), covertLevel), label)
sizerBombing.Add(label, 0, wx.ALIGN_CENTER)
def refreshPanel(self, fit):
# If we did anything interesting, we'd update our labels to reflect the new fit's stats here
if fit is None:
return
mkt = Market.getInstance()
emBomb = mkt.getItem(27920)
thermalBomb = mkt.getItem(27916)
kineticBomb = mkt.getItem(27912)
explosiveBomb = mkt.getItem(27918)
environementBombDamageModifier = 1.0
# list all environmental effects affecting bomb damage
relevantEffects = [
'Class 6 Red Giant Effects',
'Class 5 Red Giant Effects',
'Class 4 Red Giant Effects',
'Class 3 Red Giant Effects',
'Class 2 Red Giant Effects',
'Class 1 Red Giant Effects',
]
for effect in fit.projectedModules:
if effect.state == FittingModuleState.ONLINE and effect.fullName in relevantEffects:
# note: despite the name, smartbombDamageMultiplier applies to the damage of launched bombs
environementBombDamageModifier = environementBombDamageModifier *\
effect.item.attributes['smartbombDamageMultiplier'].value
# signature radius of the current fit to calculate the application of bombs
shipSigRadius = fit.ship.getModifiedItemAttr('signatureRadius')
# get the raw values for all hp layers
hullHP = fit.ship.getModifiedItemAttr('hp')
armorHP = fit.ship.getModifiedItemAttr('armorHP')
shieldHP = fit.ship.getModifiedItemAttr('shieldCapacity')
# we calculate the total ehp for pure damage of all types based on raw hp and resonance (resonance= 1-resistance)
emEhp = hullHP / fit.ship.getModifiedItemAttr('emDamageResonance') +\
armorHP / fit.ship.getModifiedItemAttr('armorEmDamageResonance') +\
shieldHP / fit.ship.getModifiedItemAttr('shieldEmDamageResonance')
thermalEhp = hullHP / fit.ship.getModifiedItemAttr('thermalDamageResonance') +\
armorHP / fit.ship.getModifiedItemAttr('armorThermalDamageResonance') +\
shieldHP / fit.ship.getModifiedItemAttr('shieldThermalDamageResonance')
kineticEhp = hullHP / fit.ship.getModifiedItemAttr('kineticDamageResonance') +\
armorHP / fit.ship.getModifiedItemAttr('armorKineticDamageResonance') +\
shieldHP / fit.ship.getModifiedItemAttr('shieldKineticDamageResonance')
explosiveEhp = hullHP / fit.ship.getModifiedItemAttr('explosiveDamageResonance') +\
armorHP / fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance') +\
shieldHP / fit.ship.getModifiedItemAttr('shieldExplosiveDamageResonance')
# updates the labels for each combination of covert op level and damage type
for covertLevel in ("0", "1", "2", "3", "4", "5"):
covertOpsBombDamageModifier = 1 + 0.05 * int(covertLevel)
for damageType, ehp, bomber, bomb in (("em", emEhp, "Purifier", emBomb),
("thermal", thermalEhp, "Nemesis", thermalBomb),
("kinetic", kineticEhp, "Manticore", kineticBomb),
("explosive", explosiveEhp, "Hound", explosiveBomb)):
baseBombDamage = (bomb.attributes['emDamage'].value + bomb.attributes['thermalDamage'].value +
bomb.attributes['kineticDamage'].value + bomb.attributes['explosiveDamage'].value)
appliedBombDamage = baseBombDamage * covertOpsBombDamageModifier * environementBombDamageModifier * \
(min(bomb.attributes['signatureRadius'].value, shipSigRadius) /
bomb.attributes['signatureRadius'].value)
label = getattr(self, "labelDamagetypeCovertlevel%s%s" % (damageType.capitalize(), covertLevel))
label.SetLabel("{:.1f}".format(math.ceil((ehp / appliedBombDamage) * 10) / 10))
if covertLevel != "0":
label.SetToolTip("Number of %s to kill a %s using a %s "
"with Covert Ops level %s" % (bomb.customName, fit.name, bomber, covertLevel))
else:
label.SetToolTip("Number of %s to kill a %s with Covert Ops level %s" %
(bomb.customName, fit.name, covertLevel))
self.panel.Layout()
self.headerPanel.Layout()
BombingViewFull.register()

View File

@@ -481,6 +481,35 @@ class SkillTreeView(wx.Panel):
toClipboard(list)
def exportSkillsSuperCondensed(self, evt):
char = self.charEditor.entityEditor.getActiveEntity()
skills = {}
explicit_levels = {}
implicit_levels = {}
for s in char.__class__.getSkillNameMap().keys():
skill = char.getSkill(s)
if skill.level < 1:
continue
skills[skill.item.ID] = skill
explicit_levels[skill.item.ID] = skill.level
for skill in skills.values():
for req_skill, level in skill.item.requiredSkills.items():
if req_skill.ID not in implicit_levels or implicit_levels[req_skill.ID] < level:
implicit_levels[req_skill.ID] = level
condensed = {}
for typeID, level in explicit_levels.items():
if typeID not in implicit_levels or implicit_levels[typeID] < level:
condensed[skills[typeID].item.name] = level
lines = []
for skill in sorted(condensed):
lines.append(f'{skill}\t{condensed[skill]}')
toClipboard('\n'.join(lines))
def onSecStatus(self, event):
sChar = Character.getInstance()
char = self.charEditor.entityEditor.getActiveEntity()

View File

@@ -43,6 +43,7 @@ class StatsPane(wx.Panel):
"outgoing",
"capacitor",
"targetingMisc",
"bombing",
"price",
]

View File

@@ -51,6 +51,7 @@ from gui.builtinStatsViews import ( # noqa: E402, F401
capacitorViewFull,
rechargeViewFull,
targetingMiscViewMinimal,
bombingViewFull,
priceViewFull,
priceViewMinimal,
outgoingViewFull,

BIN
imgs/icons/10877@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

BIN
imgs/icons/10877@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
imgs/icons/1156@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

BIN
imgs/icons/1156@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 787 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 B

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 818 B

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 808 B

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 807 B

After

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 816 B

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 809 B

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 823 B

After

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 B

After

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

After

Width:  |  Height:  |  Size: 792 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 821 B

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 839 B

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 819 B

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 817 B

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 B

After

Width:  |  Height:  |  Size: 801 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 823 B

After

Width:  |  Height:  |  Size: 789 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 780 B

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 829 B

After

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 821 B

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 784 B

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 808 B

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 829 B

After

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 783 B

After

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 814 B

After

Width:  |  Height:  |  Size: 841 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 B

After

Width:  |  Height:  |  Size: 840 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 782 B

After

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 816 B

After

Width:  |  Height:  |  Size: 850 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 823 B

After

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 787 B

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 836 B

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 846 B

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 848 B

After

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 816 B

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 B

After

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Some files were not shown because too many files have changed in this diff Show More