@Override
  public int getBVMod(Entity unit) {
    if (CampaignMain.cm.getBooleanConfig("USEFLATGUNNERYLASERMODIFIER")) {
      CampaignData.mwlog.debugLog("Using Flat GL Mod");
      return getBVModFlat(unit);
    }
    double laserBV = 0;
    double gunneryLaserBVBaseMod =
        megamek.common.Crew.getBVSkillMultiplier(
            unit.getCrew().getGunnery() - 1, unit.getCrew().getPiloting());
    double originalLaserBV = 0;
    for (Mounted weapon : unit.getWeaponList()) {
      if (weapon.getType().hasFlag(WeaponType.F_ENERGY)) {
        laserBV += weapon.getType().getBV(unit);
        originalLaserBV += weapon.getType().getBV(unit);
      }
    }
    // This is adding the base BV of the weapon twice - once originally, and once here.
    // Need to back out the original cost so that it only gets added once.
    CampaignData.mwlog.debugLog("Laser BV: " + laserBV);
    CampaignData.mwlog.debugLog("Original Laser BV: " + originalLaserBV);
    CampaignData.mwlog.debugLog(
        "Mod: " + (int) ((laserBV * gunneryLaserBVBaseMod) - originalLaserBV));

    return (int) ((laserBV * gunneryLaserBVBaseMod) - originalLaserBV);
  }
Example #2
0
  public float getTankWeightTurret() {
    float weight = 0f;

    // For omni vees, the base chassis sets a turret weight
    if (tank.isOmni() && tank.getBaseChassisTurretWeight() >= 0) {
      weight = tank.getBaseChassisTurretWeight();
    } else {
      // For non-omnis, count up the weight of eq in the turret
      for (Mounted m : tank.getEquipment()) {
        if ((m.getLocation() == tank.getLocTurret()) && !(m.getType() instanceof AmmoType)) {
          weight += m.getType().getTonnage(tank);
        }
      }
      // Turrets weight 10% of the weight of weapons in them
      weight = weight / 10.0f;
    }

    if (tank.isSupportVehicle()) {
      if (getEntity().getWeight() < 5) {
        return TestEntity.ceil(weight, CEIL_KILO);
      } else {
        return TestEntity.ceil(weight, CEIL_HALFTON);
      }
    } else {
      return TestEntity.ceilMaxHalf(weight, getWeightCeilingTurret());
    }
  }
  public int getBVModFlat(Entity unit) {
    int numberOfLasers = 0;
    int gunneryLaserBVBaseMod = CampaignMain.cm.getIntegerConfig("GunneryLaserBaseBVMod");

    for (Mounted weapon : unit.getWeaponList()) {
      if (weapon.getType().hasFlag(WeaponType.F_ENERGY)) {
        numberOfLasers++;
      }
    }
    return numberOfLasers * gunneryLaserBVBaseMod;
  }
Example #4
0
 @Override
 public String checkFixable() {
   if (null == unit) {
     return null;
   }
   if (isSalvaging()) {
     // check for armor
     if (unit.getEntity().getArmorForReal(loc, false) > 0
         || (unit.getEntity().hasRearArmor(loc)
             && unit.getEntity().getArmorForReal(loc, true) > 0)) {
       return "must salvage armor in this location first";
     }
     // you can only salvage a location that has nothing left on it
     int systemRepairable = 0;
     for (int i = 0; i < unit.getEntity().getNumberOfCriticals(loc); i++) {
       CriticalSlot slot = unit.getEntity().getCritical(loc, i);
       // ignore empty & non-hittable slots
       if ((slot == null) || !slot.isEverHittable()) {
         continue;
       }
       // we don't care about the final critical hit to the system
       // in locations because that just represents the location destruction
       if (slot.getType() == CriticalSlot.TYPE_SYSTEM) {
         if (slot.isRepairable()) {
           if (systemRepairable > 0) {
             return "Repairable parts in "
                 + unit.getEntity().getLocationName(loc)
                 + " must be salvaged or scrapped first.";
           } else {
             systemRepairable++;
           }
         }
       } else if (slot.isRepairable()) {
         return "Repairable parts in "
             + unit.getEntity().getLocationName(loc)
             + " must be salvaged or scrapped first.";
       }
     }
     // protomechs only have system stuff in the crits, so we need to also
     // check for mounted equipment separately
     for (Mounted m : unit.getEntity().getEquipment()) {
       if (m.isRepairable() && (m.getLocation() == loc || m.getSecondLocation() == loc)) {
         return "Repairable parts in "
             + unit.getEntity().getLocationName(loc)
             + " must be salvaged or scrapped first."
             + m.getName();
       }
     }
   }
   return null;
 }
Example #5
0
 @Override
 public void remove(boolean salvage) {
   blownOff = false;
   if (null != unit) {
     unit.getEntity().setInternal(IArmorState.ARMOR_DESTROYED, loc);
     unit.getEntity().setLocationBlownOff(loc, false);
     Part spare = campaign.checkForExistingSparePart(this);
     if (!salvage) {
       campaign.removePart(this);
     } else if (null != spare) {
       spare.incrementQuantity();
       campaign.removePart(this);
     }
     unit.removePart(this);
     if (loc != Protomech.LOC_TORSO) {
       Part missing = getMissingPart();
       unit.addPart(missing);
       campaign.addPart(missing, 0);
     }
     // According to StratOps, this always destroys all equipment in that location as well
     for (int i = 0; i < unit.getEntity().getNumberOfCriticals(loc); i++) {
       final CriticalSlot cs = unit.getEntity().getCritical(loc, i);
       if (null == cs || !cs.isEverHittable()) {
         continue;
       }
       cs.setHit(true);
       cs.setDestroyed(true);
       cs.setRepairable(false);
       Mounted m = cs.getMount();
       if (null != m) {
         m.setHit(true);
         m.setDestroyed(true);
         m.setRepairable(false);
       }
     }
     for (Mounted m : unit.getEntity().getEquipment()) {
       if (m.getLocation() == loc || m.getSecondLocation() == loc) {
         m.setHit(true);
         m.setDestroyed(true);
         m.setRepairable(false);
       }
     }
   }
   setUnit(null);
   updateConditionFromEntity(false);
 }
Example #6
0
 @Override
 public void fix() {
   super.fix();
   if (isBlownOff()) {
     blownOff = false;
     unit.getEntity().setLocationBlownOff(loc, false);
     for (int i = 0; i < unit.getEntity().getNumberOfCriticals(loc); i++) {
       CriticalSlot slot = unit.getEntity().getCritical(loc, i);
       // ignore empty & non-hittable slots
       if (slot == null) {
         continue;
       }
       slot.setMissing(false);
       Mounted m = slot.getMount();
       if (null != m) {
         m.setMissing(false);
       }
     }
   } else if (isBreached()) {
     breached = false;
     unit.getEntity().setLocationStatus(loc, ILocationExposureStatus.NORMAL, true);
     for (int i = 0; i < unit.getEntity().getNumberOfCriticals(loc); i++) {
       CriticalSlot slot = unit.getEntity().getCritical(loc, i);
       // ignore empty & non-hittable slots
       if (slot == null) {
         continue;
       }
       slot.setBreached(false);
       Mounted m = slot.getMount();
       if (null != m) {
         m.setBreached(false);
       }
     }
   } else {
     percent = 1.0;
     if (null != unit) {
       unit.getEntity().setInternal(unit.getEntity().getOInternal(loc), loc);
     }
   }
 }
