Add scanres vs locktime on active fit graph as experimental feature
This commit is contained in:
38
eos/calc.py
38
eos/calc.py
@@ -18,6 +18,38 @@
|
||||
# =============================================================================
|
||||
|
||||
|
||||
import math
|
||||
|
||||
|
||||
# Just copy-paste penalization chain calculation code (with some modifications,
|
||||
# as multipliers arrive in different form) in here to not make actual attribute
|
||||
# calculations slower than they already are due to extra function calls
|
||||
def calculateMultiplier(multipliers):
|
||||
"""
|
||||
multipliers: dictionary in format:
|
||||
{stacking group name: [(mult, resist attr ID), (mult, resist attr ID)]}
|
||||
"""
|
||||
val = 1
|
||||
for penalizedMultipliers in multipliers.values():
|
||||
# A quick explanation of how this works:
|
||||
# 1: Bonuses and penalties are calculated seperately, so we'll have to filter each of them
|
||||
l1 = [v[0] for v in penalizedMultipliers if v[0] > 1]
|
||||
l2 = [v[0] for v in penalizedMultipliers if v[0] < 1]
|
||||
# 2: The most significant bonuses take the smallest penalty,
|
||||
# This means we'll have to sort
|
||||
abssort = lambda _val: -abs(_val - 1)
|
||||
l1.sort(key=abssort)
|
||||
l2.sort(key=abssort)
|
||||
# 3: The first module doesn't get penalized at all
|
||||
# Any module after the first takes penalties according to:
|
||||
# 1 + (multiplier - 1) * math.exp(- math.pow(i, 2) / 7.1289)
|
||||
for l in (l1, l2):
|
||||
for i in range(len(l)):
|
||||
bonus = l[i]
|
||||
val *= 1 + (bonus - 1) * math.exp(- i ** 2 / 7.1289)
|
||||
return val
|
||||
|
||||
|
||||
def calculateRangeFactor(srcOptimalRange, srcFalloffRange, distance, restrictedRange=True):
|
||||
"""Range strength/chance factor, applicable to guns, ewar, RRs, etc."""
|
||||
if distance is None:
|
||||
@@ -31,3 +63,9 @@ def calculateRangeFactor(srcOptimalRange, srcFalloffRange, distance, restrictedR
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
def calculateLockTime(srcScanRes, tgtSigRadius):
|
||||
if not srcScanRes or not tgtSigRadius:
|
||||
return None
|
||||
return min(40000 / srcScanRes / math.asinh(tgtSigRadius) ** 2, 30 * 60)
|
||||
|
||||
@@ -21,13 +21,14 @@ import datetime
|
||||
import time
|
||||
from copy import deepcopy
|
||||
from itertools import chain
|
||||
from math import asinh, log, sqrt
|
||||
from math import log, sqrt
|
||||
|
||||
from logbook import Logger
|
||||
from sqlalchemy.orm import reconstructor, validates
|
||||
|
||||
import eos.db
|
||||
from eos import capSim
|
||||
from eos.calc import calculateMultiplier, calculateLockTime
|
||||
from eos.const import CalcType, FitSystemSecurity, FittingHardpoint, FittingModuleState, FittingSlot, ImplantLocation
|
||||
from eos.effectHandlerHelpers import (
|
||||
HandledBoosterList, HandledDroneCargoList, HandledImplantList,
|
||||
@@ -1529,9 +1530,7 @@ class Fit:
|
||||
def calculateLockTime(self, radius):
|
||||
scanRes = self.ship.getModifiedItemAttr("scanResolution")
|
||||
if scanRes is not None and scanRes > 0:
|
||||
# Yes, this function returns time in seconds, not miliseconds.
|
||||
# 40,000 is indeed the correct constant here.
|
||||
return min(40000 / scanRes / asinh(radius) ** 2, 30 * 60)
|
||||
return calculateLockTime(srcScanRes=scanRes, tgtSigRadius=radius)
|
||||
else:
|
||||
return self.ship.getModifiedItemAttr("scanSpeed") / 1000.0
|
||||
|
||||
@@ -1626,6 +1625,22 @@ class Fit:
|
||||
if ability.active:
|
||||
yield fighter, ability
|
||||
|
||||
def getDampMultScanRes(self):
|
||||
damps = []
|
||||
for mod in self.activeModulesIter():
|
||||
for effectName in ('remoteSensorDampFalloff', 'structureModuleEffectRemoteSensorDampener'):
|
||||
if effectName in mod.item.effects:
|
||||
damps.append((mod.getModifiedItemAttr('scanResolutionBonus'), 'default'))
|
||||
if 'doomsdayAOEDamp' in mod.item.effects:
|
||||
damps.append((mod.getModifiedItemAttr('scanResolutionBonus'), 'default'))
|
||||
for drone in self.activeDronesIter():
|
||||
if 'remoteSensorDampEntity' in drone.item.effects:
|
||||
damps.extend(drone.amountActive * ((drone.getModifiedItemAttr('scanResolutionBonus'), 'default'),))
|
||||
mults = {}
|
||||
for strength, stackingGroup in damps:
|
||||
mults.setdefault(stackingGroup, []).append((1 + strength / 100, None))
|
||||
return calculateMultiplier(mults)
|
||||
|
||||
def __deepcopy__(self, memo=None):
|
||||
fitCopy = Fit()
|
||||
# Character and owner are not copied
|
||||
|
||||
Reference in New Issue
Block a user