Ejemplo n.º 1
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
Ejemplo n.º 2
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)
Ejemplo n.º 3
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
Ejemplo n.º 4
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
Ejemplo n.º 5
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
Ejemplo n.º 6
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)
Ejemplo n.º 7
0
def getApplicationPerKey(src, tgt, atkSpeed, atkAngle, distance, tgtSpeed,
                         tgtAngle, tgtSigRadius):
    inLockRange = checkLockRange(src=src, distance=distance)
    inDroneRange = checkDroneControlRange(src=src, distance=distance)
    applicationMap = {}
    for mod in src.item.activeModulesIter():
        if not mod.isDealingDamage():
            continue
        if "ChainLightning" in mod.item.effects:
            if inLockRange:
                applicationMap[mod] = getVortonMult(mod=mod,
                                                    distance=distance,
                                                    tgtSpeed=tgtSpeed,
                                                    tgtSigRadius=tgtSigRadius)
        elif mod.hardpoint == FittingHardpoint.TURRET:
            if inLockRange:
                applicationMap[mod] = getTurretMult(mod=mod,
                                                    src=src,
                                                    tgt=tgt,
                                                    atkSpeed=atkSpeed,
                                                    atkAngle=atkAngle,
                                                    distance=distance,
                                                    tgtSpeed=tgtSpeed,
                                                    tgtAngle=tgtAngle,
                                                    tgtSigRadius=tgtSigRadius)
            else:
                applicationMap[mod] = 0
        elif mod.hardpoint == FittingHardpoint.MISSILE:
            # FoF missiles can shoot beyond lock range
            if inLockRange or (mod.charge is not None and 'fofMissileLaunching'
                               in mod.charge.effects):
                applicationMap[mod] = getLauncherMult(
                    mod=mod,
                    distance=distance,
                    tgtSpeed=tgtSpeed,
                    tgtSigRadius=tgtSigRadius)
            else:
                applicationMap[mod] = 0
        elif mod.item.group.name in ('Smart Bomb',
                                     'Structure Area Denial Module'):
            applicationMap[mod] = getSmartbombMult(mod=mod, distance=distance)
        elif mod.item.group.name == 'Missile Launcher Bomb':
            applicationMap[mod] = getBombMult(mod=mod,
                                              src=src,
                                              tgt=tgt,
                                              distance=distance,
                                              tgtSigRadius=tgtSigRadius)
        elif mod.item.group.name == 'Structure Guided Bomb Launcher':
            if inLockRange:
                applicationMap[mod] = getGuidedBombMult(
                    mod=mod,
                    src=src,
                    distance=distance,
                    tgtSigRadius=tgtSigRadius)
            else:
                applicationMap[mod] = 0
        elif mod.item.group.name in ('Super Weapon',
                                     'Structure Doomsday Weapon'):
            # Only single-target DDs need locks
            if not inLockRange and {
                    'superWeaponAmarr', 'superWeaponCaldari',
                    'superWeaponGallente', 'superWeaponMinmatar',
                    'lightningWeapon'
            }.intersection(mod.item.effects):
                applicationMap[mod] = 0
            else:
                applicationMap[mod] = getDoomsdayMult(
                    mod=mod,
                    tgt=tgt,
                    distance=distance,
                    tgtSigRadius=tgtSigRadius)
    for drone in src.item.activeDronesIter():
        if not drone.isDealingDamage():
            continue
        if inLockRange and inDroneRange:
            applicationMap[drone] = getDroneMult(drone=drone,
                                                 src=src,
                                                 tgt=tgt,
                                                 atkSpeed=atkSpeed,
                                                 atkAngle=atkAngle,
                                                 distance=distance,
                                                 tgtSpeed=tgtSpeed,
                                                 tgtAngle=tgtAngle,
                                                 tgtSigRadius=tgtSigRadius)
        else:
            applicationMap[drone] = 0
    for fighter in src.item.activeFightersIter():
        if not fighter.isDealingDamage():
            continue
        for ability in fighter.abilities:
            if not ability.dealsDamage or not ability.active:
                continue
            # Bomb launching doesn't need locks
            if inLockRange or ability.effect.name == 'fighterAbilityLaunchBomb':
                applicationMap[(fighter,
                                ability.effectID)] = getFighterAbilityMult(
                                    fighter=fighter,
                                    ability=ability,
                                    src=src,
                                    tgt=tgt,
                                    distance=distance,
                                    tgtSpeed=tgtSpeed,
                                    tgtSigRadius=tgtSigRadius)
            else:
                applicationMap[(fighter, ability.effectID)] = 0
    # Ensure consistent results - round off a little to avoid float errors
    for k, v in applicationMap.items():
        applicationMap[k] = floatUnerr(v)
    return applicationMap