📄 weaponattackaction.java
字号:
// they can only target the Mek they're swarming. else if ( te != null && ae.getSwarmTargetId() == te.getId() ) { // Only certain weapons can be used in a swarm attack. return new ToHitData( ToHitData.AUTOMATIC_SUCCESS, "Attack during swarm.", ToHitData.HIT_SWARM, ToHitData.SIDE_FRONT ); } else if (isArtilleryFLAK) { toHit = new ToHitData(9, "artillery FLAK"); } else { toHit = new ToHitData(ae.crew.getGunnery(), "gunnery skill"); } //Engineer's fire extinguisher has fixed to hit number, //Note that coolant trucks make a regular attack. if(wtype.hasFlag(WeaponType.F_EXTINGUISHER)) { toHit = new ToHitData(8, "fire extinguisher"); if(target instanceof Entity && ((Entity)target).infernos.isStillBurning() || target instanceof Tank && ((Tank)target).isInfernoFire()) { toHit.addModifier(2, "inferno fire"); } if(Targetable.TYPE_HEX_EXTINGUISH == target.getTargetType() && game.getBoard().isInfernoBurning(target.getPosition())) { toHit.addModifier(2, "inferno fire"); } return toHit; } // If a unit is suffering from electromagnetic interference, they get a blanket +2. // Sucks to be them. if (ae.isSufferingEMI()) toHit.addModifier(+2, "electromagnetic interference"); if ( ae.hasShield() ){ //active shield has already been checked as it makes shots impossible //time to check passive defense and no defense if ( ae.hasPassiveShield(weapon.getLocation(),weapon.isRearMounted())) toHit.addModifier(+2, "weapon hampered by passive shield"); else if ( ae.hasNoDefenseShield(weapon.getLocation())) toHit.addModifier(+1, "weapon hampered by shield"); } // if we have BAP with MaxTech rules, and there are woods in the // way, and we are within BAP range, we reduce the BTH by 1 if (game.getOptions().booleanOption("maxtech_bap") && !isIndirect && te != null && ae.hasBAP() && ae.getBAPRange() >= Compute.effectiveDistance(game, ae, te) && !Compute.isAffectedByECM(ae,ae.getPosition(),te.getPosition()) && (game.getBoard().getHex(te.getPosition()) .containsTerrain(Terrains.WOODS) || game.getBoard().getHex(te.getPosition()) .containsTerrain(Terrains.JUNGLE) || los.getLightWoods() > 0 || los.getHeavyWoods() > 0 || los.getUltraWoods() > 0) ) { toHit.addModifier(-1, "target in/behind woods and attacker has BAP"); } // Is the pilot a weapon specialist? if (ae.crew.getOptions().stringOption("weapon_specialist").equals(wtype.getName())) { toHit.addModifier( -2, "weapon specialist" ); } // Has the pilot the appropriate gunnery skill? if (ae.crew.getOptions().booleanOption("gunnery_laser") && wtype.hasFlag(WeaponType.F_ENERGY) ) { toHit.addModifier ( -1, "Gunnery/Laser" ); } if (ae.crew.getOptions().booleanOption("gunnery_ballistic") && wtype.hasFlag(WeaponType.F_BALLISTIC) ) { toHit.addModifier ( -1, "Gunnery/Ballistic" ); } if (ae.crew.getOptions().booleanOption("gunnery_missile") && wtype.hasFlag(WeaponType.F_MISSILE) ) { toHit.addModifier ( -1, "Gunnery/Missile" ); } // If it has a torso-mounted cockpit and two head sensor hits or three sensor hits... // It gets a =4 penalty for being blind! if (ae instanceof Mech && ((Mech)ae).getCockpitType() == Mech.COCKPIT_TORSO_MOUNTED) { int sensorHits = ae.getBadCriticals(CriticalSlot.TYPE_SYSTEM, Mech.SYSTEM_SENSORS, Mech.LOC_HEAD); if (sensorHits == 2) { toHit.addModifier(4, "Head Sensors Destroyed for Torso-Mounted Cockpit"); } } // Do we use Listen-Kill ammo from War of 3039 sourcebook? if (!isECMAffected && atype != null && (atype.getAmmoType() == AmmoType.T_LRM || atype.getAmmoType() == AmmoType.T_SRM) && atype.getMunitionType() == AmmoType.M_LISTEN_KILL && !(te != null && te.isClan())) { toHit.addModifier(-1, "Listen-Kill ammo"); } // determine some more variables int aElev = ae.getElevation(); int tElev = target.getElevation(); int distance = Compute.effectiveDistance(game, ae, target); toHit.append(nightModifiers(game, target, atype, ae)); // Handle direct artillery attacks. if (isArtilleryDirect) { if (!isArtilleryFLAK) { toHit.addModifier(5, "direct artillery modifer"); } toHit.append(Compute.getAttackerMovementModifier(game, attackerId)); toHit.append(losMods); toHit.append(Compute.getSecondaryTargetMod(game, ae, target)); // actuator & sensor damage to attacker toHit.append(Compute.getDamageWeaponMods(ae, weapon)); // heat if (ae.getHeatFiringModifier() != 0) { toHit.addModifier(ae.getHeatFiringModifier(), "heat"); } // weapon to-hit modifier if (wtype.getToHitModifier() != 0) { toHit.addModifier(wtype.getToHitModifier(), "weapon to-hit modifier"); } // ammo to-hit modifier if (usesAmmo && atype.getToHitModifier() != 0) { toHit.addModifier(atype.getToHitModifier(), "ammunition to-hit modifier"); } if (isHoming) { return new ToHitData(4, "Homing shot"); } if (game.getEntity(attackerId).getOwner().getArtyAutoHitHexes().contains(target.getPosition()) && !isArtilleryFLAK) { return new ToHitData(ToHitData.AUTOMATIC_SUCCESS, "Artillery firing at designated artillery target."); } return toHit; } if (isArtilleryIndirect) { if (isHoming) { return new ToHitData(4, "Homing shot (will miss if TAG misses)"); } if (game.getEntity(attackerId).getOwner().getArtyAutoHitHexes().contains(target.getPosition())) { return new ToHitData(ToHitData.AUTOMATIC_SUCCESS, "Artillery firing at designated artillery target."); } toHit.addModifier(7, "indirect artillery modifier"); int adjust = ae.aTracker.getModifier(weapon,target.getPosition()); if (adjust==ToHitData.AUTOMATIC_SUCCESS) { return new ToHitData(ToHitData.AUTOMATIC_SUCCESS, "Artillery firing at target that's been hit before."); } else if (adjust!=0) { toHit.addModifier(adjust, "adjusted fire"); } return toHit; } // Attacks against adjacent buildings automatically hit. if (distance == 1 && (target.getTargetType() == Targetable.TYPE_BUILDING || target.getTargetType() == Targetable.TYPE_BLDG_IGNITE || target.getTargetType() == Targetable.TYPE_FUEL_TANK || target.getTargetType() == Targetable.TYPE_FUEL_TANK_IGNITE || target instanceof GunEmplacement)) { return new ToHitData(ToHitData.AUTOMATIC_SUCCESS, "Targeting adjacent building."); } // Attacks against buildings from inside automatically hit. if (null != los.getThruBldg() && (target.getTargetType() == Targetable.TYPE_BUILDING || target.getTargetType() == Targetable.TYPE_BLDG_IGNITE || target.getTargetType() == Targetable.TYPE_FUEL_TANK || target.getTargetType() == Targetable.TYPE_FUEL_TANK_IGNITE || target instanceof GunEmplacement)) { return new ToHitData(ToHitData.AUTOMATIC_SUCCESS, "Targeting building from inside (are you SURE this is a good idea?)."); } // add range mods toHit.append(Compute.getRangeMods(game, ae, weaponId, target)); // If it's an anti-air system, add mods for that if (ae.getTargSysType() == MiscType.T_TARGSYS_ANTI_AIR && target instanceof Entity) { if (target instanceof VTOL) toHit.addModifier(-2, "anti-air targetting system vs. VTOL"); else toHit.addModifier(1, "anti-air targetting system vs. non-aerial unit"); } // Battle Armor targets are hard for Meks and Tanks to hit. if ( !isAttackerInfantry && te != null && te instanceof BattleArmor ) { toHit.addModifier( 1, "battle armor target" ); } // Ejected MechWarriors are harder to hit if ( te != null && te instanceof MechWarrior ) { toHit.addModifier( 2, "ejected MechWarrior target" ); } // Indirect fire has a +1 mod if (isIndirect) { toHit.addModifier( 1, "indirect fire" ); } // attacker movement toHit.append(Compute.getAttackerMovementModifier(game, attackerId)); // target movement if (te != null) { ToHitData thTemp = Compute.getTargetMovementModifier(game, target.getTargetId()); toHit.append(thTemp); toSubtract += thTemp.getValue(); // semiguided ammo negates this modifier, if TAG succeeded if (atype != null && atype.getAmmoType() == AmmoType.T_LRM && atype.getMunitionType() == AmmoType.M_SEMIGUIDED && te.getTaggedBy() != -1) { int nAdjust = thTemp.getValue(); if (nAdjust > 0) { toHit.append(new ToHitData(-nAdjust, "Semi-guided ammo vs tagged target")); } } // precision ammo reduces this modifier else if (atype != null && (atype.getAmmoType() == AmmoType.T_AC || atype.getAmmoType() == AmmoType.T_LAC) && atype.getMunitionType() == AmmoType.M_PRECISION) { int nAdjust = Math.min(2, thTemp.getValue()); if (nAdjust > 0) { toHit.append(new ToHitData(-nAdjust, "Precision Ammo")); } } } // Armor Piercing ammo is a flat +1 if ( atype != null && (atype.getAmmoType() == AmmoType.T_AC || atype.getAmmoType() == AmmoType.T_LAC) && atype.getMunitionType() == AmmoType.M_ARMOR_PIERCING ) { toHit.addModifier( 1, "Armor-Piercing Ammo" ); } // spotter movement, if applicable if (isIndirect) { // semiguided ammo negates this modifier, if TAG succeeded if (atype != null && atype.getAmmoType() == AmmoType.T_LRM && atype.getMunitionType() == AmmoType.M_SEMIGUIDED && te.getTaggedBy() != -1) { toHit.addModifier(-1 , "semiguided ignores spotter movement & indirect fire penalties"); } else { toHit.append(Compute.getSpotterMovementModifier(game, spotter.getId())); } } // attacker terrain toHit.append(Compute.getAttackerTerrainModifier(game, attackerId)); // target terrain, not applicable when delivering minefields if (target.getTargetType() != Targetable.TYPE_MINEFIELD_DELIVER) { toHit.append(Compute.getTargetTerrainModifier(game, target, eistatus)); toSubtract += Compute.getTargetTerrainModifier(game, target, eistatus).getValue(); } // target in water? IHex targHex = game.getBoard().getHex(target.getPosition()); if (targHex.containsTerrain(Terrains.WATER) && targHex.terrainLevel(Terrains.WATER) == 1 && targEl == 0 && te.height() > 0) { //target in partial water los.setTargetCover(los.getTargetCover() | LosEffects.COVER_HORIZONTAL); losMods = los.losModifiers(game, eistatus); } if(target instanceof Infantry && !wtype.hasFlag(WeaponType.F_FLAMER)) { if(targHex.containsTerrain(Terrains.FORTIFIED) || ((Infantry)target).getDugIn() == Infantry.DUG_IN_COMPLETE) { toHit.addModifier(2, "infantry dug in"); } } // add in LOS mods that we've been keeping toHit.append(losMods); if (te != null && te.isHullDown() && (te instanceof Mech && los.getTargetCover() > LosEffects.COVER_NONE || te instanceof Tank && targHex.containsTerrain(Terrains.FORTIFIED) && te.sideTable(ae.getPosition()) == ToHitData.SIDE_FRONT)) { toHit.addModifier(2, "Hull down target"); } // secondary targets modifier, // if this is not a iNarc Nemesis confused attack if (!isNemesisConfused) { toHit.append(Compute.getSecondaryTargetMod(game, ae, target, exchangeSwarmTarget)); } // heat if (ae.getHeatFiringModifier() != 0) { toHit.addModifier(ae.getHeatFiringModifier(), "heat"); } // actuator & sensor damage to attacker toHit.append(Compute.getDamageWeaponMods(ae, weapon)); // target immobile ToHitData immobileMod = Compute.getImmobileMod(target, aimingAt, aimingMode); if (immobileMod != null) { toHit.append(immobileMod); toSubtract += immobileMod.getValue(); } // attacker prone toHit.append(Compute.getProneMods(game, ae, weaponId)); // target prone ToHitData proneMod = null; if (te != null && te.isProne()) { // easier when point-blank if (distance <= 1) { // BMRr, pg. 72: Swarm Mek attacks get "an additional -4 // if the BattleMech is prone or immoble." I interpret // this to mean that the bonus gets applied *ONCE*. if ( Infantry.SWARM_MEK.equals( wtype.getInternalName() ) ) { // If the target is immoble, don't give a bonus for prone. if ( !te.isImmobile() ) { proneMod = new ToHitData(-4, "swarm prone target"); } } else { proneMod = new ToHitData(-2, "target prone and adjacent"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -