Compare commits

..

51 Commits

Author SHA1 Message Date
DarkPhoenix
83973dda73 Bump macos image version, p2 2026-01-11 21:11:07 +01:00
DarkPhoenix
e68530d08c Bump macos image version 2026-01-11 19:30:41 +01:00
DarkPhoenix
750ed8b6fa Bump version 2026-01-11 18:05:06 +01:00
Anton Vorobyov
8225dc8f49 Merge pull request #2675 from tsadler1988/contributing-suggested-changes
CONTRIBUTING.md suggested changes
2026-01-11 20:24:40 +04:00
DarkPhoenix
ec4a0743b8 Add new packages to linux build 2026-01-11 17:19:22 +01:00
Anton Vorobyov
2201dde8ed Merge pull request #2706 from freeone3000/master
fix: Fixed clipboard issues on Wayland, using pyclip instead of wx
2026-01-11 20:12:32 +04:00
Anton Vorobyov
3a324b9f9f Merge pull request #2713 from alexjurkiewicz/tox-py-minver
Update minimum Python version in tox.ini
2026-01-11 20:11:23 +04:00
DarkPhoenix
11dcc31554 Update effects 2026-01-11 15:49:34 +01:00
DarkPhoenix
074048890c Update static data 2026-01-11 15:17:59 +01:00
Alex Jurkiewicz
4ac1627b33 Update minimum Python version in tox.ini
To match the minimum version specified in CONTRIBUTING.md.
2026-01-02 09:04:43 +08:00
Jasmine Moore
84f532284e fix: remove debug statement 2025-12-17 12:31:05 -05:00
Jasmine Moore
ccbe88d3bf fix: Fixed clipboard issues on Wayland, using pyclip instead of wx 2025-12-17 12:26:36 -05:00
DarkPhoenix
c7074f499f Add a guard against situation where fit is empty for some reason 2025-12-15 12:18:52 +01:00
DarkPhoenix
f6f3a69be4 Fail build if image tool couldn't be fetched 2025-12-11 19:21:03 +01:00
DarkPhoenix
23e09729f7 CCP mistype is actually a mistype on my part 2025-12-11 18:50:14 +01:00
DarkPhoenix
0aca05704f Bump version 2025-12-11 18:03:49 +01:00
DarkPhoenix
b08894e984 Anhinga effect changes 2025-12-11 18:03:32 +01:00
DarkPhoenix
a1bc8742c9 Add new renders 2025-12-11 15:58:02 +01:00
DarkPhoenix
6472cabc05 Update static data and make some changes to support new AT ships 2025-12-11 15:54:11 +01:00
DarkPhoenix
56bb8217d3 Do not fail whole app when ESI access object fails instantiation 2025-12-10 19:22:52 +01:00
DarkPhoenix
17f9071317 Bump version 2025-12-09 15:28:26 +01:00
DarkPhoenix
50eda1f4db Add option to copy condensed skill list 2025-12-09 15:26:17 +01:00
DarkPhoenix
84fbc0a46c Fix clipboard on my wayland installation 2025-12-09 15:08:38 +01:00
Anton Vorobyov
9551195078 Merge pull request #2700 from skyride/master
Fixed bug with Clipboard on Wayland
2025-12-09 17:49:24 +04:00
DarkPhoenix
f01949d892 Add expedition hold display 2025-12-09 14:44:43 +01:00
DarkPhoenix
26b4c05b6f Stacking penalize residue probability attribute 2025-12-09 14:41:40 +01:00
Anton Vorobyov
6ecab03fd8 Merge pull request #2683 from cryonox/dev/refresh_tokens
Refresh tokens when pyfa start to avoid expiry
2025-12-09 17:35:55 +04:00
DarkPhoenix
edc0418d9a Add perserverance effects 2025-12-09 14:31:05 +01:00
DarkPhoenix
1d413595b9 Update icons 2025-12-09 14:17:49 +01:00
DarkPhoenix
ce5a593f7b Add missing wightstorm booster effects 2025-12-09 14:15:35 +01:00
DarkPhoenix
faea6a97f0 Update static data 2025-12-09 14:13:14 +01:00
Amy Findlay
b92913cbf9 Fixed bug with Clipboard on Wayland 2025-11-22 19:57:55 +01:00
DarkPhoenix
1af2e7f94b Bump version & update static data 2025-11-18 12:38:44 +01:00
DarkPhoenix
dbb61a8a37 Change presentation of mining info 2025-11-17 17:25:25 +01:00
DarkPhoenix
b12adcae3d Add slowdown modifier to effects of grappler 2025-11-15 21:04:56 +01:00
DarkPhoenix
72567a7155 Add new mining charge effects 2025-11-15 15:16:01 +01:00
DarkPhoenix
0d4c2551c1 Update effects, add new ISA jargon entry and make attribute cap to use modified value 2025-11-15 14:57:39 +01:00
DarkPhoenix
ce10aeb55e Change version name back to dev 2025-11-15 13:26:07 +01:00
DarkPhoenix
7b14266f0d Update icons 2025-11-15 13:25:51 +01:00
DarkPhoenix
b436f6ec89 Change renamed items 2025-11-15 13:18:28 +01:00
DarkPhoenix
e7e3f4e626 Try non-dev name 2025-11-15 10:32:55 +01:00
DarkPhoenix
ae8405d132 Update static data and remove some now-unused data 2025-11-14 22:52:00 +01:00
DarkPhoenix
977cf61ff5 Merge branch 'master' into singularity
# Conflicts:
#	eos/effects.py
#	staticdata/fsd_built/dogmaeffects.0.json
#	staticdata/fsd_built/iconids.0.json
#	staticdata/fsd_built/marketgroups.0.json
#	staticdata/fsd_built/types.4.json
#	staticdata/fsd_built/types.5.json
#	staticdata/phobos/metadata.0.json
#	version.yml
2025-11-14 22:13:20 +01:00
DarkPhoenix
d271515060 Bump version 2025-10-28 14:01:28 +01:00
DarkPhoenix
343e52e556 Update static data and effects 2025-10-28 14:01:05 +01:00
cryonox
edec81f4b8 Refresh tokens when pyfa start to avoid expiry 2025-09-10 12:39:34 +08:00
Tom Sadler
8afb2139b3 venv activation for PowerShell (running tests) 2025-05-23 20:06:43 +01:00
Tom Sadler
c7412a5174 Add PyfaDEV path for translations and database scripts 2025-05-23 20:04:57 +01:00
Tom Sadler
2494ad8cef venv activation for PowerShell 2025-05-23 20:02:54 +01:00
Tom Sadler
a2f17e3205 Add note on C compiler 2025-05-23 19:53:24 +01:00
Tom Sadler
f4d50792ea Add note on Python versions 2025-05-23 19:39:49 +01:00
145 changed files with 68504 additions and 26257 deletions

View File

@@ -1,7 +1,7 @@
image:
- Ubuntu2204
- Visual Studio 2022
- macos-catalina
- macos-monterey
for:
-
matrix:
@@ -21,7 +21,7 @@ for:
# AppImage dependencies
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install libfuse2
# Preparation script dependencies
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install python3-wxgtk4.0 python3-sqlalchemy python3-logbook
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install python3-wxgtk4.0 python3-sqlalchemy python3-logbook xclip wl-clipboard
before_build:
# Prepare pyfa data
- sh: find locale/ -type f -name "*.po" -exec msgen "{}" -o "{}" \;
@@ -32,7 +32,7 @@ for:
- sh: export PYFA_VERSION="$(python3 -B scripts/dump_version.py)"
- sh: mkdir build
# Download packaging tool
- sh: curl -o $APPIMAGE_TOOL -L https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage
- sh: curl --fail-with-body -o $APPIMAGE_TOOL -L https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage
- sh: chmod +x $APPIMAGE_TOOL
build_script:
- sh: mkdir -p AppDir/opt/pyfa
@@ -147,7 +147,7 @@ for:
-
matrix:
only:
- image: macos-catalina
- image: macos-monterey
environment:
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJDW/+oYNGOiPvwuwAL9tc/LQgg58aosIVpMYfepQZ20V+VZnHpZh8IRDA8Jo5xht19p2PksA+hFgqA0kpKtrSkuiWdE8rATQItfk4gf7yB0yGasJGGQZYazy9k/9XtmYkq2HHOOeEqdxvrICddJQ88MLCLT9lJENSUP/YS/yGcjZFXVxE11pTeIcqlCRU+3eYa1v7BeNvXIKNhZoK5orXWrtuH3cy8jrSns/u70aYfJ6B2jA8CnWnDbuvpeQtEY61SQqlKUsSArNa8NAsXj41wr3Ar9gAG9330w7EMTqlutk8HZO35uHI0q5qinUhaQYufPPrVkb2L/N+ZCfu0fnh appveyor"
cache:

View File

@@ -2,7 +2,7 @@
## Requirements
- Python 3.11
- Python 3.11 (later versions may not work)
- Git CLI installed
- Python, pip and git are all available as command-line commands (add to the path if needed)
@@ -26,6 +26,7 @@ Activate the virtual environment
```
For cmd.exe: PyfaEnv\scripts\activate.bat
For PowerShell: PyfaEnv\Scripts\Activate.ps1
For bash: source <venv>/Scripts/activate
```
> For other OS check [Python documentation](https://docs.python.org/3/library/venv.html)
@@ -36,6 +37,8 @@ pip install -r PyfaDEV\requirements.txt
```
> For some Linux distributions, you may need to install separate wxPython bindings, such as `python-matplotlib-wx`
> You may need to [install a C compiler](https://mesonbuild.com/SimpleStart.html#installing-a-compiler-toolchain)
Check that the libs from *requirements.txt* are installed
```
pip list
@@ -43,8 +46,8 @@ pip list
Build translations and database:
```
python scripts\compile_lang.py
python db_update.py
python PyfaDEV\scripts\compile_lang.py
python PyfaDEV\db_update.py
```
Test that the project is starting properly
@@ -88,6 +91,7 @@ Check that the project is starting properly.
Switch to the proper virtual environment
```
For cmd.exe: PyfaEnv\scripts\activate.bat
For PowerShell: PyfaEnv\Scripts\Activate.ps1
For bash: source <venv>/Scripts/activate
```

File diff suppressed because it is too large Load Diff

View File

@@ -324,7 +324,7 @@ class ModifiedAttributeDict(MutableMapping):
cappingAttrKeyCache[key] = cappingKey
if cappingKey:
cappingValue = self.original.get(cappingKey, self.__calculateValue(cappingKey))
cappingValue = self[cappingKey]
cappingValue = cappingValue.value if hasattr(cappingValue, "value") else cappingValue
else:
cappingValue = None

View File

@@ -82,7 +82,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
self.__baseVolley = None
self.__baseRRAmount = None
self.__miningYield = None
self.__miningWaste = None
self.__miningDrain = None
self.__ehp = None
self.__itemModifiedAttributes = ModifiedAttributeDict()
self.__itemModifiedAttributes.original = self._item.attributes
@@ -240,15 +240,15 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
if not ignoreState and self.amountActive <= 0:
return 0
if self.__miningYield is None:
self.__miningYield, self.__miningWaste = self.__calculateMining()
self.__miningYield, self.__miningDrain = self.__calculateMining()
return self.__miningYield
def getMiningWPS(self, ignoreState=False):
def getMiningDPS(self, ignoreState=False):
if not ignoreState and self.amountActive <= 0:
return 0
if self.__miningWaste is None:
self.__miningYield, self.__miningWaste = self.__calculateMining()
return self.__miningWaste
if self.__miningDrain is None:
self.__miningYield, self.__miningDrain = self.__calculateMining()
return self.__miningDrain
def __calculateMining(self):
if self.mines is True:
@@ -262,8 +262,8 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
yps = yield_ / (cycleTime / 1000.0)
wasteChance = self.getModifiedItemAttr("miningWasteProbability")
wasteMult = self.getModifiedItemAttr("miningWastedVolumeMultiplier")
wps = yps * max(0, min(1, wasteChance / 100)) * wasteMult
return yps, wps
dps = yps * (1 + max(0, min(1, wasteChance / 100)) * wasteMult)
return yps, dps
else:
return 0, 0
@@ -335,7 +335,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
self.__baseVolley = None
self.__baseRRAmount = None
self.__miningYield = None
self.__miningWaste = None
self.__miningDrain = None
self.__ehp = None
self.itemModifiedAttributes.clear()
self.chargeModifiedAttributes.clear()

View File

@@ -140,8 +140,8 @@ class Fit:
self.__remoteRepMap = {}
self.__minerYield = None
self.__droneYield = None
self.__minerWaste = None
self.__droneWaste = None
self.__minerDrain = None
self.__droneDrain = None
self.__droneDps = None
self.__droneVolley = None
self.__sustainableTank = None
@@ -378,11 +378,11 @@ class Fit:
return self.__minerYield
@property
def minerWaste(self):
if self.__minerWaste is None:
def minerDrain(self):
if self.__minerDrain is None:
self.calculatemining()
return self.__minerWaste
return self.__minerDrain
@property
def droneYield(self):
@@ -392,19 +392,19 @@ class Fit:
return self.__droneYield
@property
def droneWaste(self):
if self.__droneWaste is None:
def droneDrain(self):
if self.__droneDrain is None:
self.calculatemining()
return self.__droneWaste
return self.__droneDrain
@property
def totalYield(self):
return self.droneYield + self.minerYield
@property
def totalWaste(self):
return self.droneWaste + self.minerWaste
def totalDrain(self):
return self.droneDrain + self.minerDrain
@property
def maxTargets(self):
@@ -518,8 +518,8 @@ class Fit:
self.__remoteRepMap = {}
self.__minerYield = None
self.__droneYield = None
self.__minerWaste = None
self.__droneWaste = None
self.__minerDrain = None
self.__droneDrain = None
self.__effectiveSustainableTank = None
self.__sustainableTank = None
self.__droneDps = None
@@ -702,15 +702,12 @@ class Fit:
mod.item.requiresSkill("High Speed Maneuvering"),
"speedFactor", value, stackingPenalties=True)
if warfareBuffID == 23: # Mining Burst: Mining Laser Field Enhancement: Mining/Survey Range
if warfareBuffID == 23: # Mining Burst: Mining Laser Field Enhancement: Mining Range
self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining") or
mod.item.requiresSkill("Ice Harvesting") or
mod.item.requiresSkill("Gas Cloud Harvesting"),
"maxRange", value, stackingPenalties=True)
self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("CPU Management"),
"surveyScanRange", value, stackingPenalties=True)
if warfareBuffID == 24: # Mining Burst: Mining Laser Optimization: Mining Capacitor/Duration
self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining") or
mod.item.requiresSkill("Ice Harvesting") or
@@ -944,6 +941,17 @@ class Fit:
self.ship.forceItemAttr("miningScannerUpgrade", value)
if warfareBuffID == 2481: # Expedition Burst: Salvager duration bonus
self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Salvaging"), "duration", value)
if warfareBuffID == 2516: # Mining Burst: Mining Crit Chance
self.modules.filteredItemBoost(
lambda mod: mod.item.requiresSkill("Mining") or mod.item.requiresSkill("Ice Harvesting"),
"miningCritChance", value)
if warfareBuffID == 2517: # Mining Burst: Mining Residue Chance Reduction
self.modules.filteredItemBoost(
lambda mod: (
mod.item.requiresSkill("Mining")
or mod.item.requiresSkill("Ice Harvesting")
or mod.item.requiresSkill("Gas Cloud Harvesting")),
"miningWasteProbability", value, stackingPenalties=True)
del self.commandBonuses[warfareBuffID]
@@ -1726,21 +1734,21 @@ class Fit:
def calculatemining(self):
minerYield = 0
minerWaste = 0
minerDrain = 0
droneYield = 0
droneWaste = 0
droneDrain = 0
for mod in self.modules:
minerYield += mod.getMiningYPS()
minerWaste += mod.getMiningWPS()
minerDrain += mod.getMiningDPS()
for drone in self.drones:
droneYield += drone.getMiningYPS()
droneWaste += drone.getMiningWPS()
droneDrain += drone.getMiningDPS()
self.__minerYield = minerYield
self.__minerWaste = minerWaste
self.__minerDrain = minerDrain
self.__droneYield = droneYield
self.__droneWaste = droneWaste
self.__droneDrain = droneDrain
def calculateWeaponDmgStats(self, spoolOptions):
weaponVolley = DmgTypes.default()

View File

@@ -127,7 +127,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
self.__baseVolley = None
self.__baseRRAmount = None
self.__miningYield = None
self.__miningWaste = None
self.__miningDrain = None
self.__reloadTime = None
self.__reloadForce = None
self.__chargeCycles = None
@@ -418,17 +418,17 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
if not ignoreState and self.state < FittingModuleState.ACTIVE:
return 0
if self.__miningYield is None:
self.__miningYield, self.__miningWaste = self.__calculateMining()
self.__miningYield, self.__miningDrain = self.__calculateMining()
return self.__miningYield
def getMiningWPS(self, ignoreState=False):
def getMiningDPS(self, ignoreState=False):
if self.isEmpty:
return 0
if not ignoreState and self.state < FittingModuleState.ACTIVE:
return 0
if self.__miningWaste is None:
self.__miningYield, self.__miningWaste = self.__calculateMining()
return self.__miningWaste
if self.__miningDrain is None:
self.__miningYield, self.__miningDrain = self.__calculateMining()
return self.__miningDrain
def __calculateMining(self):
yield_ = self.getModifiedItemAttr("miningAmount")
@@ -443,11 +443,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
yps = 0
wasteChance = self.getModifiedItemAttr("miningWasteProbability")
wasteMult = self.getModifiedItemAttr("miningWastedVolumeMultiplier")
wps = yps * max(0, min(1, wasteChance / 100)) * wasteMult
dps = yps * (1 + max(0, min(1, wasteChance / 100)) * wasteMult)
critChance = self.getModifiedItemAttr("miningCritChance")
critBonusMult = self.getModifiedItemAttr("miningCritBonusYield")
yps += yps * critChance * critBonusMult
return yps, wps
return yps, dps
def isDealingDamage(self, ignoreState=False):
volleyParams = self.getVolleyParameters(ignoreState=ignoreState)
@@ -897,7 +897,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
self.__baseVolley = None
self.__baseRRAmount = None
self.__miningYield = None
self.__miningWaste = None
self.__miningDrain = None
self.__reloadTime = None
self.__reloadForce = None
self.__chargeCycles = None

