Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52d6c452c7 | ||
|
|
fb3721ace5 | ||
|
|
b1f048ac93 | ||
|
|
73b3e347fb | ||
|
|
6090d748d2 | ||
|
|
5e37b5ef77 | ||
|
|
78bb5e7cc0 | ||
|
|
96c248f477 | ||
|
|
696b195bb5 | ||
|
|
b0fa8f1b8c | ||
|
|
6e173551ed | ||
|
|
2fccc7487b | ||
|
|
2f5b674b75 | ||
|
|
80ced86ace | ||
|
|
de93777f99 | ||
|
|
f23d1e4921 | ||
|
|
e8e22017cd | ||
|
|
e79f97964a | ||
|
|
138e7cd706 | ||
|
|
ce6fd4bd3a | ||
|
|
6e4ca641d7 | ||
|
|
46c6381cd9 | ||
|
|
126105cd0d | ||
|
|
fedaa70d9d | ||
|
|
d1707a0dca | ||
|
|
9065d348d3 | ||
|
|
602916c23f | ||
|
|
0d43a8a4c3 | ||
|
|
1e6431a8b3 | ||
|
|
b6067ff0a2 | ||
|
|
89e426815d | ||
|
|
cf0e88495d | ||
|
|
7c67f18be5 | ||
|
|
9ab7e0dbac | ||
|
|
7e92b58c62 | ||
|
|
9c519b878e | ||
|
|
bb07dd8553 | ||
|
|
60555e72d8 | ||
|
|
a457d1d629 | ||
|
|
0e62b29028 | ||
|
|
8a0cb156b2 | ||
|
|
654f8ed7f5 | ||
|
|
cfa927dcd0 | ||
|
|
4383481a5f | ||
|
|
22063842f9 | ||
|
|
0e5d29a8f9 | ||
|
|
5ee16476dc | ||
|
|
2abb73eab8 | ||
|
|
547d8be21e | ||
|
|
b6d8582867 | ||
|
|
370cb7eae6 | ||
|
|
d883935d8c | ||
|
|
235ca94dba | ||
|
|
2dabfe4c79 |
@@ -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
|
||||
|
||||
68
db_update.py
@@ -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')
|
||||
|
||||
749
eos/effects.py
@@ -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)
|
||||
|
||||
@@ -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"""
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
68
gui/builtinContextMenus/cargoFill.py
Normal 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()
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -7,6 +7,7 @@ __all__ = [
|
||||
"outgoingViewFull",
|
||||
"outgoingViewMinimal",
|
||||
"targetingMiscViewMinimal",
|
||||
"bombingViewFull",
|
||||
"priceViewFull",
|
||||
"priceViewMinimal",
|
||||
]
|
||||
|
||||
165
gui/builtinStatsViews/bombingViewFull.py
Normal 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()
|
||||
@@ -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()
|
||||
|
||||
@@ -43,6 +43,7 @@ class StatsPane(wx.Panel):
|
||||
"outgoing",
|
||||
"capacitor",
|
||||
"targetingMisc",
|
||||
"bombing",
|
||||
"price",
|
||||
]
|
||||
|
||||
|
||||
@@ -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
|
After Width: | Height: | Size: 721 B |
BIN
imgs/icons/10877@2x.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
imgs/icons/1156@1x.png
Normal file
|
After Width: | Height: | Size: 762 B |
BIN
imgs/icons/1156@2x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 433 B After Width: | Height: | Size: 539 B |
|
Before Width: | Height: | Size: 944 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 717 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 804 B After Width: | Height: | Size: 787 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 788 B After Width: | Height: | Size: 799 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 818 B After Width: | Height: | Size: 796 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 808 B After Width: | Height: | Size: 785 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 807 B After Width: | Height: | Size: 756 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 816 B After Width: | Height: | Size: 806 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 809 B After Width: | Height: | Size: 816 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 823 B After Width: | Height: | Size: 805 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 820 B After Width: | Height: | Size: 756 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 831 B After Width: | Height: | Size: 792 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 821 B After Width: | Height: | Size: 803 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 839 B After Width: | Height: | Size: 798 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 819 B After Width: | Height: | Size: 747 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 817 B After Width: | Height: | Size: 790 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 820 B After Width: | Height: | Size: 801 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 823 B After Width: | Height: | Size: 789 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 780 B After Width: | Height: | Size: 769 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 829 B After Width: | Height: | Size: 805 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 821 B After Width: | Height: | Size: 796 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 824 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 784 B After Width: | Height: | Size: 809 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 808 B After Width: | Height: | Size: 847 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 829 B After Width: | Height: | Size: 856 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 833 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 783 B After Width: | Height: | Size: 802 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 814 B After Width: | Height: | Size: 841 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 825 B After Width: | Height: | Size: 840 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 821 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 782 B After Width: | Height: | Size: 821 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 816 B After Width: | Height: | Size: 850 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 823 B After Width: | Height: | Size: 839 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 814 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 787 B After Width: | Height: | Size: 794 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 836 B After Width: | Height: | Size: 847 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 846 B After Width: | Height: | Size: 853 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 848 B After Width: | Height: | Size: 852 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 816 B After Width: | Height: | Size: 807 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 778 B After Width: | Height: | Size: 797 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |