📄 weaponattackaction.java
字号:
&& !vf_cool) { return "Weapon can't put out fires"; } IHex hexTarget = game.getBoard().getHex(target.getPosition()); if(!hexTarget.containsTerrain(Terrains.FIRE)) { return "Target is not on fire."; } } else if(wtype.hasFlag(WeaponType.F_EXTINGUISHER)) { if(!((target instanceof Tank && ((Tank)target).isOnFire()) || (target instanceof Entity && ((Entity)target).infernos.getTurnsLeftToBurn() > 0))) { return "Target is not on fire."; } } // can't target non-wood hexes for clearing (except thin ice) if (Targetable.TYPE_HEX_CLEAR == target.getTargetType()) { IHex hexTarget = game.getBoard().getHex(target.getPosition()); if(!hexTarget.containsTerrain(Terrains.WOODS) && !hexTarget.containsTerrain(Terrains.JUNGLE) && !(hexTarget.containsTerrain(Terrains.ICE) && hexTarget.containsTerrain(Terrains.WATER))) { return "Target terrain cannot be cleared."; } // Infantry can't clear woods. if ( isAttackerInfantry ) { return "Infantry can not clear terrain."; } } // Infantry can't clear woods. if ( isAttackerInfantry && Targetable.TYPE_HEX_CLEAR == target.getTargetType() ) { return "Infantry can not clear woods."; } // Some weapons can't cause fires, but Infernos always can. if ( (vf_cool || wtype.hasFlag(WeaponType.F_NO_FIRES) && !isInferno) && Targetable.TYPE_HEX_IGNITE == target.getTargetType() ) { return "Weapon can not cause fires."; } // only woods and buildings can be set intentionally on fire if (target.getTargetType() == Targetable.TYPE_HEX_IGNITE && game.getOptions().booleanOption("no_ignite_clear") && !(game.getBoard().getHex(((HexTarget) target).getPosition()).containsTerrain(Terrains.WOODS) || game.getBoard().getHex(((HexTarget) target).getPosition()).containsTerrain(Terrains.JUNGLE) || game.getBoard().getHex(((HexTarget) target).getPosition()).containsTerrain(Terrains.FUEL_TANK) || game.getBoard().getHex(((HexTarget) target).getPosition()).containsTerrain(Terrains.BUILDING))) { return "Only woods and building hexes can be set on fire intentionally."; } // Can't target infantry with Inferno rounds (BMRr, pg. 141). // Also, enforce options for keeping vehicles and protos safe // if those options are checked. if ( isInferno && (te instanceof Infantry || te instanceof Tank && game.getOptions().booleanOption("vehicles_safe_from_infernos") || te instanceof Protomech && game.getOptions().booleanOption("protos_safe_from_infernos")) ) { return "Can not target that unit type with Inferno rounds."; } // The TAG system cannot target infantry. if( isTAG && te instanceof Infantry ) { return "Can not target infantry with TAG."; } // Can't raise the heat of infantry or tanks. if ( wtype.hasFlag(WeaponType.F_FLAMER) && wtype.hasModes() && weapon.curMode().equals("Heat") && !(te instanceof Mech) ) { return "Can only raise the heat level of Meks."; } // Handle solo attack weapons. if ( wtype.hasFlag(WeaponType.F_SOLO_ATTACK) ) { for ( Enumeration i = game.getActions(); i.hasMoreElements(); ) { Object o = i.nextElement(); if (!(o instanceof WeaponAttackAction)) { continue; } WeaponAttackAction prevAttack = (WeaponAttackAction)o; if (prevAttack.getEntityId() == attackerId) { // If the attacker fires another weapon, this attack fails. if ( weaponId != prevAttack.getWeaponId() ) { return "Other weapon attacks declared."; } } } } else if(isAttackerInfantry && !(ae instanceof BattleArmor)) { // check for trying to fire field gun after moving if(!wtype.hasFlag(WeaponType.F_INFANTRY) && ae.moved != IEntityMovementType.MOVE_NONE) { return "Can't fire field guns in same turn as moving"; } //check for mixing infantry and field gun attacks for ( Enumeration i = game.getActions(); i.hasMoreElements(); ) { Object o = i.nextElement(); if (!(o instanceof WeaponAttackAction)) { continue; } WeaponAttackAction prevAttack = (WeaponAttackAction)o; if (prevAttack.getEntityId() == attackerId) { Mounted prevWeapon = ae.getEquipment(prevAttack.getWeaponId()); if( prevWeapon.getType().hasFlag(WeaponType.F_INFANTRY) != wtype.hasFlag(WeaponType.F_INFANTRY) ) { return "Can't fire field guns and small arms at the same time."; } } } } // check if indirect fire is valid if (isIndirect && !game.getOptions().booleanOption("indirect_fire")) { return "Indirect fire option not enabled"; } if (isIndirect && game.getOptions().booleanOption("indirect_fire") && !game.getOptions().booleanOption("indirect_always_possible") && LosEffects.calculateLos(game, attackerId, target).canSee()) { return "Indirect fire impossible with direct LOS"; } // hull down vees can't fire front weapons if(ae instanceof Tank && ae.isHullDown() && weapon.getLocation() == Tank.LOC_FRONT) { return "Nearby terrain blocks front weapons."; } // Weapon in arc? if (!Compute.isInArc(game, attackerId, weaponId, target)) { return "Target not in arc."; } // BA Micro bombs only when flying if (atype != null && atype.getAmmoType() == AmmoType.T_BA_MICRO_BOMB) { if (ae.getElevation() == 0) { return "attacker must be at least at elevation 1"; } else if (target.getTargetType() != Targetable.TYPE_HEX_BOMB) { return "must target hex with bombs"; } } if (target.getTargetType() == Targetable.TYPE_HEX_BOMB && !(usesAmmo && atype.getAmmoType() == AmmoType.T_BA_MICRO_BOMB)) { return "Weapon can't deliver bombs"; } Entity spotter = null; if (isIndirect) { spotter = Compute.findSpotter(game, ae, target); if (spotter == null) { return "No available spotter"; } } int eistatus=0; // check LOS (indirect LOS is from the spotter) LosEffects los; ToHitData losMods; if (!isIndirect) { los = LosEffects.calculateLos(game, attackerId, target); if(ae.hasActiveEiCockpit()) { if(los.getLightWoods() > 0) eistatus = 2; else eistatus = 1; } losMods = los.losModifiers(game, eistatus); } else { los = LosEffects.calculateLos(game, spotter.getId(), target); // do not count attacker partial cover in indirect fire los.setAttackerCover(LosEffects.COVER_NONE); if(spotter.hasActiveEiCockpit()) { if(los.getLightWoods() > 0) eistatus = 2; else eistatus = 1; } losMods = los.losModifiers(game); } // if LOS is blocked, block the shot if (losMods.getValue() == ToHitData.IMPOSSIBLE && !isArtilleryIndirect) { return losMods.getDesc(); } // Must target infantry in buildings from the inside. if ( targetInBuilding && te instanceof Infantry && null == los.getThruBldg() ) { return "Attack on infantry crosses building exterior wall."; } // attacker partial cover means no leg weapons if (los.isAttackerCover() && ae.locationIsLeg(weapon.getLocation()) && ae.getLocationStatus(weapon.getLocation()) != ILocationExposureStatus.WET) { return "Nearby terrain blocks leg weapons."; } // Leg attacks, Swarm attacks, and // Mine Launchers don't use gunnery. if ( Infantry.LEG_ATTACK.equals( wtype.getInternalName() ) ) { toHit = Compute.getLegAttackBaseToHit( ae, te ); // Return if the attack is impossible. if ( ToHitData.IMPOSSIBLE == toHit.getValue() ) { return toHit.getDesc(); } } else if ( Infantry.SWARM_MEK.equals( wtype.getInternalName() ) ) { toHit = Compute.getSwarmMekBaseToHit( ae, te ); // Return if the attack is impossible. if ( ToHitData.IMPOSSIBLE == toHit.getValue() ) { return toHit.getDesc(); } } else if ( Infantry.STOP_SWARM.equals( wtype.getInternalName() ) ) { // Can't stop if we're not swarming, otherwise automatic. if ( Entity.NONE == ae.getSwarmTargetId() ) { return "Not swarming a Mek."; } } else if ( BattleArmor.MINE_LAUNCHER.equals(wtype.getInternalName()) ) { // Mine launchers can not hit infantry. if ( te instanceof Infantry ) { return "Can not attack infantry."; } } // Swarming infantry always hit their target, but // 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. if ( wtype.getDamage() == 0 ) { return "Weapon causes no damage."; } } else if ( Entity.NONE != ae.getSwarmTargetId() ) { return "Must target the Mek being swarmed."; } int distance = Compute.effectiveDistance(game, ae, target); if(atype != null && atype.getAmmoType() == AmmoType.T_LRM && atype.getMunitionType() == AmmoType.M_SEMIGUIDED) { if (te == null || te.getTaggedBy() == -1) { // from a rules clarification return "Semi-guided LRMs must target a unit tagged this turn"; } } // Handle direct artillery attacks. if (isArtilleryDirect) { if (distance >17) { return "Direct artillery attack at range >17 hexes."; } if (isHoming) { if (te == null || te.getTaggedBy() == -1) { // see BMRr p77 on board arrow IV return "On board homing shot must target a unit tagged this turn"; } } } if (isArtilleryIndirect) { int boardRange=(int)Math.ceil(distance / 17f); if (boardRange>wtype.getLongRange()) { return "Indirect artillery attack out of range"; } if (distance<=17 && !(losMods.getValue()==ToHitData.IMPOSSIBLE)) { return "Cannot fire indirectly at range <=17 hexes unless no LOS."; } if (isHoming) { if(ttype != Targetable.TYPE_HEX_ARTILLERY) { return "Off board homing shot must target a map sheet"; } } } if(ae instanceof Mech) { int grapple = ((Mech)ae).getGrappled(); if(grapple != Entity.NONE) { if(grapple != target.getTargetId()) { return "Can only attack grappled mech"; } int loc = weapon.getLocation(); if((loc != Mech.LOC_CT && loc != Mech.LOC_LT && loc != Mech.LOC_RT && loc != Mech.LOC_HEAD) || weapon.isRearMounted()) { return "Can only fire head and front torso weapons when grappled"; } } } return null; } /** * @return Returns the nemesisConfused. */ public boolean isNemesisConfused() { return nemesisConfused; } /** * @param nemesisConfused The nemesisConfused to set. */ public void setNemesisConfused(boolean nemesisConfused) { this.nemesisConfused = nemesisConfused; } public boolean isSwarmingMissiles() { return swarmingMissiles; } public void setSwarmingMissiles(boolean swarmingMissiles) { this.swarmingMissiles = swarmingMissiles; } public void setOldTargetId(int id) { oldTargetId = id; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -