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; }
@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); }
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()); } }
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; }
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; }
@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; }
@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; }
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; }
@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; }