View File

@@ -126,7 +126,7 @@ class Ship(ItemAttrShortcut, HandledItem):
valid Item objects, not the Mode objects. Returns None if not a
t3 dessy
"""
if self.item.group.name != "Tactical Destroyer":
if self.item.group.name != "Tactical Destroyer" and self.item.name != "Anhinga":
return None
items = []

View File

@@ -47,6 +47,8 @@ class AddCurrentlyOpenFit(ContextMenuUnconditional):
if isinstance(page, BlankPage):
continue
fit = sFit.getFit(page.activeFitID, basic=True)
if fit is None:
continue
id = ContextMenuUnconditional.nextID()
mitem = wx.MenuItem(rootMenu, id, "{}: {}".format(fit.ship.item.name, fit.name))
bindmenu.Bind(wx.EVT_MENU, self.handleSelection, mitem)

View File

@@ -17,7 +17,10 @@ class ChangeShipTacticalMode(ContextMenuUnconditional):
self.modeMap = {
'Defense': _t('Defense'),
'Propulsion': _t('Propulsion'),
'Sharpshooter': _t('Sharpshooter')
'Sharpshooter': _t('Sharpshooter'),
'Primary': _t('Primary'),
'Secondary': _t('Secondary'),
'Tertiary': _t('Tertiary'),
}
def display(self, callingWindow, srcContext):

View File

@@ -130,9 +130,9 @@ class MiningYieldViewFull(StatsView):
def refreshPanel(self, fit):
# If we did anything intresting, we'd update our labels to reflect the new fit's stats here
stats = (("labelFullminingyieldMiner", lambda: fit.minerYield, lambda: fit.minerWaste, 3, 0, 0, "{}{} m\u00B3/s", None),
("labelFullminingyieldDrone", lambda: fit.droneYield, lambda: fit.droneWaste, 3, 0, 0, "{}{} m\u00B3/s", None),
("labelFullminingyieldTotal", lambda: fit.totalYield, lambda: fit.totalWaste, 3, 0, 0, "{}{} m\u00B3/s", None))
stats = (("labelFullminingyieldMiner", lambda: fit.minerYield, lambda: fit.minerDrain, 3, 0, 0, "{} m\u00B3/s", None),
("labelFullminingyieldDrone", lambda: fit.droneYield, lambda: fit.droneDrain, 3, 0, 0, "{} m\u00B3/s", None),
("labelFullminingyieldTotal", lambda: fit.totalYield, lambda: fit.totalDrain, 3, 0, 0, "{} m\u00B3/s", None))
def processValue(value):
value = value() if fit is not None else 0
@@ -140,23 +140,26 @@ class MiningYieldViewFull(StatsView):
return value
counter = 0
for labelName, yieldValue, wasteValue, prec, lowest, highest, valueFormat, altFormat in stats:
for labelName, yieldValue, drainValue, prec, lowest, highest, valueFormat, altFormat in stats:
label = getattr(self, labelName)
yieldValue = processValue(yieldValue)
wasteValue = processValue(wasteValue)
if self._cachedValues[counter] != (yieldValue, wasteValue):
drainValue = processValue(drainValue)
if self._cachedValues[counter] != (yieldValue, drainValue):
try:
efficiency = '{}%'.format(formatAmount(yieldValue / drainValue * 100, 4, 0, 0))
except ZeroDivisionError:
efficiency = '0%'
yps = formatAmount(yieldValue, prec, lowest, highest)
yph = formatAmount(yieldValue * 3600, prec, lowest, highest)
wps = formatAmount(wasteValue, prec, lowest, highest)
wph = formatAmount(wasteValue * 3600, prec, lowest, highest)
wasteSuffix = '\u02b7' if wasteValue > 0 else ''
label.SetLabel(valueFormat.format(yps, wasteSuffix))
dps = formatAmount(drainValue, prec, lowest, highest)
dph = formatAmount(drainValue * 3600, prec, lowest, highest)
label.SetLabel(valueFormat.format(yps))
tipLines = []
tipLines.append("{} m\u00B3 mining yield per second ({} m\u00B3 per hour)".format(yps, yph))
if wasteValue > 0:
tipLines.append("{} m\u00B3 mining waste per second ({} m\u00B3 per hour)".format(wps, wph))
tipLines.append("{} m\u00B3 yield per second ({} m\u00B3 per hour)".format(yps, yph))
tipLines.append("{} m\u00B3 drain per second ({} m\u00B3 per hour)".format(dps, dph))
tipLines.append(f'{efficiency} efficiency')
label.SetToolTip(wx.ToolTip('\n'.join(tipLines)))
self._cachedValues[counter] = (yieldValue, wasteValue)
self._cachedValues[counter] = (yieldValue, drainValue)
counter += 1
self.panel.Layout()
self.headerPanel.Layout()

View File

@@ -130,6 +130,7 @@ class TargetingMiscViewMinimal(StatsView):
("specialPlanetaryCommoditiesHoldCapacity", _t("Planetary goods hold")),
("specialQuafeHoldCapacity", _t("Quafe hold")),
("specialMobileDepotHoldCapacity", _t("Mobile depot hold")),
("specialExpeditionHoldCapacity", _t("Expedition hold")),
))
cargoValues = {
@@ -154,6 +155,7 @@ class TargetingMiscViewMinimal(StatsView):
"specialPlanetaryCommoditiesHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialPlanetaryCommoditiesHoldCapacity"),
"specialQuafeHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialQuafeHoldCapacity"),
"specialMobileDepotHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialMobileDepotHoldCapacity"),
"specialExpeditionHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialExpeditionHoldCapacity"),
}
stats = (("labelTargets", {"main": lambda: fit.maxTargets}, 3, 0, 0, ""),

View File

@@ -27,6 +27,7 @@ from gui.viewColumn import ViewColumn
from gui.bitmap_loader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
from gui.utils.listFormatter import formatList
from eos.utils.float import floatUnerr
from eos.utils.spoolSupport import SpoolType, SpoolOptions
import eos.config
@@ -195,7 +196,7 @@ class Miscellanea(ViewColumn):
tooltip = "Warp core strength modification"
return text, tooltip
elif (
itemGroup in ("Stasis Web", "Stasis Webifying Drone", "Structure Stasis Webifier") or
itemGroup in ("Stasis Web", "Stasis Grappler", "Stasis Webifying Drone", "Structure Stasis Webifier") or
(itemGroup in ("Structure Burst Projector", "Burst Projectors") and "doomsdayAOEWeb" in item.effects)
):
speedFactor = stuff.getModifiedItemAttr("speedFactor")
@@ -547,18 +548,24 @@ class Miscellanea(ViewColumn):
if not yps:
return "", None
yph = yps * 3600
wps = stuff.getMiningWPS(ignoreState=True)
wph = wps * 3600
dps = stuff.getMiningDPS(ignoreState=True)
dph = dps * 3600
try:
efficiency = yps / dps
except ZeroDivisionError:
efficiency = 0
textParts = []
textParts.append(formatAmount(yps, 3, 0, 3))
tipLines = []
textParts.append('{} m\u00B3/s'.format(formatAmount(yps, 3, 0, 3)))
tipLines.append("{} m\u00B3 mining yield per second ({} m\u00B3 per hour)".format(
formatAmount(yps, 3, 0, 3), formatAmount(yph, 3, 0, 3)))
if wps > 0:
textParts.append(formatAmount(wps, 3, 0, 3))
tipLines.append("{} m\u00B3 mining waste per second ({} m\u00B3 per hour)".format(
formatAmount(wps, 3, 0, 3), formatAmount(wph, 3, 0, 3)))
text = '{} m\u00B3/s'.format('+'.join(textParts))
tipLines.append("{} m\u00B3 mining drain per second ({} m\u00B3 per hour)".format(
formatAmount(dps, 3, 0, 3), formatAmount(dph, 3, 0, 3)))
if floatUnerr(efficiency) != 1:
eff_text = '{}%'.format(formatAmount(efficiency * 100, 4, 0, 0))
textParts.append(eff_text)
tipLines.append(f"{eff_text} mining efficiency")
text = '{}'.format(' | '.join(textParts))
tooltip = '\n'.join(tipLines)
return text, tooltip
elif itemGroup == "Logistic Drone":
@@ -701,7 +708,7 @@ class Miscellanea(ViewColumn):
formatAmount(itemArmorResistanceShiftHardenerExp, 3, 0, 3),
)
return text, tooltip
elif itemGroup in ("Cargo Scanner", "Ship Scanner", "Survey Scanner"):
elif itemGroup in ("Cargo Scanner", "Ship Scanner"):
duration = stuff.getModifiedItemAttr("duration")
if not duration:
return "", None
@@ -766,9 +773,9 @@ class Miscellanea(ViewColumn):
elif buffId == 22: # Skirmish Burst: Rapid Deployment: AB/MWD Speed Increase
textSections.append(f"{formatAmount(buffValue, 3, 0, 3, forceSign=True)}%")
tooltipSections.append("AB/MWD speed increase")
elif buffId == 23: # Mining Burst: Mining Laser Field Enhancement: Mining/Survey Range
elif buffId == 23: # Mining Burst: Mining Laser Field Enhancement: Mining Range
textSections.append(f"{formatAmount(buffValue, 3, 0, 3, forceSign=True)}%")
tooltipSections.append("mining/survey module range")
tooltipSections.append("mining module range")
elif buffId == 24: # Mining Burst: Mining Laser Optimization: Mining Capacitor/Duration
textSections.append(f"{formatAmount(buffValue, 3, 0, 3, forceSign=True)}%")
tooltipSections.append("mining module duration & capacitor use")
@@ -790,6 +797,12 @@ class Miscellanea(ViewColumn):
elif buffId == 2481: # Expedition Burst: Salvager duration bonus
textSections.append(f"{formatAmount(buffValue, 3, 0, 3, forceSign=True)}%")
tooltipSections.append("salvager cycle time")
elif buffId == 2516: # Mining Burst: Mining Crit Chance
textSections.append(f"{formatAmount(buffValue, 3, 0, 3, forceSign=True)}%")
tooltipSections.append("crit chance")
elif buffId == 2517: # Mining Burst: Mining Residue Chance Reduction
textSections.append(f"{formatAmount(buffValue, 3, 0, 3, forceSign=True)}%")
tooltipSections.append("waste chance")
if not textSections:
return '', None
text = ' | '.join(textSections)

View File

@@ -106,6 +106,9 @@ class CharacterSelection(wx.Panel):
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills"))
self.Bind(wx.EVT_MENU, self.exportSkills, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (condensed)"))
self.Bind(wx.EVT_MENU, self.exportSkillsCondensed, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (EVEMon)"))
self.Bind(wx.EVT_MENU, self.exportSkillsEveMon, exportItem)
@@ -268,6 +271,15 @@ class CharacterSelection(wx.Panel):
toClipboard(list)
def exportSkillsCondensed(self, evt):
skillsMap = self._buildSkillsTooltipSuperCondensed(self.reqs, skillsMap={})
list = ""
for key in sorted(skillsMap):
list += "%s %d\n" % (key, skillsMap[key][0])
toClipboard(list)
def exportSkillsEveMon(self, evt):
skillsMap = self._buildSkillsTooltipCondensed(self.reqs, skillsMap={})

View File

@@ -1,22 +1,20 @@
# noinspection PyPackageRequirements
import wx
import pyclip
from logbook import Logger
logger = Logger(__name__)
def toClipboard(text):
clip = wx.TheClipboard
clip.Open()
data = wx.TextDataObject(text)
clip.SetData(data)
clip.Close()
pyclip.copy(text)
def fromClipboard():
clip = wx.TheClipboard
clip.Open()
data = wx.TextDataObject("")
if clip.GetData(data):
clip.Close()
return data.GetText()
else:
clip.Close()
return None
"""
Read text from clipboard. Uses pyclip to grab in a cross-platform, reliable manner.
"""
data = pyclip.paste(text=True)
if not isinstance(data, str):
data = data.decode('utf-8')
logger.debug("Pasted data: {}", data)
return data

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 863 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 922 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

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: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

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: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

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: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

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