@Override
  public void advance(float amount) {
    if (Global.getCombatEngine() == null) return;

    float t = Global.getCombatEngine().getTotalElapsedTime(false);
    if (t > timeOfNextUpdate) {
      timeOfNextUpdate = t + UPDATE_FREQUENCY;

      if (findTarget() == null) return;

      float selfOverloadTime = IceUtils.getBaseOverloadDuration(ship);
      float targetOverloadTime =
          IceUtils.estimateOverloadDurationOnHit(
              target, weapon.getDerivedStats().getDamagePerShot(), weapon.getDamageType());
      float incomingMissileDamage = IceUtils.estimateIncomingMissileDamage(ship);
      float fpOfSupport = IceUtils.getFPWorthOfSupport(ship, 2000);
      float fpOfEnemies = IceUtils.getFPWorthOfHostility(ship, 2000);
      fpOfEnemies = Math.max(0, fpOfEnemies - IceUtils.getFP(target) / 2);

      hitChance = IceUtils.getHitChance(weapon, target);
      targetWillDieSoonAnyway = (IceUtils.getLifeExpectancy(ship) < 3);
      overloadBalance = targetOverloadTime - selfOverloadTime;
      fpRatio = IceUtils.getFPStrength(target) / IceUtils.getFPStrength(ship);
      danger = Math.max(0, fpOfEnemies - fpOfSupport + incomingMissileDamage / 100f);
    }
  }
  ShipAPI findTarget() {
    target = IceUtils.getShipInLineOfFire(weapon);

    if (target != null && target.getOwner() != ship.getOwner()) {
      return target;
    } else return target = null;
  }
  @Override
  public void advance(float amount) {
    if (!missile.getSource().isAlive()) {
      IceUtils.destroy(missile);
      return;
    }

    super.advance(amount);

    weaponCooldown = Math.max(0, weaponCooldown - amount);

    if (target == null) return;

    Vector2f.add(destOffset, target.getLocation(), dest);

    accelerate();
    turnToward(dest);

    if (ammo > 0 && weaponCooldown == 0) {
      CombatEntityAPI nearest = null;
      float record = Float.MAX_VALUE;

      for (int i = 0; i < potentialTargets.size(); ++i) {
        CombatEntityAPI m = (CombatEntityAPI) potentialTargets.get(i);

        float dist2 = MathUtils.getDistanceSquared(missile, m);

        if (dist2 < record && dist2 <= WEAPON_RANGE_SQUARED) {
          record = dist2;
          nearest = m;
        }
      }

      if (nearest != null) {
        Global.getCombatEngine()
            .spawnProjectile(
                missile.getSource(),
                null,
                WEAPON_ID,
                missile.getLocation(),
                VectorUtils.getAngle(missile.getLocation(), nearest.getLocation()),
                new Vector2f());

        --ammo;
        weaponCooldown = WEAPON_COOLDOWN;
      }
    }
  }
  @Override
  public void evaluateCircumstances() {
    super.evaluateCircumstances();

    //        if(target == null || (!(target instanceof ShipAPI) || !((ShipAPI)target).isAlive())) {
    //            findTarget();
    //            return;
    //        }

    Vector2f.sub(
        MathUtils.getRandomPointInCircle(target.getLocation(), target.getCollisionRadius()),
        target.getLocation(),
        destOffset);

    if (missile.isFading() || ammo <= 0 || !missile.getSource().isAlive())
      IceUtils.destroy(missile);

    potentialTargets.clear();
    potentialTargets.addAll(AIUtils.getNearbyEnemyMissiles(missile, POTENTIAL_TARGET_RANGE));
    potentialTargets.addAll(AIUtils.getNearbyEnemies(missile, POTENTIAL_TARGET_RANGE));
  }
  public PdDroneMissileAI(MissileAPI missile) {
    super(missile);

    findTarget();
    this.circumstanceEvaluationTimer.setInterval(0.6f, 1.4f);

    int count = 0;

    Object[] missiles = Global.getCombatEngine().getMissiles().toArray();

    for (int i = missiles.length - 1; i >= 0; --i) {
      MissileAPI m = (MissileAPI) missiles[i];

      if (m.getProjectileSpecId().equals(MISSILE_ID) && m.getWeapon() == missile.getWeapon()) {
        ++count;

        if (count >= MAX_ACTIVE_DRONES) {
          IceUtils.destroy(m);
        }
      }
    }

    // missile.setCollisionClass(CollisionClass.FIGHTER);
  }