Example #7
0
  private int getTankCountHeatLaserWeapons() {
    int heat = 0;
    for (Mounted m : tank.getWeaponList()) {
      WeaponType wt = (WeaponType) m.getType();
      if ((wt.hasFlag(WeaponType.F_LASER) && (wt.getAmmoType() == AmmoType.T_NA))
          || wt.hasFlag(WeaponType.F_PPC)
          || wt.hasFlag(WeaponType.F_PLASMA)
          || wt.hasFlag(WeaponType.F_PLASMA_MFUK)
          || (wt.hasFlag(WeaponType.F_FLAMER) && (wt.getAmmoType() == AmmoType.T_NA))) {
        heat += wt.getHeat();
      }
      // laser insulator reduce heat by 1, to a minimum of 1
      if (wt.hasFlag(WeaponType.F_LASER)
          && (m.getLinkedBy() != null)
          && !m.getLinkedBy().isInoperable()
          && m.getLinkedBy().getType().hasFlag(MiscType.F_LASER_INSULATOR)) {
        heat -= 1;
        if (heat == 0) {
          heat++;
        }
      }

      if ((m.getLinkedBy() != null)
          && (m.getLinkedBy().getType() instanceof MiscType)
          && m.getLinkedBy().getType().hasFlag(MiscType.F_PPC_CAPACITOR)) {
        heat += 5;
      }
    }
    for (Mounted m : tank.getMisc()) {
      MiscType mtype = (MiscType) m.getType();
      // mobile HPGs count as energy weapons for construction purposes
      if (mtype.hasFlag(MiscType.F_MOBILE_HPG)) {
        heat += 20;
      }
      if (mtype.hasFlag(MiscType.F_RISC_LASER_PULSE_MODULE)) {
        heat += 2;
      }
      if (mtype.hasFlag(MiscType.F_VIRAL_JAMMER_DECOY)
          || mtype.hasFlag(MiscType.F_VIRAL_JAMMER_DECOY)) {
        heat += 12;
      }
    }
    return heat;
  }
Example #8
0
 @Override
 public float getWeightPowerAmp() {
   if (!engine.isFusion() && (engine.getEngineType() != Engine.FISSION)) {
     int weight = 0;
     for (Mounted m : tank.getWeaponList()) {
       WeaponType wt = (WeaponType) m.getType();
       if (wt.hasFlag(WeaponType.F_ENERGY)
           && !(wt instanceof CLChemicalLaserWeapon)
           && !(wt instanceof VehicleFlamerWeapon)) {
         weight += wt.getTonnage(tank);
       }
       if ((m.getLinkedBy() != null)
           && (m.getLinkedBy().getType() instanceof MiscType)
           && m.getLinkedBy().getType().hasFlag(MiscType.F_PPC_CAPACITOR)) {
         weight += ((MiscType) m.getLinkedBy().getType()).getTonnage(tank);
       }
     }
     return TestEntity.ceil(weight / 10f, getWeightCeilingPowerAmp());
   }
   return 0;
 }
Example #9
0
  public boolean correctCriticals(StringBuffer buff) {
    Vector<Mounted> unallocated = new Vector<Mounted>();
    boolean correct = true;

    for (Mounted mount : tank.getMisc()) {
      if (mount.getLocation() == Entity.LOC_NONE && !(mount.getType().getCriticals(tank) == 0)) {
        unallocated.add(mount);
      }
    }
    for (Mounted mount : tank.getWeaponList()) {
      if (mount.getLocation() == Entity.LOC_NONE) {
        unallocated.add(mount);
      }
    }
    for (Mounted mount : tank.getAmmo()) {
      int ammoType = ((AmmoType) mount.getType()).getAmmoType();
      if ((mount.getLocation() == Entity.LOC_NONE)
          && (mount.getUsableShotsLeft() > 1 || ammoType == AmmoType.T_CRUISE_MISSILE)) {
        unallocated.add(mount);
      }
    }

    if (!unallocated.isEmpty()) {
      buff.append("Unallocated Equipment:\n");
      for (Mounted mount : unallocated) {
        buff.append(mount.getType().getInternalName()).append("\n");
      }
      correct = false;
    }

    return correct;
  }
Example #10
0
  @Override
  public boolean correctEntity(StringBuffer buff, int ammoTechLvl) {
    boolean correct = true;
    if (skip()) {
      return true;
    }
    if (!correctWeight(buff)) {
      buff.insert(0, printTechLevel() + printShortMovement());
      buff.append(printWeightCalculation()).append("\n");
      correct = false;
    }
    if (!engine.engineValid) {
      buff.append(engine.problem.toString()).append("\n\n");
      correct = false;
    }
    if (tank.hasWorkingMisc(MiscType.F_ARMORED_MOTIVE_SYSTEM)
        && !((tank.getMovementMode() == EntityMovementMode.WHEELED)
            || (tank.getMovementMode() == EntityMovementMode.TRACKED)
            || (tank.getMovementMode() == EntityMovementMode.HOVER)
            || (tank.getMovementMode() == EntityMovementMode.HYDROFOIL)
            || (tank.getMovementMode() == EntityMovementMode.NAVAL)
            || (tank.getMovementMode() == EntityMovementMode.SUBMARINE)
            || (tank.getMovementMode() == EntityMovementMode.WIGE))) {
      buff.append("Armored Motive system and incompatible movemement mode!\n\n");
      correct = false;
    }
    if (tank.getFreeSlots() < 0) {
      buff.append("Not enough item slots available! Using ");
      buff.append(Math.abs(tank.getFreeSlots()));
      buff.append(" slot(s) too many.\n\n");
      correct = false;
    }
    int armorLimit = (int) (((tank.getWeight() * 7) / 2) + 40);
    if (tank.getTotalOArmor() > armorLimit) {
      buff.append("Armor exceeds point limit for ");
      buff.append(tank.getWeight());
      buff.append("-ton vehicle: ");
      buff.append(tank.getTotalOArmor());
      buff.append(" points > ");
      buff.append(armorLimit);
      buff.append(".\n\n");
      correct = false;
    }
    if (tank instanceof VTOL) {
      if (!tank.hasWorkingMisc(MiscType.F_MAST_MOUNT)) {
        for (Mounted m : tank.getEquipment()) {
          if (m.getLocation() == VTOL.LOC_ROTOR) {
            buff.append("rotor equipment must be placed in mast mount");
            correct = false;
          }
        }
      }
      if (tank.getOArmor(VTOL.LOC_ROTOR) > VTOL_MAX_ROTOR_ARMOR) {
        buff.append(tank.getOArmor(VTOL.LOC_ROTOR));
        buff.append(
            " points of VTOL rotor armor exceed " + VTOL_MAX_ROTOR_ARMOR + "-point limit.\n\n");
        correct = false;
      }
    }
    for (Mounted m : tank.getMisc()) {
      if (m.getType().hasFlag(MiscType.F_COMBAT_VEHICLE_ESCAPE_POD)) {
        if (m.getLocation()
            != (tank instanceof SuperHeavyTank ? SuperHeavyTank.LOC_REAR : Tank.LOC_REAR)) {
          buff.append("combat vehicle escape pod must be placed in rear");
          correct = false;
        }
      }
    }
    for (int loc = 0; loc < tank.locations(); loc++) {
      int count = 0;
      for (Mounted misc : tank.getMisc()) {
        if ((misc.getLocation() == loc) && misc.getType().hasFlag(MiscType.F_MANIPULATOR)) {
          count++;
        }
      }
      if (count > 2) {
        buff.append("max of 2 manipulators per location");
        correct = false;
        break;
      }
    }

    if (showFailedEquip() && hasFailedEquipment(buff)) {
      correct = false;
    }
    if (hasIllegalTechLevels(buff, ammoTechLvl)) {
      correct = false;
    }
    if (hasIllegalEquipmentCombinations(buff)) {
      correct = false;
    }
    // only tanks with fusion engine can be vacuum protected
    if (!(tank.getEngine().isFusion()
            || (tank.getEngine().getEngineType() == Engine.FUEL_CELL)
            || (tank.getEngine().getEngineType() == Engine.SOLAR)
            || (tank.getEngine().getEngineType() == Engine.BATTERY)
            || (tank.getEngine().getEngineType() == Engine.FISSION)
            || (tank.getEngine().getEngineType() == Engine.NONE))
        && !tank.doomedInVacuum()) {
      buff.append("Vacuum protection requires fusion engine.\n");
      correct = false;
    }

    if (!correctCriticals(buff)) {
      correct = false;
    }
    return correct;
  }
Example #11
0
  public double calculateTotalHeat() {
    double heat = 0;

    if (getMech().getOriginalJumpMP() > 0) {
      if (getMech().getJumpType() == Mech.JUMP_IMPROVED) {
        heat += Math.max(3, Math.ceil(getMech().getOriginalJumpMP() / 2.0f));
      } else if (getMech().getJumpType() != Mech.JUMP_BOOSTER) {
        heat += Math.max(3, getMech().getOriginalJumpMP());
      }
      if (getMech().getEngine().getEngineType() == Engine.XXL_ENGINE) {
        heat *= 2;
      }
    } else if (getMech().getEngine().getEngineType() == Engine.XXL_ENGINE) {
      heat += 6;
    } else {
      heat += 2;
    }

    if (getMech().hasNullSig()) {
      heat += 10;
    }

    if (getMech().hasChameleonShield()) {
      heat += 6;
    }

    for (Mounted mounted : getMech().getWeaponList()) {
      WeaponType wtype = (WeaponType) mounted.getType();
      double weaponHeat = wtype.getHeat();

      // only count non-damaged equipment
      if (mounted.isMissing() || mounted.isHit() || mounted.isDestroyed() || mounted.isBreached()) {
        continue;
      }

      // one shot weapons count 1/4
      if ((wtype.getAmmoType() == AmmoType.T_ROCKET_LAUNCHER)
          || wtype.hasFlag(WeaponType.F_ONESHOT)) {
        weaponHeat *= 0.25;
      }

      // double heat for ultras
      if ((wtype.getAmmoType() == AmmoType.T_AC_ULTRA)
          || (wtype.getAmmoType() == AmmoType.T_AC_ULTRA_THB)) {
        weaponHeat *= 2;
      }

      // Six times heat for RAC
      if (wtype.getAmmoType() == AmmoType.T_AC_ROTARY) {
        weaponHeat *= 6;
      }

      // half heat for streaks
      if ((wtype.getAmmoType() == AmmoType.T_SRM_STREAK)
          || (wtype.getAmmoType() == AmmoType.T_MRM_STREAK)
          || (wtype.getAmmoType() == AmmoType.T_LRM_STREAK)) {
        weaponHeat *= 0.5;
      }
      heat += weaponHeat;
    }
    return heat;
  }
Example #12
0
  @Override
  public StringBuffer getTooltip() {

    // Tooltip info for a sensor blip
    if (onlyDetectedBySensors())
      return new StringBuffer(Messages.getString("BoardView1.sensorReturn"));

    // No sensor blip...
    Infantry thisInfantry = null;
    if (entity instanceof Infantry) thisInfantry = (Infantry) entity;
    GunEmplacement thisGunEmp = null;
    if (entity instanceof GunEmplacement) thisGunEmp = (GunEmplacement) entity;
    Aero thisAero = null;
    if (entity instanceof Aero) thisAero = (Aero) entity;

    tooltipString = new StringBuffer();

    // Unit Chassis and Player
    addToTT(
        "Unit",
        NOBR,
        Integer.toHexString(PlayerColors.getColorRGB(entity.getOwner().getColorIndex())),
        entity.getChassis(),
        entity.getOwner().getName());

    // Pilot Info
    // Nickname > Name > "Pilot"
    String pnameStr = "Pilot";

    if ((entity.getCrew().getName() != null) && !entity.getCrew().getName().equals(""))
      pnameStr = entity.getCrew().getName();

    if ((entity.getCrew().getNickname() != null) && !entity.getCrew().getNickname().equals(""))
      pnameStr = "'" + entity.getCrew().getNickname() + "'";

    addToTT("Pilot", BR, pnameStr, entity.getCrew().getGunnery(), entity.getCrew().getPiloting());

    // Pilot Status
    if (!entity.getCrew().getStatusDesc().equals(""))
      addToTT("PilotStatus", NOBR, entity.getCrew().getStatusDesc());

    // Pilot Advantages
    int numAdv = entity.getCrew().countOptions(PilotOptions.LVL3_ADVANTAGES);
    if (numAdv == 1) addToTT("Adv1", NOBR, numAdv);
    else if (numAdv > 1) addToTT("Advs", NOBR, numAdv);

    // Pilot Manei Domini
    if ((entity.getCrew().countOptions(PilotOptions.MD_ADVANTAGES) > 0)) addToTT("MD", NOBR);

    // Unit movement ability
    if (thisGunEmp == null) {
      addToTT("Movement", BR, entity.getWalkMP(), entity.getRunMPasString());
      if (entity.getJumpMP() > 0) tooltipString.append("/" + entity.getJumpMP());
    }

    // Armor and Internals
    addToTT("ArmorInternals", BR, entity.getTotalArmor(), entity.getTotalInternal());

    // Heat, not shown for units with 999 heat sinks (vehicles)
    if (entity.getHeatCapacity() != 999) {
      if (entity.heat == 0) addToTT("Heat0", BR);
      else addToTT("Heat", BR, entity.heat);
    }

    // Actual Movement
    if (thisGunEmp == null) {
      // In the Movement Phase, unit not done
      if (!entity.isDone() && this.bv.game.getPhase() == Phase.PHASE_MOVEMENT) {
        // "Has not yet moved" only during movement phase
        addToTT("NotYetMoved", BR);

        // In the Movement Phase, unit is done - or in the Firing Phase
      } else if ((entity.isDone() && this.bv.game.getPhase() == Phase.PHASE_MOVEMENT)
          || this.bv.game.getPhase() == Phase.PHASE_FIRING) {
        int tmm = Compute.getTargetMovementModifier(bv.game, entity.getId()).getValue();
        // Unit didn't move
        if (entity.moved == EntityMovementType.MOVE_NONE) {
          addToTT("NoMove", BR, tmm);

          // Unit did move
        } else {
          // Colored arrow
          // get the color resource
          String guipName = "AdvancedMoveDefaultColor";
          if ((entity.moved == EntityMovementType.MOVE_RUN)
              || (entity.moved == EntityMovementType.MOVE_VTOL_RUN)
              || (entity.moved == EntityMovementType.MOVE_OVER_THRUST))
            guipName = "AdvancedMoveRunColor";
          else if (entity.moved == EntityMovementType.MOVE_SPRINT)
            guipName = "AdvancedMoveSprintColor";
          else if (entity.moved == EntityMovementType.MOVE_JUMP) guipName = "AdvancedMoveJumpColor";

          // HTML color String from Preferences
          String moveTypeColor =
              Integer.toHexString(
                  GUIPreferences.getInstance().getColor(guipName).getRGB() & 0xFFFFFF);

          // Arrow
          addToTT("Arrow", BR, moveTypeColor);

          // Actual movement and modifier
          addToTT(
              "MovementF",
              NOBR,
              entity.getMovementString(entity.moved),
              entity.delta_distance,
              tmm);
        }
        // Special Moves
        if (entity.isEvading()) addToTT("Evade", NOBR);

        if ((thisInfantry != null) && (thisInfantry.isTakingCover())) addToTT("TakingCover", NOBR);

        if (entity.isCharging()) addToTT("Charging", NOBR);

        if (entity.isMakingDfa()) addToTT("DFA", NOBR);
      }
    }

    // ASF Velocity
    if (thisAero != null) {
      addToTT("AeroVelocity", BR, thisAero.getCurrentVelocity());
    }

    // Gun Emplacement Status
    if (thisGunEmp != null) {
      if (thisGunEmp.isTurret() && thisGunEmp.isTurretLocked(thisGunEmp.getLocTurret()))
        addToTT("TurretLocked", BR);
    }

    // Unit Immobile
    if ((thisGunEmp == null) && (entity.isImmobile())) addToTT("Immobile", BR);

    if (entity.isHiddenActivating()) {
      addToTT(
          "HiddenActivating",
          BR,
          IGame.Phase.getDisplayableName(entity.getHiddenActivationPhase()));
    } else if (entity.isHidden()) {
      addToTT("Hidden", BR);
    }

    // Jammed by ECM
    if (isAffectedByECM()) {
      addToTT("Jammed", BR);
    }

    // If DB, add information about who sees this Entity
    if (bv.game.getOptions().booleanOption("double_blind")) {
      StringBuffer playerList = new StringBuffer();
      boolean teamVision = bv.game.getOptions().booleanOption("team_vision");
      for (IPlayer player : entity.getWhoCanSee()) {
        if (player.isEnemyOf(entity.getOwner()) || !teamVision) {
          playerList.append(player.getName());
          playerList.append(", ");
        }
      }
      if (playerList.length() > 1) {
        playerList.delete(playerList.length() - 2, playerList.length());
        addToTT("SeenBy", BR, playerList.toString());
      }
    }

    // If sensors, display what sensors this unit is using
    if (bv.game.getOptions().booleanOption("tacops_sensors")) {
      addToTT("Sensors", BR, entity.getSensorDesc());
    }

    // Weapon List
    if (GUIPreferences.getInstance().getBoolean(GUIPreferences.SHOW_WPS_IN_TT)) {

      ArrayList<Mounted> weapons = entity.getWeaponList();
      HashMap<String, Integer> wpNames = new HashMap<String, Integer>();

      // Gather names, counts, Clan/IS
      // When clan then the number will be stored as negative
      for (Mounted curWp : weapons) {
        String weapDesc = curWp.getDesc();
        // Append ranges
        WeaponType wtype = (WeaponType) curWp.getType();
        int ranges[];
        if (entity instanceof Aero) {
          ranges = wtype.getATRanges();
        } else {
          ranges = wtype.getRanges(curWp);
        }
        String rangeString = "(";
        if ((ranges[RangeType.RANGE_MINIMUM] != WeaponType.WEAPON_NA)
            && (ranges[RangeType.RANGE_MINIMUM] != 0)) {
          rangeString += ranges[RangeType.RANGE_MINIMUM] + "/";
        } else {
          rangeString += "-/";
        }
        int maxRange = RangeType.RANGE_LONG;
        if (bv.game.getOptions().booleanOption(OptionsConstants.AC_TAC_OPS_RANGE)) {
          maxRange = RangeType.RANGE_EXTREME;
        }
        for (int i = RangeType.RANGE_SHORT; i <= maxRange; i++) {
          rangeString += ranges[i];
          if (i != maxRange) {
            rangeString += "/";
          }
        }

        weapDesc += rangeString + ")";
        if (wpNames.containsKey(weapDesc)) {
          int number = wpNames.get(weapDesc);
          if (number > 0) wpNames.put(weapDesc, number + 1);
          else wpNames.put(weapDesc, number - 1);
        } else {
          WeaponType wpT = ((WeaponType) curWp.getType());

          if (entity.isClan() && TechConstants.isClan(wpT.getTechLevel(entity.getYear())))
            wpNames.put(weapDesc, -1);
          else wpNames.put(weapDesc, 1);
        }
      }

      // Print to Tooltip
      tooltipString.append("<FONT SIZE=\"-2\">");

      for (Entry<String, Integer> entry : wpNames.entrySet()) {
        // Check if weapon is destroyed, text gray and strikethrough if so, remove the "x "/"*"
        // Also remove "+", means currently selected for firing
        boolean wpDest = false;
        String nameStr = entry.getKey();
        if (entry.getKey().startsWith("x ")) {
          nameStr = entry.getKey().substring(2, entry.getKey().length());
          wpDest = true;
        }

        if (entry.getKey().startsWith("*")) {
          nameStr = entry.getKey().substring(1, entry.getKey().length());
          wpDest = true;
        }

        if (entry.getKey().startsWith("+")) {
          nameStr = entry.getKey().substring(1, entry.getKey().length());
          nameStr = nameStr.concat(" <I>(Firing)</I>");
        }

        // normal coloring
        tooltipString.append("<FONT COLOR=#8080FF>");
        // but: color gray and strikethrough when weapon destroyed
        if (wpDest) tooltipString.append("<FONT COLOR=#a0a0a0><S>");

        String clanStr = "";
        if (entry.getValue() < 0) clanStr = Messages.getString("BoardView1.Tooltip.Clan");

        // when more than 5 weapons are present, they will be grouped
        // and listed with a multiplier
        if (weapons.size() > 5) {
          addToTT("WeaponN", BR, Math.abs(entry.getValue()), clanStr, nameStr);

        } else { // few weapons: list each weapon separately
          for (int i = 0; i < Math.abs(entry.getValue()); i++) {
            addToTT("Weapon", BR, Math.abs(entry.getValue()), clanStr, nameStr);
          }
        }
        // Weapon destroyed? End strikethrough
        if (wpDest) tooltipString.append("</S>");
        tooltipString.append("</FONT>");
      }
      tooltipString.append("</FONT>");
    }
    return tooltipString;
  }