NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

fittingDogmaLocationUtil.py (26079B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\shipfitting\fittingDogmaLocationUtil.py
      2 import math
      3 from carbon.common.script.util.mathCommon import FloatCloseEnough
      4 from collections import defaultdict
      5 from math import sqrt, log, exp
      6 import evetypes
      7 from inventorycommon.const import groupMissileLauncherDot
      8 from itertoolsext import Bundle
      9 from fighters import ABILITY_SLOT_0, ABILITY_SLOT_2, GetAbilityIDForSlot
     10 from fighters.abilityAttributes import GetDogmaAttributeIDsForAbilityID, FIGHTER_DAMAGE_ATTRIBUTES, GetDamageMultiplierAttributeFromAbilityID, GetAbilityDurationAttributeID, GetAbilityRangeAndFalloffAttributeIDs
     11 from fighters import GetMaxSquadronSize
     12 from utillib import KeyVal
     13 CAP_STABLE_TIME = const.HOUR
     14 DAMAGE_ATTRIBUTES = (const.attributeEmDamage,
     15  const.attributeExplosiveDamage,
     16  const.attributeKineticDamage,
     17  const.attributeThermalDamage)
     18 DURATION_ATTRIBUTES = [const.attributeFighterAbilityAttackMissileDuration, const.attributeFighterAbilityMissilesDuration, const.attributeFighterAbilityAttackTurretDuration]
     19 
     20 def GetFittingItemDragData(itemID, dogmaLocation):
     21     dogmaItem = dogmaLocation.dogmaItems[itemID]
     22     data = Bundle()
     23     data.__guid__ = 'listentry.Item'
     24     data.item = KeyVal(itemID=dogmaItem.itemID, typeID=dogmaItem.typeID, groupID=dogmaItem.groupID, categoryID=dogmaItem.categoryID, flagID=dogmaItem.flagID, ownerID=dogmaItem.ownerID, locationID=dogmaItem.locationID, stacksize=dogmaLocation.GetAccurateAttributeValue(itemID, const.attributeQuantity) or getattr(dogmaItem, 'stacksize', 1), singleton=False)
     25     data.flagID = dogmaItem.flagID
     26     data.isFitted = True
     27     data.rec = data.item
     28     data.typeID = dogmaItem.typeID
     29     data.itemID = itemID
     30     data.viewMode = 'icons'
     31     return [data]
     32 
     33 
     34 def GetFittedItemsByFlag(dogmaLocation):
     35     typeHasEffectFunc = dogmaLocation.dogmaStaticMgr.TypeHasEffect
     36     chargesByFlag = {}
     37     turretsByFlag = {}
     38     launchersByFlag = {}
     39     aoeWeaponsByFlag = {}
     40     dotLaunchersByFlag = {}
     41     IsTurret = lambda typeID: typeHasEffectFunc(typeID, const.effectTurretFitted)
     42     IsLauncher = lambda typeID: typeHasEffectFunc(typeID, const.effectLauncherFitted) or typeHasEffectFunc(typeID, const.effectUseMissiles)
     43     IsAOE = lambda itemID: dogmaLocation.GetAccurateAttributeValue(itemID, const.attributeEmpFieldRange)
     44     for module in dogmaLocation.GetFittedItemsToShip().itervalues():
     45         if IsTurret(module.typeID):
     46             if not dogmaLocation.IsModuleIncludedInCalculation(module):
     47                 continue
     48             turretsByFlag[module.flagID] = module.itemID
     49         elif IsLauncher(module.typeID):
     50             if not dogmaLocation.IsModuleIncludedInCalculation(module):
     51                 continue
     52             if module.groupID == groupMissileLauncherDot:
     53                 dotLaunchersByFlag[module.flagID] = module.itemID
     54             else:
     55                 launchersByFlag[module.flagID] = module.itemID
     56         elif module.categoryID == const.categoryCharge:
     57             chargesByFlag[module.flagID] = module.itemID
     58         elif IsAOE(module.itemID):
     59             if not dogmaLocation.IsModuleIncludedInCalculation(module):
     60                 continue
     61             aoeWeaponsByFlag[module.flagID] = module.itemID
     62 
     63     return (chargesByFlag,
     64      launchersByFlag,
     65      turretsByFlag,
     66      aoeWeaponsByFlag,
     67      dotLaunchersByFlag)
     68 
     69 
     70 def GetAlphaStrike(dogmaLocation):
     71     chargesByFlag, launchersByFlag, turretsByFlag, aoeWeaponsByFlag, dotLaunchersByFlag = GetFittedItemsByFlag(dogmaLocation)
     72     GAV = dogmaLocation.GetAccurateAttributeValue
     73     alpha = 0.0
     74     ownerID = session.charid
     75     for flagID, itemID in launchersByFlag.iteritems():
     76         chargeKey = chargesByFlag.get(flagID)
     77         damagePerShot = _GetLauncherDamagePerShot(dogmaLocation, chargeKey, itemID, ownerID, GAV)
     78         alpha += damagePerShot
     79 
     80     for flagID, itemID in turretsByFlag.iteritems():
     81         chargeKey = chargesByFlag.get(flagID)
     82         damagePerShot = _GetTurretDamagePerShot(dogmaLocation, chargeKey, itemID, GAV)
     83         alpha += damagePerShot
     84 
     85     for flagID, itemID in dotLaunchersByFlag.iteritems():
     86         chargeKey = chargesByFlag.get(flagID)
     87         damagePerHit = GetDotDps(chargeKey, itemID, GAV)
     88         alpha += damagePerHit
     89 
     90     for flagID, itemID in aoeWeaponsByFlag.iteritems():
     91         damagePerHit = GetDamageFromItem(dogmaLocation, itemID)
     92         alpha += damagePerHit
     93 
     94     return alpha
     95 
     96 
     97 def _GetTurretDps(GAV, chargesByFlag, dogmaLocation, turretsByFlag, getMaxValue = False):
     98     turretDps = 0.0
     99     turretDpsWithReload = 0.0
    100     for flagID, itemID in turretsByFlag.iteritems():
    101         chargeKey = chargesByFlag.get(flagID)
    102         thisTurretDps, thisTurretDpsWithReload = GetTurretDps(dogmaLocation, chargeKey, itemID, GAV, getMaxValue)
    103         turretDps += thisTurretDps
    104         turretDpsWithReload += thisTurretDpsWithReload
    105 
    106     return (turretDps, turretDpsWithReload)
    107 
    108 
    109 def _GetMissileDps(GAV, chargesByFlag, dogmaLocation, launchersByFlag, shipDogmaItem):
    110     missileDps = 0.0
    111     missilDpsWithReload = 0.0
    112     for flagID, itemID in launchersByFlag.iteritems():
    113         chargeKey = chargesByFlag.get(flagID)
    114         if chargeKey is None:
    115             continue
    116         ownerID = session.charid
    117         thisLauncherDps, thisLauncherDpsWithReload = GetLauncherDps(dogmaLocation, chargeKey, itemID, ownerID, GAV)
    118         missileDps += thisLauncherDps
    119         missilDpsWithReload += thisLauncherDpsWithReload
    120 
    121     return (missileDps, missilDpsWithReload)
    122 
    123 
    124 def _GetDotDps(GAV, chargesByFlag, dotLaunchersByFlagID):
    125     dotDps = 0.0
    126     for flagID, itemID in dotLaunchersByFlagID.iteritems():
    127         chargeKey = chargesByFlag.get(flagID)
    128         if chargeKey is None:
    129             continue
    130         dotDps += GetDotDps(chargeKey, itemID, GAV)
    131 
    132     return dotDps
    133 
    134 
    135 def _GetAoeDps(GAV, aoeWeaponsByFlag, dogmaLocation):
    136     dps = 0.0
    137     for flagID, itemID in aoeWeaponsByFlag.iteritems():
    138         damage = GetDamageFromItem(dogmaLocation, itemID)
    139         duration = GAV(itemID, const.attributeDuration)
    140         if not duration:
    141             continue
    142         missileDps = damage / duration
    143         dps += missileDps
    144 
    145     return dps * 1000
    146 
    147 
    148 def GetAllDpsInfo(shipID, dogmaLocation):
    149     dpsInfo = GetTurretMissileAndAoeDps(shipID, dogmaLocation)
    150     from shipfitting.droneUtil import GetDroneDps
    151     droneDps, _ = GetDroneDps(shipID, dogmaLocation)
    152     dpsInfo.droneDps = droneDps
    153     fighterDamage, dpsByTubeID, dpsByPrimaryAbilityID, dpsBySecondaryAbilityID = GetFighterDamage(dogmaLocation)
    154     totalFighterDps = sum(dpsByTubeID.values())
    155     dpsInfo.fighterDps = totalFighterDps
    156     dpsInfo.dpsByPrimaryAbilityID = dpsByPrimaryAbilityID
    157     dpsInfo.dpsBySecondaryAbilityID = dpsBySecondaryAbilityID
    158     dpsInfo.totalDps += droneDps + totalFighterDps
    159     dpsInfo.totalDpsWithReload += droneDps + totalFighterDps
    160     return dpsInfo
    161 
    162 
    163 def GetTotalFighterDps(dogmaLocation):
    164     fighterDamage, dpsByTubeID, dpsByPrimaryAbilityID, dpsBySecondaryAbilityID = GetFighterDamage(dogmaLocation)
    165     totalFighterDps = sum(dpsByTubeID.values())
    166     return totalFighterDps
    167 
    168 
    169 def GetTurretMissileAndAoeDps(shipID, dogmaLocation):
    170     shipDogmaItem = dogmaLocation.dogmaItems[shipID]
    171     GAV = dogmaLocation.GetAttributeValue
    172     if getattr(dogmaLocation, 'godma', False):
    173         godmaShipItem = dogmaLocation.godma.GetItem(shipID)
    174         if godmaShipItem is not None:
    175             GAV = dogmaLocation.GetGodmaAttributeValue
    176     chargesByFlag, launchersByFlag, turretsByFlag, aoeWeaponsByFlag, dotLaunchersByFlag = GetFittedItemsByFlag(dogmaLocation)
    177     turretDps, turretDpsWithReload = _GetTurretDps(GAV, chargesByFlag, dogmaLocation, turretsByFlag)
    178     maxTurretDps, maxTurretDpsWithReload = _GetTurretDps(GAV, chargesByFlag, dogmaLocation, turretsByFlag, True)
    179     if maxTurretDps and FloatCloseEnough(turretDps, maxTurretDps):
    180         maxTurretDps = None
    181         maxTurretDpsWithReload = None
    182     missileDps, missileDpsWithReload = _GetMissileDps(GAV, chargesByFlag, dogmaLocation, launchersByFlag, shipDogmaItem)
    183     dotDps = _GetDotDps(GAV, chargesByFlag, dotLaunchersByFlag)
    184     aoeDps = _GetAoeDps(GAV, aoeWeaponsByFlag, dogmaLocation)
    185     totalDps = (maxTurretDps or turretDps) + missileDps + aoeDps + dotDps
    186     totalDpsWithReload = (maxTurretDpsWithReload or turretDpsWithReload) + missileDpsWithReload + aoeDps + dotDps
    187     dpsInfo = KeyVal(turretDps=turretDps, turretDpsWithReload=turretDpsWithReload, maxTurretDps=maxTurretDps, maxTurretDpsWithReload=maxTurretDpsWithReload, missileDps=missileDps, missileDpsWithReload=missileDpsWithReload, aoeDps=aoeDps, totalDps=totalDps, totalDpsWithReload=totalDpsWithReload, dotDps=dotDps)
    188     return dpsInfo
    189 
    190 
    191 def GetChanceToHit(shipID, dogmaLocation):
    192     chargesByFlag, launchersByFlag, turretsByFlag, aoeWeaponsByFlag, dotLaunchersByFlag = GetFittedItemsByFlag(dogmaLocation)
    193     trackingSpeed = falloff = maxRange = optimalSig = 0
    194     numTurrets = len(turretsByFlag)
    195     for turret in turretsByFlag.itervalues():
    196         trackingSpeed += dogmaLocation.GetAttributeValue(turret, const.attributeTrackingSpeed)
    197         falloff += dogmaLocation.GetAttributeValue(turret, const.attributeFalloff)
    198         maxRange += dogmaLocation.GetAttributeValue(turret, const.attributeMaxRange)
    199         optimalSig += dogmaLocation.GetAttributeValue(turret, const.attributeOptimalSigRadius)
    200 
    201     trackingSpeed /= numTurrets
    202     falloff /= numTurrets
    203     maxRange /= numTurrets
    204     optimalSig /= numTurrets
    205     return (trackingSpeed,
    206      falloff,
    207      maxRange,
    208      optimalSig)
    209 
    210 
    211 def GetLauncherDps(dogmaLocation, chargeKey, itemID, ownerID, GAV):
    212     damagePerShot = _GetLauncherDamagePerShot(dogmaLocation, chargeKey, itemID, ownerID, GAV)
    213     duration = GAV(itemID, const.attributeRateOfFire)
    214     missileDps = damagePerShot / duration
    215     missileDpsWithReload = _GetDpsWithReload(chargeKey, itemID, GAV, damagePerShot, duration)
    216     return (missileDps * 1000, missileDpsWithReload * 1000)
    217 
    218 
    219 def _GetLauncherDamagePerShot(dogmaLocation, chargeKey, moduleID, ownerID, GAV):
    220     if chargeKey is None:
    221         return 0
    222     damageMultiplier = GetMissleDamageMultiplier(dogmaLocation, moduleID, ownerID, GAV)
    223     damage = GetDamageFromItem(dogmaLocation, chargeKey)
    224     damagePerShot = damage * damageMultiplier
    225     return damagePerShot
    226 
    227 
    228 def GetMissleDamageMultiplier(dogmaLocation, moduleID, ownerID, GAV):
    229     dogmaItem = dogmaLocation.SafeGetDogmaItem(moduleID)
    230     if dogmaItem and dogmaItem.groupID == const.groupMissileLauncherBomb:
    231         damageMultiplier = 1
    232     else:
    233         damageMultiplier = GAV(ownerID, const.attributeMissileDamageMultiplier)
    234     return damageMultiplier
    235 
    236 
    237 def GetTurretDpsWithMax(dogmaLocation, chargeKey, itemID, GAV, *args):
    238     dps, dpsWithReload = GetTurretDps(dogmaLocation, chargeKey, itemID, GAV, False)
    239     maxDps, maxDpsWithReload = GetTurretDps(dogmaLocation, chargeKey, itemID, GAV, True)
    240     if not maxDps or FloatCloseEnough(dps, maxDps):
    241         maxDps = None
    242         maxDpsWithReload = None
    243     return (dps,
    244      dpsWithReload,
    245      maxDps,
    246      maxDpsWithReload)
    247 
    248 
    249 def GetTurretDps(dogmaLocation, chargeKey, itemID, GAV, getMaxValue = False, *args):
    250     turretDps = 0.0
    251     turretDpsWithReload = 0.0
    252     damagePerShot = _GetTurretDamagePerShot(dogmaLocation, chargeKey, itemID, GAV, getMaxValue)
    253     if abs(damagePerShot) > 0:
    254         duration = GAV(itemID, const.attributeRateOfFire)
    255         if abs(duration) > 0:
    256             turretDps = damagePerShot / duration
    257             turretDpsWithReload = _GetDpsWithReload(chargeKey, itemID, GAV, damagePerShot, duration)
    258     return (turretDps * 1000, turretDpsWithReload * 1000)
    259 
    260 
    261 def _GetTurretDamagePerShot(dogmaLocation, chargeKey, itemID, GAV, getMaxValue = False):
    262     if chargeKey is not None:
    263         damage = GetDamageFromItem(dogmaLocation, chargeKey)
    264     else:
    265         damage = GetDamageFromItem(dogmaLocation, itemID)
    266     if damage > 0:
    267         damageMultiplier = GAV(itemID, const.attributeDamageMultiplier)
    268         if getMaxValue:
    269             extraMaxDamageMultiplier = dogmaLocation.GetMaxDamageMultiplier(itemID)
    270             damageMultiplier *= extraMaxDamageMultiplier
    271         damage *= damageMultiplier
    272     return damage
    273 
    274 
    275 def _GetDpsWithReload(chargeKey, itemID, GAV, damagePerShot, duration):
    276     if chargeKey is None:
    277         return damagePerShot / duration
    278     reloadTime = GAV(itemID, const.attributeReloadTime)
    279     reactivationDelay = GAV(itemID, const.attributeModuleReactivationDelay)
    280     numShotBeforeReload = GetNumChargesFullyLoaded(chargeKey, itemID, GAV)
    281     if reactivationDelay > reloadTime:
    282         missileDpsWithReload = damagePerShot / (reactivationDelay + duration)
    283         return missileDpsWithReload
    284     if numShotBeforeReload:
    285         missileDpsWithReload = numShotBeforeReload * damagePerShot / (numShotBeforeReload * duration + reloadTime)
    286         return missileDpsWithReload
    287     return 0
    288 
    289 
    290 def GetDotDps(chargeKey, itemID, GAV, *args):
    291     if chargeKey is None:
    292         return 0
    293     dotMaxDamagePerTick = GAV(chargeKey, const.attributeDotMaxDamagePerTick)
    294     damageMultiplier = GAV(itemID, const.attributeDamageMultiplier)
    295     return dotMaxDamagePerTick * damageMultiplier
    296 
    297 
    298 def GetNumChargesFullyLoaded(chargeKey, itemID, GAV):
    299     launcherCapacity = GAV(itemID, const.attributeCapacity)
    300     chargeVolume = GAV(chargeKey, const.attributeVolume)
    301     if chargeVolume:
    302         numShotBeforeReload = int(launcherCapacity / float(chargeVolume))
    303         return numShotBeforeReload
    304     else:
    305         return 0
    306 
    307 
    308 def GetDamageFromItem(dogmaLocation, itemID):
    309     accDamage = 0
    310     for attributeID in DAMAGE_ATTRIBUTES:
    311         d = dogmaLocation.GetAccurateAttributeValue(itemID, attributeID)
    312         accDamage += d
    313 
    314     return accDamage
    315 
    316 
    317 def CapacitorSimulator(dogmaLocation, shipID):
    318     dogmaItem = dogmaLocation.dogmaItems[shipID]
    319     capacitorCapacity = dogmaLocation.GetAccurateAttributeValue(shipID, const.attributeCapacitorCapacity)
    320     rechargeTime = dogmaLocation.GetAccurateAttributeValue(shipID, const.attributeRechargeRate)
    321     modules = []
    322     totalCapNeed = 0
    323     modulesByFlag = {}
    324     chargesByFlag = {}
    325     for moduleID, module in dogmaItem.GetFittedItems().iteritems():
    326         if module.categoryID == const.categoryCharge:
    327             chargesByFlag[module.flagID] = module
    328         else:
    329             modulesByFlag[module.flagID] = module
    330 
    331     for flagID, module in modulesByFlag.iteritems():
    332         moduleID = module.itemID
    333         if not dogmaLocation.IsModuleIncludedInCalculation(module):
    334             continue
    335         try:
    336             defaultEffectID = dogmaLocation.dogmaStaticMgr.GetDefaultEffect(module.typeID)
    337         except KeyError:
    338             defaultEffectID = None
    339 
    340         if defaultEffectID is None:
    341             continue
    342         defaultEffect = dogmaLocation.dogmaStaticMgr.effects[defaultEffectID]
    343         durationAttributeID = defaultEffect.durationAttributeID
    344         dischargeAttributeID = defaultEffect.dischargeAttributeID
    345         if durationAttributeID is None:
    346             continue
    347         duration = dogmaLocation.GetAccurateAttributeValue(moduleID, durationAttributeID)
    348         reactivationDelay = dogmaLocation.GetAccurateAttributeValue(moduleID, const.attributeModuleReactivationDelay)
    349         reloadInfo = None
    350         moduleGroupID = evetypes.GetGroupID(module.typeID)
    351         if moduleGroupID == const.groupCapacitorBooster:
    352             charges = chargesByFlag.get(flagID, None)
    353             if not charges:
    354                 continue
    355             avgCapInjectedEachCycle, capInjectedPerCycle, reloadInfo = _GetAvgInjectedEachCycle(dogmaLocation, moduleID, charges, duration)
    356             avgCapNeed = -avgCapInjectedEachCycle
    357             capNeed = -capInjectedPerCycle
    358         elif moduleGroupID == const.groupEnergyVampire:
    359             capInjectedPerCycle = dogmaLocation.GetAccurateAttributeValue(moduleID, const.attributePowerTransferAmount)
    360             capNeed = -capInjectedPerCycle
    361             avgCapNeed = -capInjectedPerCycle
    362         elif dischargeAttributeID is None:
    363             continue
    364         else:
    365             avgCapNeed = capNeed = dogmaLocation.GetAccurateAttributeValue(moduleID, dischargeAttributeID)
    366         k = KeyVal(capNeeded=capNeed, durationValue=long(duration * const.dgmTauConstant), nextRun=0, cyclesSinceReload=0, reloadInfo=reloadInfo, reactivationDelay=reactivationDelay)
    367         modules.append(k)
    368         totalCapNeed += avgCapNeed / (duration + reactivationDelay)
    369 
    370     rechargeRateAverage = capacitorCapacity / rechargeTime
    371     peakRechargeRate = 2.5 * rechargeRateAverage
    372     tau = rechargeTime / 5
    373     totalPositiveCapNeeded = max(0, totalCapNeed)
    374     TTL = None
    375     runSimulation = totalCapNeed > peakRechargeRate
    376     if runSimulation or totalCapNeed / peakRechargeRate > 0.95:
    377         TTL = RunSimulation(capacitorCapacity, rechargeTime, modules)
    378         if TTL >= CAP_STABLE_TIME:
    379             TTL = None
    380     if TTL is not None:
    381         loadBalance = 0
    382     else:
    383         c = 2 * capacitorCapacity / tau
    384         k = totalPositiveCapNeeded / c
    385         fourK = min(1, 4 * k)
    386         exponent = (1 - sqrt(1 - fourK)) / 2
    387         if exponent == 0:
    388             loadBalance = 1
    389         else:
    390             t = -log(exponent) * tau
    391             loadBalance = (1 - exp(-t / tau)) ** 2
    392     return (peakRechargeRate,
    393      totalCapNeed,
    394      loadBalance,
    395      TTL)
    396 
    397 
    398 def _GetReloadInfo(dogmaLocation, moduleID, charges):
    399     GAV = dogmaLocation.GetAccurateAttributeValue
    400     reloadTime = GAV(moduleID, const.attributeReloadTime)
    401     moduleCapacity = GAV(moduleID, const.attributeCapacity)
    402     chargeVolume = GAV(charges.itemID, const.attributeVolume)
    403     maxChargesInModule = int(moduleCapacity / float(chargeVolume))
    404     moduleRechargeInfo = KeyVal(reloadTime=reloadTime, maxChargesInModule=maxChargesInModule)
    405     return moduleRechargeInfo
    406 
    407 
    408 def _GetAvgInjectedEachCycle(dogmaLocation, moduleID, charges, duration):
    409     moduleRechargeInfo = _GetReloadInfo(dogmaLocation, moduleID, charges)
    410     capInjectedPerCycle = dogmaLocation.GetAccurateAttributeValue(charges.itemID, const.attributeCapacitorBonus)
    411     injectedInOneLoad = moduleRechargeInfo.maxChargesInModule * capInjectedPerCycle
    412     durationOfFullLoad = moduleRechargeInfo.maxChargesInModule * duration
    413     avgCapInjectedEachCycle = injectedInOneLoad / (durationOfFullLoad + moduleRechargeInfo.reloadTime) * duration
    414     return (avgCapInjectedEachCycle, capInjectedPerCycle, moduleRechargeInfo)
    415 
    416 
    417 def RunSimulation(capacitorCapacity, rechargeRate, modules):
    418     capacitor = capacitorCapacity
    419     tauThingy = float(const.dgmTauConstant) * (rechargeRate / 5.0)
    420     currentTime = nextTime = 0
    421     while capacitor > 0.0 and nextTime < CAP_STABLE_TIME:
    422         capacitor = (1.0 + (math.sqrt(capacitor / capacitorCapacity) - 1.0) * math.exp((currentTime - nextTime) / tauThingy)) ** 2 * capacitorCapacity
    423         currentTime = nextTime
    424         nextTime = CAP_STABLE_TIME
    425         for data in modules:
    426             if data.nextRun == currentTime:
    427                 capacitor -= data.capNeeded
    428                 data.cyclesSinceReload += 1
    429                 if data.reloadInfo:
    430                     if data.cyclesSinceReload >= data.reloadInfo.maxChargesInModule:
    431                         data.nextRun += data.reloadInfo.reloadTime * const.SEC
    432                         data.cyclesSinceReload = 0
    433                 if data.reactivationDelay:
    434                     data.nextRun += data.reactivationDelay * const.SEC
    435                 data.nextRun += data.durationValue
    436             nextTime = min(nextTime, data.nextRun)
    437 
    438     if capacitor > 0.0:
    439         return CAP_STABLE_TIME
    440     return currentTime
    441 
    442 
    443 LN_025 = math.log(0.25)
    444 
    445 def GetAlignTime(dogmaLocation):
    446     shipID = dogmaLocation.GetCurrentShipID()
    447     agility = dogmaLocation.GetAttributeValue(shipID, const.attributeAgility)
    448     mass = dogmaLocation.GetAttributeValue(shipID, const.attributeMass)
    449     return GetAlignTimeFromAgilityAndMass(agility, mass)
    450 
    451 
    452 def GetAlignTimeFromAgilityAndMass(agility, mass):
    453     alignTime = -LN_025 * agility * mass / 1000000
    454     return alignTime
    455 
    456 
    457 def GetFuelUsage(dogmaLocation):
    458     totalFuelPerHour = GetFuelUsagePerHour(dogmaLocation)
    459     return totalFuelPerHour * 24
    460 
    461 
    462 def GetFuelUsagePerHour(dogmaLocation):
    463     ship = dogmaLocation.GetShip()
    464     totalFuelPerHour = 0
    465     for itemID, dogmaItem in ship.GetFittedItems().iteritems():
    466         fuelPerHour = dogmaLocation.GetAccurateAttributeValue(itemID, const.attributeServiceModuleFuelAmount)
    467         if fuelPerHour and dogmaItem.IsOnline():
    468             totalFuelPerHour += fuelPerHour
    469 
    470     return totalFuelPerHour
    471 
    472 
    473 def GetFighterDamage(dogmaLocation):
    474     totalDmgFromFighters = 0
    475     dpsByPrimaryAbilityID = defaultdict(int)
    476     dpsBySecondaryAbilityID = defaultdict(int)
    477     dpsByTubeID = defaultdict(int)
    478     for eachTubeFlagID in const.fighterTubeFlags:
    479         fighterBelongingToTube = dogmaLocation.GetFightersForTube(eachTubeFlagID)
    480         if fighterBelongingToTube is None:
    481             continue
    482         fighterID = fighterBelongingToTube.itemID
    483         qty = fighterBelongingToTube.squadronSize
    484         primaryDmg, primaryDps, primaryAbilityID = GetPrimaryDamageForSquadron(dogmaLocation, fighterID, fighterBelongingToTube.typeID, qty)
    485         secondaryDmg, secondaryDps, secondaryAbilityID = GetSecondaryForSquadron(dogmaLocation, fighterID, fighterBelongingToTube.typeID, qty)
    486         totalDmgFromFighters += primaryDmg + secondaryDmg
    487         dpsByPrimaryAbilityID[primaryAbilityID] += primaryDps
    488         if secondaryDps and secondaryAbilityID is not None:
    489             dpsBySecondaryAbilityID[secondaryAbilityID] += secondaryDps
    490         dpsByTubeID[eachTubeFlagID] += primaryDps + secondaryDps
    491 
    492     return (totalDmgFromFighters,
    493      dpsByTubeID,
    494      dpsByPrimaryAbilityID,
    495      dpsBySecondaryAbilityID)
    496 
    497 
    498 def GetPrimaryDamageForSquadron(dogmaLocation, fighterID, typeID, qty):
    499     dps, squadronDmg, abilityID = GetDamageForAbilitySlot(dogmaLocation, fighterID, typeID, qty, abilitySlotID=ABILITY_SLOT_0)
    500     return (squadronDmg, dps, abilityID)
    501 
    502 
    503 def GetSecondaryForSquadron(dogmaLocation, fighterID, typeID, qty):
    504     dps, squadronDmg, abilityID = GetDamageForAbilitySlot(dogmaLocation, fighterID, typeID, qty, abilitySlotID=ABILITY_SLOT_2)
    505     return (squadronDmg, dps, abilityID)
    506 
    507 
    508 def GetDamageForAbilitySlot(dogmaLocation, fighterID, typeID, qty, abilitySlotID):
    509     squadronDmg = 0
    510     dps = 0
    511     abilityID = GetAbilityIDForSlot(typeID, abilitySlotID)
    512     if abilityID:
    513         squadronDmg, dps = GetDamageForSquadron(dogmaLocation, fighterID, qty, abilityID)
    514     return (dps, squadronDmg, abilityID)
    515 
    516 
    517 def GetDamageForSquadron(dogmaLocation, fighterID, qty, abilityID):
    518     dItem = dogmaLocation.SafeGetDogmaItem(fighterID)
    519     if dItem is None:
    520         return (0, 0)
    521     dmg, dps = GetDamageFromFighter(dogmaLocation, dItem.itemID, abilityID)
    522     totalDmg = qty * dmg
    523     totalDps = qty * dps
    524     return (totalDmg, totalDps)
    525 
    526 
    527 def GetDamageFromFighter(dogmaLocation, itemID, abilityID):
    528     damageMultiplierAttributeID = GetDamageMultiplierAttributeFromAbilityID(abilityID)
    529     if damageMultiplierAttributeID is None:
    530         return (0, 0)
    531     multiplier = dogmaLocation.GetAccurateAttributeValue(itemID, damageMultiplierAttributeID)
    532     accDamage = 0
    533     abilityAttributeIDs = GetDogmaAttributeIDsForAbilityID(abilityID)
    534     durationAttributeID = GetAbilityDurationAttributeID(dogmaLocation.dogmaStaticMgr, abilityID)
    535     for attributeID in abilityAttributeIDs:
    536         if attributeID not in FIGHTER_DAMAGE_ATTRIBUTES:
    537             if attributeID in DURATION_ATTRIBUTES:
    538                 durationAttributeID = attributeID
    539             continue
    540         d = dogmaLocation.GetAccurateAttributeValue(itemID, attributeID)
    541         accDamage += d * multiplier
    542 
    543     dps = 0
    544     if durationAttributeID:
    545         duration = dogmaLocation.GetAccurateAttributeValue(itemID, durationAttributeID)
    546         if duration:
    547             dps = accDamage / duration
    548     return (accDamage, dps * 1000)
    549 
    550 
    551 def GetRangesForAbilitySlot(dogmaLocation, fighterID, typeID, abilitySlotID):
    552     maxRange = None
    553     falloffDist = None
    554     abilityID = GetAbilityIDForSlot(typeID, abilitySlotID)
    555     if abilityID:
    556         rangeAttributeID, falloffAttributeID = GetAbilityRangeAndFalloffAttributeIDs(dogmaLocation.dogmaStaticMgr, abilityID)
    557         if rangeAttributeID:
    558             maxRange = dogmaLocation.GetAccurateAttributeValue(fighterID, rangeAttributeID)
    559         if falloffAttributeID:
    560             falloffDist = dogmaLocation.GetAccurateAttributeValue(fighterID, falloffAttributeID)
    561     return (maxRange, falloffDist, abilityID)
    562 
    563 
    564 def AddDogmaOwnerModifiers(fittingDogmaLocation, fighterID):
    565     fighterDogmaItem = fittingDogmaLocation.SafeGetDogmaItem(fighterID)
    566     if fighterDogmaItem is not None:
    567         fighterDogmaItem.AddFighterControllerOwnerModifiers()
    568 
    569 
    570 def GetFullAndPartialSquadrons(dogmaLocation):
    571     full = 0
    572     partial = 0
    573     for flagID in const.fighterTubeFlags:
    574         dogmaItem = dogmaLocation.GetFightersForTube(flagID)
    575         if dogmaItem:
    576             squadronSize = dogmaItem.squadronSize
    577             if not squadronSize:
    578                 continue
    579             maxInSquadron = GetMaxSquadronSize(dogmaItem.typeID)
    580             if squadronSize < maxInSquadron:
    581                 partial += 1
    582             else:
    583                 full += 1
    584 
    585     return (full, partial)
    586 
    587 
    588 def GetHardware(dogmaLocation):
    589     shipDogmaItem = dogmaLocation.GetShipItem()
    590     if not shipDogmaItem:
    591         return []
    592     hardwareDict = {}
    593     for module in shipDogmaItem.GetFittedItems().itervalues():
    594         typeID = module.typeID
    595         if IsCharge(typeID):
    596             continue
    597         flagID = module.flagID
    598         flagInHardware = hardwareDict.get(typeID, None)
    599         if flagInHardware:
    600             flagID = min(flagInHardware, flagID)
    601         hardwareDict[typeID] = flagID
    602 
    603     hardwareList = [ (flagID, typeID) for typeID, flagID in hardwareDict.iteritems() ]
    604     lst = sorted(hardwareList, key=lambda data: data[0])
    605     return [ x[1] for x in lst ]
    606 
    607 
    608 def IsCharge(typeID):
    609     return evetypes.GetCategoryID(typeID) == const.categoryCharge