📄 weaponattackaction.java
字号:
} else { // Harder at range. proneMod = new ToHitData(1, "target prone and at range"); } } if (proneMod != null) { toHit.append(proneMod); toSubtract += proneMod.getValue(); } // weapon to-hit modifier if (wtype.getToHitModifier() != 0) { toHit.addModifier(wtype.getToHitModifier(), "weapon to-hit modifier"); } // ammo to-hit modifier if (te != null && te.getMovementMode() == IEntityMovementMode.VTOL && (atype != null && (atype.getAmmoType() == AmmoType.T_AC_LBX || atype.getAmmoType() == AmmoType.T_AC_LBX_THB) && atype.getMunitionType() == AmmoType.M_CLUSTER) && te.getElevation() > 0 && te.getElevation() > game.getBoard().getHex(te.getPosition()).terrainLevel(Terrains.BLDG_ELEV) && te.getElevation() != game.getBoard().getHex(te.getPosition()).terrainLevel(Terrains.BRIDGE_ELEV)) { toHit.addModifier(-3, "flak to-hit modifier"); } else if (usesAmmo && atype.getToHitModifier() != 0) { toHit.addModifier(atype.getToHitModifier(), "ammunition to-hit modifier"); } // add iNarc bonus if (isINarcGuided) { toHit.addModifier(-1, "iNarc homing pod"); } if (isHaywireINarced) { toHit.addModifier(1, "iNarc Haywire pod"); } //Heavy infantry have +1 penalty if(ae instanceof Infantry && ae.hasWorkingMisc(MiscType.F_TOOLS, MiscType.S_HEAVY_ARMOR)) { toHit.addModifier(1, "Heavy Armor"); } // add targeting computer (except with LBX cluster ammo) if (aimingMode == IAimingModes.AIM_MODE_TARG_COMP && aimingAt != Mech.LOC_NONE) { if(ae.hasActiveEiCockpit()) { if(ae.hasTargComp()) { toHit.addModifier(2, "aiming with targeting computer & EI system"); } else { toHit.addModifier(6, "aiming with EI system"); } } else { toHit.addModifier(3, "aiming with targeting computer"); } } else { if (ae.hasTargComp() && wtype.hasFlag(WeaponType.F_DIRECT_FIRE) && (!usesAmmo || !((atype.getAmmoType() == AmmoType.T_AC_LBX || atype.getAmmoType() == AmmoType.T_AC_LBX_THB) && atype.getMunitionType() == AmmoType.M_CLUSTER))) { toHit.addModifier(-1, "targeting computer"); } } // Change hit table for elevation differences inside building. if ( null != los.getThruBldg() && aElev != tElev ) { // Tanks get hit in a random side. if ( target instanceof Tank ) { toHit.setSideTable( ToHitData.SIDE_RANDOM ); } else if ( target instanceof Mech ) { // Meks have special tables for shots from above and below. if ( aElev > tElev ) { toHit.setHitTable( ToHitData.HIT_ABOVE ); } else { toHit.setHitTable( ToHitData.HIT_BELOW ); } } } // Change hit table for partial cover, accomodate for partial underwater(legs) if (los.getTargetCover() != LosEffects.COVER_NONE) { if (ae.getLocationStatus(weapon.getLocation()) == ILocationExposureStatus.WET && (targHex.containsTerrain(Terrains.WATER) && targEl == 0 && te.height() > 0)) { //weapon underwater, target in partial water toHit.setHitTable(ToHitData.HIT_KICK); } else { if(game.getOptions().booleanOption("maxtech_partial_cover")) { toHit.setHitTable(ToHitData.HIT_PARTIAL_COVER); toHit.setCover(los.getTargetCover()); } else { toHit.setHitTable(ToHitData.HIT_PUNCH); toHit.setCover(LosEffects.COVER_HORIZONTAL); } } // XXX what to do about GunEmplacements with partial cover? } // factor in target side if ( isAttackerInfantry && 0 == distance ) { // Infantry attacks from the same hex are resolved against the front. toHit.setSideTable( ToHitData.SIDE_FRONT ); } else { toHit.setSideTable( Compute.targetSideTable(ae, target) ); } //deal with grapples if(target instanceof Mech) { int grapple = ((Mech)target).getGrappled(); if(grapple != Entity.NONE) { if(grapple == ae.getId()) toHit.addModifier(-4, "target grappled"); else if(!exchangeSwarmTarget) toHit.addModifier(1, "CQC, possible friendly fire"); else { //this -1 cancels the original +1 toHit.addModifier(-1, "friendly fire"); return toHit; } } } // remove old target movement and terrain mods, // add those for new target. if (exchangeSwarmTarget) { toHit.addModifier(-toSubtract, "original target mods"); toHit.append(Compute.getImmobileMod(oldTarget, aimingAt, aimingMode)); toHit.append(Compute.getTargetMovementModifier(game, oldTarget.getId())); toHit.append(Compute.getTargetTerrainModifier(game, game.getEntity(oldTarget.getId()))); distance = Compute.effectiveDistance(game, ae, oldTarget); if (oldTarget != null && oldTarget.isProne()) { // easier when point-blank if (distance <= 1) { proneMod = new ToHitData(-2, "target prone and adjacent"); } else { // Harder at range. proneMod = new ToHitData(1, "target prone and at range"); } } toHit.append(proneMod); if (!isECMAffected && !oldTarget.isEnemyOf(ae) && !(oldTarget.getBadCriticals(CriticalSlot.TYPE_SYSTEM, Mech.SYSTEM_SENSORS, Mech.LOC_HEAD) > 0) && atype.getMunitionType() == AmmoType.M_SWARM_I) { toHit.addModifier( +2, "Swarm-I at friendly unit with intact sensors"); } } // okay! return toHit; } private static String toHitIsImpossible(IGame game, Entity ae, Targetable target, Mounted weapon, AmmoType atype, WeaponType wtype, int ttype, boolean exchangeSwarmTarget, boolean usesAmmo, Entity te, boolean isTAG, boolean isInferno, boolean isAttackerInfantry, boolean isIndirect, int attackerId, int weaponId, boolean isArtilleryIndirect, Mounted ammo, boolean isArtilleryFLAK, boolean targetInBuilding, boolean isArtilleryDirect) { boolean isHoming = false; ToHitData toHit = null; if ( ae.hasShield() && ae.hasActiveShield(weapon.getLocation(),weapon.isRearMounted()) ) { return "Weapon blocked by active shield"; } // 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); int sensorHits2 = ae.getBadCriticals(CriticalSlot.TYPE_SYSTEM, Mech.SYSTEM_SENSORS, Mech.LOC_CT); if ((sensorHits + sensorHits2) == 3) { return "Sensors Completely Destroyed for Torso-Mounted Cockpit"; } } // missing, breached or jammed weapons can't fire if (!weapon.canFire() && !exchangeSwarmTarget) { return "Weapon is not in a state where it can be fired"; } // If we're lying mines, we can't shoot. if (ae.isLayingMines()) { return "Can't fire weapons when laying mines"; } // make sure weapon can deliver minefield if (target.getTargetType() == Targetable.TYPE_MINEFIELD_DELIVER && !AmmoType.canDeliverMinefield(atype)) { return "Weapon can't deliver minefields"; } if (target.getTargetType() == Targetable.TYPE_FLARE_DELIVER && !(usesAmmo && atype.getAmmoType() == AmmoType.T_LRM && atype.getMunitionType() == AmmoType.M_FLARE)) { return "Weapon can't deliver flares"; } if (game.getPhase() == IGame.PHASE_TARGETING && !isArtilleryIndirect) { return "Only indirect artillery can be fired in the targeting phase"; } if (game.getPhase() == IGame.PHASE_OFFBOARD && !isTAG) { return "Only TAG can be fired in the offboard attack phase"; } if (game.getPhase() != IGame.PHASE_OFFBOARD && isTAG) { return "TAG can only be fired in the offboard attack phase"; } if ( atype != null && atype.getAmmoType() == AmmoType.T_LRM && ( atype.getMunitionType() == AmmoType.M_THUNDER || atype.getMunitionType() == AmmoType.M_THUNDER_ACTIVE || atype.getMunitionType() == AmmoType.M_THUNDER_INFERNO || atype.getMunitionType() == AmmoType.M_THUNDER_VIBRABOMB|| atype.getMunitionType() == AmmoType.M_THUNDER_AUGMENTED ) && target.getTargetType() != Targetable.TYPE_MINEFIELD_DELIVER) { return "Weapon can only deliver minefields"; } if ( atype != null && atype.getAmmoType() == AmmoType.T_LRM && atype.getMunitionType() == AmmoType.M_FLARE && target.getTargetType() != Targetable.TYPE_FLARE_DELIVER) { return "Weapon can only deliver flares"; } // some weapons can only target infantry if ( wtype.hasFlag(WeaponType.F_INFANTRY_ONLY) ) { if (te != null && !(te instanceof Infantry) || target.getTargetType() != Targetable.TYPE_ENTITY) { return "Weapon can only be used against infantry"; } } // make sure weapon can clear minefield if (target instanceof MinefieldTarget && !AmmoType.canClearMinefield(atype)) { return "Weapon can't clear minefields"; } // Arty shots have to be with arty, non arty shots with non arty. if (wtype.hasFlag(WeaponType.F_ARTILLERY)) { //check artillery is targetted appropriately for its ammo long munition = AmmoType.M_STANDARD; if (atype != null) { munition = atype.getMunitionType(); } if (munition == AmmoType.M_HOMING) { //target type checked later because its different for direct/indirect (BMRr p77 on board arrow IV) isHoming = true; } else if (ttype != Targetable.TYPE_HEX_ARTILLERY && !isArtilleryFLAK) { return "Weapon must make artillery attacks."; } } else { //weapon is not artillery if (ttype == Targetable.TYPE_HEX_ARTILLERY) { return "Weapon can't make artillery attacks."; } } // can't target yourself, unless those are swarm missiles that // continued to a new target if (ae.equals(te) && !exchangeSwarmTarget) { return "You can't target yourself"; } // weapon operational? if (weapon.isDestroyed() || weapon.isBreached()) { return "Weapon not operational."; } // got ammo? // don't check if it's a swarm-missile-follow-on-attack, we used the ammo previously if ( usesAmmo && !exchangeSwarmTarget && (ammo == null || ammo.getShotsLeft() == 0 || ammo.isBreached()) ) { return "Weapon out of ammo."; } // Are we dumping that ammo? if ( usesAmmo && ammo.isDumping() ) { ae.loadWeaponWithSameAmmo( weapon ); if ( ammo.getShotsLeft() == 0 || ammo.isDumping() ) { return "Dumping remaining ammo."; } } // is the attacker even active? if (ae.isShutDown() || !ae.getCrew().isActive()) { return "Attacker is in no condition to fire weapons."; } // sensors operational? int sensorHits = ae.getBadCriticals(CriticalSlot.TYPE_SYSTEM, Mech.SYSTEM_SENSORS, Mech.LOC_HEAD); if (ae instanceof Mech && ((Mech)ae).getCockpitType() == Mech.COCKPIT_TORSO_MOUNTED) { sensorHits += ae.getBadCriticals(CriticalSlot.TYPE_SYSTEM, Mech.SYSTEM_SENSORS, Mech.LOC_CT); if (sensorHits > 2) return "Attacker sensors destroyed."; } else if (sensorHits > 1) { return "Attacker sensors destroyed."; } // Is the weapon blocked by a passenger? if ( ae.isWeaponBlockedAt(weapon.getLocation(), weapon.isRearMounted()) ) { return "Weapon blocked by passenger."; } // Can't target an entity conducting a swarm attack. if ( te != null && Entity.NONE != te.getSwarmTargetId() ) { return "Target is swarming a Mek."; } //"Cool" mode for vehicle flamer requires coolant system boolean vf_cool = false; if(atype != null && wtype.hasFlag(WeaponType.F_FLAMER) && weapon.curMode().equals("Cool")) { vf_cool = true; if(!ae.hasWorkingMisc(MiscType.F_COOLANT_SYSTEM,-1)) { return "Vehicle does not have a working coolant system"; } } if(Targetable.TYPE_HEX_EXTINGUISH == target.getTargetType()) { if(!wtype.hasFlag(WeaponType.F_EXTINGUISHER)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -