Beispiel #1
0
def getSigRadiusMult(src, tgt, tgtSpeed, srcScramRange, tgtScrammables, tpMods,
                     tpDrones, tpFighters, distance):
    # Can blow non-immune ships and target profiles
    if tgt.isFit and tgt.item.ship.getModifiedItemAttr(
            'disallowOffensiveModifiers'):
        return 1
    inLockRange = checkLockRange(src=src, distance=distance)
    inDroneRange = checkDroneControlRange(src=src, distance=distance)
    initSig = tgt.getSigRadius()
    # No scrams or distance is longer than longest scram - nullify scrammables list
    if not inLockRange or srcScramRange is None or (distance is not None and
                                                    distance > srcScramRange):
        tgtScrammables = ()
    # TPing modules
    appliedMultipliers = {}
    if inLockRange:
        for tpData in tpMods:
            appliedBoost = tpData.boost * calculateRangeFactor(
                srcOptimalRange=tpData.optimal,
                srcFalloffRange=tpData.falloff,
                distance=distance)
            if appliedBoost:
                appliedMultipliers.setdefault(tpData.stackingGroup, []).append(
                    (1 + appliedBoost / 100, tpData.resAttrID))
    # TPing drones
    mobileTps = []
    if inLockRange:
        mobileTps.extend(tpFighters)
    if inLockRange and inDroneRange:
        mobileTps.extend(tpDrones)
    droneOpt = GraphSettings.getInstance().get('mobileDroneMode')
    atkRadius = src.getRadius()
    for mtpData in mobileTps:
        # Faster than target or set to follow it - apply full TP
        if (droneOpt == GraphDpsDroneMode.auto and mtpData.speed >= tgtSpeed
            ) or droneOpt == GraphDpsDroneMode.followTarget:
            appliedMtpBoost = mtpData.boost
        # Otherwise project from the center of the ship
        else:
            if distance is None:
                rangeFactorDistance = None
            else:
                rangeFactorDistance = distance + atkRadius - mtpData.radius
            appliedMtpBoost = mtpData.boost * calculateRangeFactor(
                srcOptimalRange=mtpData.optimal,
                srcFalloffRange=mtpData.falloff,
                distance=rangeFactorDistance)
        appliedMultipliers.setdefault(mtpData.stackingGroup, []).append(
            (1 + appliedMtpBoost / 100, mtpData.resAttrID))
    modifiedSig = tgt.getSigRadius(extraMultipliers=appliedMultipliers,
                                   ignoreAfflictors=tgtScrammables)
    if modifiedSig == math.inf and initSig == math.inf:
        return 1
    mult = modifiedSig / initSig
    # Ensure consistent results - round off a little to avoid float errors
    return floatUnerr(mult)
Beispiel #2
0
def getApplicationPerKey(src, distance):
    inLockRange = checkLockRange(src=src, distance=distance)
    inDroneRange = checkDroneControlRange(src=src, distance=distance)
    applicationMap = {}
    for mod in src.item.activeModulesIter():
        if not mod.isRemoteRepping():
            continue
        if not inLockRange:
            applicationMap[mod] = 0
        else:
            applicationMap[mod] = calculateRangeFactor(
                srcOptimalRange=mod.maxRange or 0,
                srcFalloffRange=mod.falloff or 0,
                distance=distance)
    for drone in src.item.activeDronesIter():
        if not drone.isRemoteRepping():
            continue
        if not inLockRange or not inDroneRange:
            applicationMap[drone] = 0
        else:
            applicationMap[drone] = 1
    # Ensure consistent results - round off a little to avoid float errors
    for k, v in applicationMap.items():
        applicationMap[k] = floatUnerr(v)
    return applicationMap
Beispiel #3
0
def getVortonMult(mod, distance, tgtSpeed, tgtSigRadius):
    rangeFactor = calculateRangeFactor(mod.getModifiedItemAttr('maxRange'), 0,
                                       distance)
    applicationFactor = _calcMissileFactor(
        atkEr=mod.getModifiedItemAttr('aoeCloudSize'),
        atkEv=mod.getModifiedItemAttr('aoeVelocity'),
        atkDrf=mod.getModifiedItemAttr('aoeDamageReductionFactor'),
        tgtSpeed=tgtSpeed,
        tgtSigRadius=tgtSigRadius)
    return rangeFactor * applicationFactor
Beispiel #4
0
 def _calculatePoint(self, x, miscParams, src, tgt, commonData):
     distance = x
     inLockRange = checkLockRange(src=src, distance=distance)
     inDroneRange = checkDroneControlRange(src=src, distance=distance)
     combinedStr = 0
     for strength, optimal, falloff, needsLock, needsDcr in commonData[
             'neuts']:
         if (needsLock and not inLockRange) or (needsDcr
                                                and not inDroneRange):
             continue
         combinedStr += strength * calculateRangeFactor(
             srcOptimalRange=optimal,
             srcFalloffRange=falloff,
             distance=distance)
     return combinedStr
Beispiel #5
0
def _calcTurretChanceToHit(atkSpeed, atkAngle, atkRadius, atkOptimalRange,
                           atkFalloffRange, atkTracking, atkOptimalSigRadius,
                           distance, tgtSpeed, tgtAngle, tgtRadius,
                           tgtSigRadius):
    """Calculate chance to hit for turret-based weapons."""
    # https://wiki.eveuniversity.org/Turret_mechanics#Hit_Math
    angularSpeed = _calcAngularSpeed(atkSpeed, atkAngle, atkRadius, distance,
                                     tgtSpeed, tgtAngle, tgtRadius)
    # Turrets can be activated regardless of range to target
    rangeFactor = calculateRangeFactor(atkOptimalRange,
                                       atkFalloffRange,
                                       distance,
                                       restrictedRange=False)
    trackingFactor = _calcTrackingFactor(atkTracking, atkOptimalSigRadius,
                                         angularSpeed, tgtSigRadius)
    cth = rangeFactor * trackingFactor
    return cth
Beispiel #6
0
 def _calculatePoint(self, x, miscParams, src, tgt, commonData):
     distance = x
     inLockRange = checkLockRange(src=src, distance=distance)
     inDroneRange = checkDroneControlRange(src=src, distance=distance)
     strMults = {}
     for strength, optimal, falloff, stackingGroup, needsLock, needsDcr in commonData[
             'tps']:
         if (needsLock and not inLockRange) or (needsDcr
                                                and not inDroneRange):
             continue
         strength *= calculateRangeFactor(srcOptimalRange=optimal,
                                          srcFalloffRange=falloff,
                                          distance=distance)
         strMults.setdefault(stackingGroup, []).append(
             (1 + strength / 100, None))
     strMult = calculateMultiplier(strMults)
     strength = (strMult - 1) * 100
     return strength
Beispiel #7
0
 def _calculatePoint(self, x, miscParams, src, tgt, commonData):
     distance = x
     inLockRange = checkLockRange(src=src, distance=distance)
     inDroneRange = checkDroneControlRange(src=src, distance=distance)
     velocityStrMults = {}
     timeStrMults = {}
     for velocityStr, timeStr, optimal, falloff, stackingGroup, needsLock, needsDcr in commonData[
             'gds']:
         if (needsLock and not inLockRange) or (needsDcr
                                                and not inDroneRange):
             continue
         rangeFactor = calculateRangeFactor(srcOptimalRange=optimal,
                                            srcFalloffRange=falloff,
                                            distance=distance)
         velocityStr *= rangeFactor
         timeStr *= rangeFactor
         velocityStrMults.setdefault(stackingGroup, []).append(
             (1 + velocityStr / 100, None))
         timeStrMults.setdefault(stackingGroup, []).append(
             (1 + timeStr / 100, None))
     velocityStrMult = calculateMultiplier(velocityStrMults)
     timeStrMult = calculateMultiplier(timeStrMults)
     strength = (1 - velocityStrMult * timeStrMult) * 100
     return strength
Beispiel #8
0
def getTackledSpeed(src, tgt, currentUntackledSpeed, srcScramRange,
                    tgtScrammables, webMods, webDrones, webFighters, distance):
    # Can slow down non-immune ships and target profiles
    if tgt.isFit and tgt.item.ship.getModifiedItemAttr(
            'disallowOffensiveModifiers'):
        return currentUntackledSpeed
    maxUntackledSpeed = tgt.getMaxVelocity()
    # What's immobile cannot be slowed
    if maxUntackledSpeed == 0:
        return maxUntackledSpeed
    inLockRange = checkLockRange(src=src, distance=distance)
    inDroneRange = checkDroneControlRange(src=src, distance=distance)
    speedRatio = currentUntackledSpeed / maxUntackledSpeed
    # No scrams or distance is longer than longest scram - nullify scrammables list
    if not inLockRange or srcScramRange is None or (distance is not None and
                                                    distance > srcScramRange):
        tgtScrammables = ()
    appliedMultipliers = {}
    # Modules first, they are always applied the same way
    if inLockRange:
        for wData in webMods:
            appliedBoost = wData.boost * calculateRangeFactor(
                srcOptimalRange=wData.optimal,
                srcFalloffRange=wData.falloff,
                distance=distance)
            if appliedBoost:
                appliedMultipliers.setdefault(wData.stackingGroup, []).append(
                    (1 + appliedBoost / 100, wData.resAttrID))
    maxTackledSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers,
                                         ignoreAfflictors=tgtScrammables)
    currentTackledSpeed = maxTackledSpeed * speedRatio
    # Drones and fighters
    mobileWebs = []
    if inLockRange:
        mobileWebs.extend(webFighters)
    if inLockRange and inDroneRange:
        mobileWebs.extend(webDrones)
    atkRadius = src.getRadius()
    # As mobile webs either follow the target or stick to the attacking ship,
    # if target is within mobile web optimal - it can be applied unconditionally
    longEnoughMws = [
        mw for mw in mobileWebs
        if distance is None or distance <= mw.optimal - atkRadius + mw.radius
    ]
    if longEnoughMws:
        for mwData in longEnoughMws:
            appliedMultipliers.setdefault(mwData.stackingGroup, []).append(
                (1 + mwData.boost / 100, mwData.resAttrID))
            mobileWebs.remove(mwData)
        maxTackledSpeed = tgt.getMaxVelocity(
            extraMultipliers=appliedMultipliers,
            ignoreAfflictors=tgtScrammables)
        currentTackledSpeed = maxTackledSpeed * speedRatio
    # Apply remaining webs, from fastest to slowest
    droneOpt = GraphSettings.getInstance().get('mobileDroneMode')
    while mobileWebs:
        # Process in batches unified by speed to save up resources
        fastestMwSpeed = max(mobileWebs, key=lambda mw: mw.speed).speed
        fastestMws = [mw for mw in mobileWebs if mw.speed == fastestMwSpeed]
        for mwData in fastestMws:
            # Faster than target or set to follow it - apply full slowdown
            if (droneOpt == GraphDpsDroneMode.auto
                    and mwData.speed >= currentTackledSpeed
                ) or droneOpt == GraphDpsDroneMode.followTarget:
                appliedMwBoost = mwData.boost
            # Otherwise project from the center of the ship
            else:
                if distance is None:
                    rangeFactorDistance = None
                else:
                    rangeFactorDistance = distance + atkRadius - mwData.radius
                appliedMwBoost = mwData.boost * calculateRangeFactor(
                    srcOptimalRange=mwData.optimal,
                    srcFalloffRange=mwData.falloff,
                    distance=rangeFactorDistance)
            appliedMultipliers.setdefault(mwData.stackingGroup, []).append(
                (1 + appliedMwBoost / 100, mwData.resAttrID))
            mobileWebs.remove(mwData)
        maxTackledSpeed = tgt.getMaxVelocity(
            extraMultipliers=appliedMultipliers,
            ignoreAfflictors=tgtScrammables)
        currentTackledSpeed = maxTackledSpeed * speedRatio
    # Ensure consistent results - round off a little to avoid float errors
    return floatUnerr(currentTackledSpeed)
Beispiel #9
0
def getFighterAbilityMult(fighter, ability, src, tgt, distance, tgtSpeed,
                          tgtSigRadius):
    fighterSpeed = fighter.getModifiedItemAttr('maxVelocity')
    attrPrefix = ability.attrPrefix
    # It's bomb attack
    if attrPrefix == 'fighterAbilityLaunchBomb':
        # Just assume we can land bomb anywhere
        return _calcBombFactor(
            atkEr=fighter.getModifiedChargeAttr('aoeCloudSize'),
            tgtSigRadius=tgtSigRadius)
    droneOpt = GraphSettings.getInstance().get('mobileDroneMode')
    # It's regular missile-based attack
    if (droneOpt == GraphDpsDroneMode.auto and fighterSpeed >= tgtSpeed
        ) or droneOpt == GraphDpsDroneMode.followTarget:
        rangeFactor = 1
    # Same as with drones, if fighters are slower - put them to center of
    # the ship and see how they apply
    else:
        if distance is None:
            rangeFactorDistance = None
        else:
            rangeFactorDistance = distance + src.getRadius(
            ) - fighter.getModifiedItemAttr('radius')
        rangeFactor = calculateRangeFactor(
            srcOptimalRange=fighter.getModifiedItemAttr(
                '{}RangeOptimal'.format(attrPrefix))
            or fighter.getModifiedItemAttr('{}Range'.format(attrPrefix)),
            srcFalloffRange=fighter.getModifiedItemAttr(
                '{}RangeFalloff'.format(attrPrefix)),
            distance=rangeFactorDistance)
    drf = fighter.getModifiedItemAttr('{}ReductionFactor'.format(attrPrefix),
                                      None)
    if drf is None:
        drf = fighter.getModifiedItemAttr(
            '{}DamageReductionFactor'.format(attrPrefix))
    drs = fighter.getModifiedItemAttr(
        '{}ReductionSensitivity'.format(attrPrefix), None)
    if drs is None:
        drs = fighter.getModifiedItemAttr(
            '{}DamageReductionSensitivity'.format(attrPrefix))
    missileFactor = _calcMissileFactor(
        atkEr=fighter.getModifiedItemAttr(
            '{}ExplosionRadius'.format(attrPrefix)),
        atkEv=fighter.getModifiedItemAttr(
            '{}ExplosionVelocity'.format(attrPrefix)),
        atkDrf=_calcAggregatedDrf(reductionFactor=drf,
                                  reductionSensitivity=drs),
        tgtSpeed=tgtSpeed,
        tgtSigRadius=tgtSigRadius)
    resistMult = 1
    if tgt.isFit:
        resistAttrID = fighter.getModifiedItemAttr(
            '{}ResistanceID'.format(attrPrefix))
        if resistAttrID:
            resistAttrInfo = Attribute.getInstance().getAttributeInfo(
                resistAttrID)
            if resistAttrInfo is not None:
                resistMult = tgt.item.ship.getModifiedItemAttr(
                    resistAttrInfo.name, 1)
    mult = rangeFactor * missileFactor * resistMult
    return mult