Package megamek.common

Examples of megamek.common.ToHitData


            if ((target.getTargetType() == Targetable.TYPE_ENTITY)
                    && ((((Entity)target).getOwnerId() == ae.getOwnerId())
                            || ((((Entity)target).getOwner().getTeam() != Player.TEAM_NONE)
                                    && (ae.getOwner().getTeam() != Player.TEAM_NONE)
                                    && (ae.getOwner().getTeam() == ((Entity)target).getOwner().getTeam())))) {
                return new ToHitData(TargetRoll.IMPOSSIBLE, "A friendly unit can never be the target of a direct attack.");
            }
        }

        final IHex attHex = game.getBoard().getHex(ae.getPosition());
        final IHex targHex = game.getBoard().getHex(target.getPosition());
        if ((attHex == null) || (targHex == null)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "off board");
        }
        final int attackerElevation = ae.getElevation() + attHex.getElevation();
        final int targetHeight = target.absHeight() + targHex.getElevation();
        final int targetElevation = target.getElevation()
                + targHex.getElevation();
        final boolean targetInBuilding = Compute.isInBuilding(game, te);

        boolean inSameBuilding = Compute.isInSameBuilding(game, ae, te);
        Building bldg = null;
        if (targetInBuilding) {
            bldg = game.getBoard().getBuildingAt(te.getPosition());
        }
        ToHitData toHit;

        // can't target yourself
        if (ae.equals(te)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "You can't target yourself");
        }

        // non-protos can't make protomech-physicalattacks
        if (!(ae instanceof Protomech)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Non-protos can't make proto-physicalattacks");
        }

        // Can't target a transported entity.
        if ((te != null) && (Entity.NONE != te.getTransportId())) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is a passenger.");
        }

        // Can't target a entity conducting a swarm attack.
        if ((te != null) && (Entity.NONE != te.getSwarmTargetId())) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is swarming a Mek.");
        }

        // check range
        final int range = ae.getPosition().distance(target.getPosition());
        if (range > 1) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target not in range");
        }

        // check elevation
        if ((attackerElevation < targetElevation)
                || (attackerElevation > targetHeight)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target elevation not in range");
        }

        // can't physically attack mechs making dfa attacks
        if ((te != null) && te.isMakingDfa()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is making a DFA attack");
        }

        // can only target targets in adjacent hexes, not in same hex
        if (range == 0) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target not in adjacent hex");
        }

        // check facing
        // Don't check arc for stomping infantry or tanks.
        if ((0 != range)
                && !Compute.isInArc(ae.getPosition(), ae.getFacing(), target
                        .getPosition(), Compute.ARC_FORWARD)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target not in arc");
        }

        // Can't target units in buildings (from the outside).
        if ((0 != range) && targetInBuilding) {
            if (!Compute.isInBuilding(game, ae)) {
                return new ToHitData(TargetRoll.IMPOSSIBLE,
                        "Target is inside building");
            } else if (!game.getBoard().getBuildingAt(ae.getPosition()).equals(
                    bldg)) {
                return new ToHitData(TargetRoll.IMPOSSIBLE,
                        "Target is inside differnt building");
            }
        }

        // Attacks against adjacent buildings automatically hit.
        if ((target.getTargetType() == Targetable.TYPE_BUILDING)
                || (target.getTargetType() == Targetable.TYPE_FUEL_TANK)
                || (target instanceof GunEmplacement)) {
            return new ToHitData(TargetRoll.AUTOMATIC_SUCCESS,
                    "Targeting adjacent building.");
        }

        // Can't target woods or ignite a building with a physical.
        if ((target.getTargetType() == Targetable.TYPE_BLDG_IGNITE)
                || (target.getTargetType() == Targetable.TYPE_HEX_CLEAR)
                || (target.getTargetType() == Targetable.TYPE_HEX_IGNITE)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Invalid attack");
        }

        // Set the base BTH
        int base = 4;

        // Start the To-Hit
        toHit = new ToHitData(base, "base");

        // attacker movement
        toHit.append(Compute.getAttackerMovementModifier(game, attackerId));

        // target movement
        toHit.append(Compute.getTargetMovementModifier(game, targetId));

        // attacker terrain
        toHit.append(Compute.getAttackerTerrainModifier(game, attackerId));

        // target terrain
        toHit.append(Compute.getTargetTerrainModifier(game, te, 0, inSameBuilding));

        // attacker is spotting
        if (ae.isSpotting()) {
            toHit.addModifier(+1, "attacker is spotting");
        }

        // target prone
        if (te.isProne()) {
            toHit.addModifier(-2, "target prone and adjacent");
        }

        // water partial cover?
        if ((te.height() > 0) && (te.getElevation() == -1)
                && (targHex.terrainLevel(Terrains.WATER) == te.height())) {
            toHit.addModifier(3, "target has partial cover");
        }

        // target immobile
        toHit.append(Compute.getImmobileMod(te));

        toHit.append(nightModifiers(game, target, null, ae, false));

        Compute.modifyPhysicalBTHForAdvantages(ae, te, toHit, game);

        // elevation
        if (attackerElevation < targetHeight) {
            toHit.setHitTable(ToHitData.HIT_KICK);
        } else if (te.height() > 0) {
            toHit.setHitTable(ToHitData.HIT_PUNCH);
        } else {
            toHit.setHitTable(ToHitData.HIT_NORMAL);
        }

        // factor in target side
        toHit.setSideTable(Compute.targetSideTable(ae, te));

        // done!
        return toHit;
    }
View Full Code Here


            Targetable target, int arm) {
        final Entity ae = game.getEntity(attackerId);
        int targetId = Entity.NONE;
        Entity te = null;
        if (ae == null || target == null) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Attacker or target not valid");
        }
        if (target.getTargetType() == Targetable.TYPE_ENTITY) {
            te = (Entity) target;
            targetId = target.getTargetId();
        }
        final int armLoc = (arm == BrushOffAttackAction.RIGHT) ? Mech.LOC_RARM
                : Mech.LOC_LARM;
        ToHitData toHit;

        // non-mechs can't BrushOff
        if (!(ae instanceof Mech)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Only mechs can brush off swarming infantry or iNarc Pods");
        }

        // arguments legal?
        if (arm != BrushOffAttackAction.RIGHT
                && arm != BrushOffAttackAction.LEFT) {
            throw new IllegalArgumentException("Arm must be LEFT or RIGHT");
        }
        if ((targetId != ae.getSwarmAttackerId() || te == null || !(te instanceof Infantry))
                && target.getTargetType() != Targetable.TYPE_INARC_POD) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Can only brush off swarming infantry or iNarc Pods");
        }

        // Quads can't brush off.
        if (ae.entityIsQuad()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Attacker is a quad");
        }

        // Can't brush off with flipped arms
        if (ae.getArmsFlipped()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Arms are flipped to the rear. Can not punch.");
        }

        // check if arm is present
        if (ae.isLocationBad(armLoc)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Arm missing");
        }

        // check if shoulder is functional
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_SHOULDER, armLoc)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Shoulder destroyed");
        }

        // check if attacker has fired arm-mounted weapons
        if (ae.weaponFiredFrom(armLoc)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Weapons fired from arm this turn");
        }

        // can't physically attack mechs making dfa attacks
        if (te != null && te.isMakingDfa()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is making a DFA attack");
        }

        // Can't brush off while prone.
        if (ae.isProne()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Attacker is prone");
        }

        // Can't target woods or a building with a brush off attack.
        if (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.getTargetType() == Targetable.TYPE_HEX_CLEAR
                || target.getTargetType() == Targetable.TYPE_HEX_IGNITE) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Invalid attack");
        }

        // okay, modifiers...
        toHit = new ToHitData(ae.getCrew().getPiloting(), "base PSR");
        toHit.addModifier(4, "brush off swarming infantry");

        // damaged or missing actuators
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_UPPER_ARM, armLoc)) {
            toHit.addModifier(2, "Upper arm actuator destroyed");
        }
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_LOWER_ARM, armLoc)) {
            toHit.addModifier(2, "Lower arm actuator missing or destroyed");
        }
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_HAND, armLoc)) {
            toHit.addModifier(1, "Hand actuator missing or destroyed");
        }

        // 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 (((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 new ToHitData(TargetRoll.IMPOSSIBLE,
                        "Sensors Completely Destroyed for Torso-Mounted Cockpit");
            } else if (sensorHits == 2) {
                toHit.addModifier(4,
                        "Head Sensors Destroyed for Torso-Mounted Cockpit");
            }
        }

        Compute.modifyPhysicalBTHForAdvantages(ae, te, toHit, game);

        // If the target has assault claws, give a 1 modifier.
        // We can stop looking when we find our first match.
        if (te != null) {
            for (Mounted mount : te.getMisc()) {
                EquipmentType equip = mount.getType();
                if (BattleArmor.ASSAULT_CLAW.equals(equip.getInternalName())) {
                    toHit.addModifier(1, "defender has assault claws");
                    break;
                }
            }
        }
View Full Code Here

     */
    public static ToHitData toHit(IGame game, int attackerId, Targetable target) {
        final Entity ae = game.getEntity(attackerId);
        if ((target.getTargetType() != Targetable.TYPE_BUILDING)
                || (target.getTargetType() != Targetable.TYPE_FUEL_TANK)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "You can only target buildings");
        }
        if (ae == null)
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "You can't attack from a null entity!");
        // if(b == null || b.getId() != target.getTargetId())
        // return new ToHitData(TargetRoll.IMPOSSIBLE, "Target out of range");
        if (!(ae instanceof Infantry))
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Attacker is not infantry");
        Infantry inf = (Infantry) ae;
        if (inf.turnsLayingExplosives > 0)
            return new ToHitData(TargetRoll.AUTOMATIC_SUCCESS,
                    "STOP: Expected Damage: " + getDamageFor(ae));
        boolean ok = false;
        for (Mounted m : ae.getMisc()) {
            if (m.getType().hasFlag(MiscType.F_TOOLS)
                    && m.getType().hasSubType(MiscType.S_DEMOLITION_CHARGE)) {
                ok = true;
                break;
            }
        }
        if (!ok)
            return new ToHitData(TargetRoll.IMPOSSIBLE, "No explosives carried");
        return new ToHitData(TargetRoll.AUTOMATIC_SUCCESS,
                "START: Can't move or fire while laying explosives");
    }
View Full Code Here

            if ((target.getTargetType() == Targetable.TYPE_ENTITY)
                    && ((((Entity)target).getOwnerId() == ae.getOwnerId())
                            || ((((Entity)target).getOwner().getTeam() != Player.TEAM_NONE)
                                    && (ae.getOwner().getTeam() != Player.TEAM_NONE)
                                    && (ae.getOwner().getTeam() == ((Entity)target).getOwner().getTeam())))) {
                return new ToHitData(TargetRoll.IMPOSSIBLE, "A friendly unit can never be the target of a direct attack.");
            }
        }

        final IHex attHex = game.getBoard().getHex(ae.getPosition());
        final IHex targHex = game.getBoard().getHex(target.getPosition());
        if ((attHex == null) || (targHex == null)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "off board");
        }

        boolean inSameBuilding = Compute.isInSameBuilding(game, ae, te);

        ToHitData toHit;

        // can't target yourself
        if ((te != null) && ae.equals(te)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "You can't target yourself");
        }

        // only BA can make this attack
        if (!(ae instanceof BattleArmor)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Non-BA can't make vibroclaw-physicalattacks");
        }

        if ((te != null) && !((te instanceof Infantry))) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "can't target non-infantry");
        }

        // need to have vibroclaws to make this attack
        if (ae.getVibroClaws() == 0) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "no vibro claws mounted");
        }

        // Can't target a transported entity.
        if ((te != null) && (Entity.NONE != te.getTransportId())) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is a passenger.");
        }

        // Can't target a entity conducting a swarm attack.
        if ((te != null) && (Entity.NONE != te.getSwarmTargetId())) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is swarming a Mek.");
        }

        // check range
        final int range = ae.getPosition().distance(target.getPosition());
        if (range > 0) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target not in range");
        }

        // check elevation
        if ((te != null) && (te.getElevation() > 0)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target elevation not in range");
        }

        // can't physically attack mechs making dfa attacks
        if ((te != null) && te.isMakingDfa()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is making a DFA attack");
        }

        // Can't target woods or ignite a building with a physical.
        if ((target.getTargetType() == Targetable.TYPE_BLDG_IGNITE)
                || (target.getTargetType() == Targetable.TYPE_HEX_CLEAR)
                || (target.getTargetType() == Targetable.TYPE_HEX_IGNITE)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Invalid attack");
        }

        // Set the base BTH
        int base = ae.getCrew().getGunnery();

        // Start the To-Hit
        toHit = new ToHitData(base, "base");

        // attacker movement
        toHit.append(Compute.getAttackerMovementModifier(game, attackerId));

        // target movement
        toHit.append(Compute.getTargetMovementModifier(game, targetId));

        // attacker terrain
        toHit.append(Compute.getAttackerTerrainModifier(game, attackerId));

        // target terrain
        toHit.append(Compute.getTargetTerrainModifier(game, te, 0, inSameBuilding));

        // attacker is spotting
        if (ae.isSpotting()) {
            toHit.addModifier(+1, "attacker is spotting");
        }

        // taser feedback
        if (ae.getTaserFeedBackRounds() > 0) {
            toHit.addModifier(1, "Taser feedback");
        }

        // target immobile
        toHit.append(Compute.getImmobileMod(te));

        toHit.append(nightModifiers(game, target, null, ae, false));

        Compute.modifyPhysicalBTHForAdvantages(ae, te, toHit, game);

        // factor in target side
        toHit.setSideTable(Compute.targetSideTable(ae, te));

        // done!
        return toHit;
    }
View Full Code Here

            te = (Entity) target;
            targetId = target.getTargetId();
        }

        if (ae == null) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "You can't attack from a null entity!");
        }
        if (te == null) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "You can't target a null entity!");
        }

        IHex attHex = game.getBoard().getHex(ae.getPosition());
        IHex targHex = game.getBoard().getHex(te.getPosition());
        final int attackerElevation = ae.getElevation() + attHex.getElevation();
        final int targetElevation = target.getElevation()
                + targHex.getElevation();

        boolean inSameBuilding = Compute.isInSameBuilding(game, ae, te);
        final boolean targetInBuilding = Compute.isInBuilding(game, te);
        Building bldg = null;
        if (targetInBuilding) {
            bldg = game.getBoard().getBuildingAt(te.getPosition());
        }
        ToHitData toHit = null;

        // can't target yourself
        if (ae.equals(te)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "You can't target yourself");
        }

        // non-mechs can't push
        if (!(ae instanceof Mech)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Non-mechs can't push");
        }

        // Quads can't push
        if (ae.entityIsQuad()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Attacker is a quad");
        }

        // Can only push mechs
        if (!(te instanceof Mech)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target is not a mech");
        }

        // Can't push with flipped arms
        if (ae.getArmsFlipped()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Arms are flipped to the rear. Can not push.");
        }

        // Can't target a transported entity.
        if (Entity.NONE != te.getTransportId()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is a passenger.");
        }

        // Can't target a entity conducting a swarm attack.
        if (Entity.NONE != te.getSwarmTargetId()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is swarming a Mek.");
        }

        // check if both arms are present
        if (ae.isLocationBad(Mech.LOC_RARM) || ae.isLocationBad(Mech.LOC_LARM)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Arm missing");
        }

        // check if attacker has fired arm-mounted weapons
        if (ae.weaponFiredFrom(Mech.LOC_RARM)
                || ae.weaponFiredFrom(Mech.LOC_LARM)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Weapons fired from arm this turn");
        }

        // check range
        if (ae.getPosition().distance(target.getPosition()) > 1) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target not in range");
        }

        // target must be at same elevation
        if (attackerElevation != targetElevation) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target not at same elevation");
        }

        // can't push mech making non-pushing displacement attack
        if (te.hasDisplacementAttack() && !te.isPushing()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is making a charge/DFA attack");
        }

        // can't push mech pushing another, different mech
        if (te.isPushing()
                && (te.getDisplacementAttack().getTargetId() != ae.getId())) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is pushing another mech");
        }

        // can't do anything but counter-push if the target of another attack
        if (ae.isTargetOfDisplacementAttack()
                && (ae.findTargetedDisplacement().getEntityId() != target
                        .getTargetId())) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Attacker is the target of another push/charge/DFA");
        }

        // can't attack the target of another displacement attack
        if (te.isTargetOfDisplacementAttack()
                && (te.findTargetedDisplacement().getEntityId() != ae.getId())) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is the target of another push/charge/DFA");
        }

        // check facing
        if (!target.getPosition().equals(
                ae.getPosition().translated(ae.getFacing()))) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target not directly ahead of feet");
        }

        // can't push while prone
        if (ae.isProne()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Attacker is prone");
        }

        // can't push prone mechs
        if (te.isProne()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target is prone");
        }

        // Can't target units in buildings (from the outside).
        if (targetInBuilding) {
            if (!Compute.isInBuilding(game, ae)) {
                return new ToHitData(TargetRoll.IMPOSSIBLE,
                        "Target is inside building");
            } else if (!game.getBoard().getBuildingAt(ae.getPosition()).equals(
                    bldg)) {
                return new ToHitData(TargetRoll.IMPOSSIBLE,
                        "Target is inside differnt building");
            }
        }

        // Attacks against adjacent buildings automatically hit.
        if ((target.getTargetType() == Targetable.TYPE_BUILDING)
                || (target.getTargetType() == Targetable.TYPE_FUEL_TANK)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "You can not push a building (well, you can, but it won't do anything).");
        }

        // Can't target woods or ignite a building with a physical.
        if ((target.getTargetType() == Targetable.TYPE_BLDG_IGNITE)
                || (target.getTargetType() == Targetable.TYPE_HEX_CLEAR)
                || (target.getTargetType() == Targetable.TYPE_HEX_IGNITE)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Invalid attack");
        }

        // Set the base BTH
        int base = ae.getCrew().getPiloting() - 1;

        toHit = new ToHitData(base, "base");

        // attacker movement
        toHit.append(Compute.getAttackerMovementModifier(game, attackerId));

        // target movement
        toHit.append(Compute.getTargetMovementModifier(game, targetId));

        // attacker terrain
        toHit.append(Compute.getAttackerTerrainModifier(game, attackerId));

        // target terrain
        toHit.append(Compute.getTargetTerrainModifier(game, te, 0, inSameBuilding));

        // damaged or missing actuators
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_SHOULDER, Mech.LOC_RARM)) {
            toHit.addModifier(2, "Right Shoulder destroyed");
        }
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_SHOULDER, Mech.LOC_LARM)) {
            toHit.addModifier(2, "Left Shoulder destroyed");
        }

        // attacker is spotting
        if (ae.isSpotting()) {
            toHit.addModifier(+1, "attacker is spotting");
        }

        // water partial cover?
        if ((te.height() > 0) && (te.getElevation() == -1)
                && (targHex.terrainLevel(Terrains.WATER) == te.height())) {
            toHit.addModifier(3, "target has partial cover");
        }

        // target immobile
        toHit.append(Compute.getImmobileMod(te));

        Compute.modifyPhysicalBTHForAdvantages(ae, te, toHit, game);

        //evading
        if(te.isEvading()) {
            toHit.addModifier(te.getEvasionBonus(), "target is evading");
        }

        toHit.append(nightModifiers(game, target, null, ae, false));
        // side and elevation shouldn't matter

        // 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 (((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 new ToHitData(TargetRoll.IMPOSSIBLE,
                        "Sensors Completely Destroyed for Torso-Mounted Cockpit");
            } else if (sensorHits == 2) {
                toHit.addModifier(4,
                        "Head Sensors Destroyed for Torso-Mounted Cockpit");
            }
        }

        //Attacking Weight Class Modifier.
        if ( game.getOptions().booleanOption("tacops_attack_physical_psr") ) {
            if ( ae.getWeightClass() == EntityWeightClass.WEIGHT_LIGHT ) {
                toHit.addModifier(-2, "Weight Class Attack Modifier");
            }else if ( ae.getWeightClass() == EntityWeightClass.WEIGHT_MEDIUM ) {
                toHit.addModifier(-1, "Weight Class Attack Modifier");
            }
        }

        if (((Mech)ae).hasIndustrialTSM()) {
            toHit.addModifier(2, "industrial TSM");
        }

        // done!
        return toHit;
    }
View Full Code Here

     * used by the toHit of derived classes atype may be null if not using an
     * ammo based weapon
     */
    public static ToHitData nightModifiers(IGame game, Targetable target,
            AmmoType atype, Entity attacker, boolean isWeapon) {
        ToHitData toHit = null;
       
            Entity te = null;
            if (target.getTargetType() == Targetable.TYPE_ENTITY) {
                te = (Entity) target;
            }
            toHit = new ToHitData();

            int lightCond = game.getPlanetaryConditions().getLight();
            if(lightCond == PlanetaryConditions.L_DAY) {
                //not nighttime so just return
                return toHit;
            }
           
            // The base night penalty
            int night_modifier = 0;  
            night_modifier = game.getPlanetaryConditions().getLightHitPenalty(isWeapon);
            toHit.addModifier(night_modifier, game.getPlanetaryConditions().getLightCurrentName());

            boolean illuminated = false;
            if (te != null) {
                illuminated = te.isIlluminated();
                // hack for unresolved actions so client shows right BTH
                if (!illuminated) {
                    for (Enumeration<EntityAction> actions = game.getActions(); actions
                            .hasMoreElements();) {
                        EntityAction a = actions.nextElement();
                        if (a instanceof SearchlightAttackAction) {
                            SearchlightAttackAction saa = (SearchlightAttackAction) a;
                            if (saa.willIlluminate(game, te)) {
                                illuminated = true;
                                break;
                            }
                        }
                    }
                }
            }
            // Searchlights reduce the penalty to zero (or 1 for pitch-black) (except for dusk/dawn)
            int searchlightMod = Math.min(3, night_modifier);
            if(te != null && lightCond > PlanetaryConditions.L_DUSK) {
                if (te.isUsingSpotlight()) {
                    toHit.addModifier(-searchlightMod, "target using searchlight");
                    night_modifier = night_modifier - searchlightMod;
                } else if (illuminated) {
                    toHit.addModifier(-searchlightMod,"target illuminated by searchlight");
                    night_modifier = night_modifier - searchlightMod;
                }
            }
            /*
            // Ignored with EI system & implants
            else if (attacker.hasActiveEiCockpit()) {
                toHit.addModifier(-night_modifier, "EI system");
                night_modifier = 0;
            }
            */
            // So do flares
            else if (game.isPositionIlluminated(target.getPosition())) {
                toHit.addModifier(-night_modifier,
                        "target illuminated by flare");
                night_modifier = 0;
            }
            // Certain ammunitions reduce the penalty
            else if (atype != null) {
                if ((atype.getAmmoType() == AmmoType.T_AC || atype
                        .getAmmoType() == AmmoType.T_LAC)
                        && (atype.getMunitionType() == AmmoType.M_INCENDIARY_AC || atype
                                .getMunitionType() == AmmoType.M_TRACER)) {
                    toHit.addModifier(-1, "incendiary/tracer ammo");
                    night_modifier--;
                }
            }
            // Laser heatsinks
            if (night_modifier > 0 && te != null && te instanceof Mech
                    && ((Mech) te).hasLaserHeatSinks()) {
                boolean lhsused = false;
                if (te.heat > 0) {
                    toHit.addModifier(-night_modifier,
                            "target overheated with laser heatsinks");
                    night_modifier = 0;
                }
                // actions that generate heat give a -1 modifier
                else if (te.heatBuildup > 0 || te.isStealthActive()) {
                    lhsused = true;
                } else {
                    // Unfortunately, we can't just check weapons fired by the
                    // target
                    // because isUsedThisRound() is not valid if the attacker
                    // declared first.
                    // therefore, enumerate WeaponAttackActions...
                    for (Enumeration<EntityAction> actions = game.getActions(); actions
                            .hasMoreElements();) {
                        EntityAction a = actions.nextElement();
                        if (a instanceof WeaponAttackAction) {
                            WeaponAttackAction waa = (WeaponAttackAction) a;
                            if (waa.getEntityId() == te.getId()) {
                                Mounted weapon = te.getEquipment(waa
                                        .getWeaponId());
                                WeaponType wtype = (WeaponType) weapon
                                        .getType();
                                if (wtype.getHeat() != 0
                                        || weapon.isRapidfire()) {
                                    // target fired a weapon that generates heat
                                    lhsused = true;
                                    break;
                                }
                            }
                        }
                    }
                }

                if (lhsused) {
                    toHit.addModifier(-1, "target uses laser heatsinks");
                }
            }
           
           
            //now check for general hit bonuses for heat
            if(te != null && !(attacker instanceof Infantry && !(attacker instanceof BattleArmor))) {                
                int heatBonus = game.getPlanetaryConditions().getLightHeatBonus(te.heat);
                if(heatBonus < 0) {
                    toHit.addModifier(heatBonus, "target excess heat at night");
                }
            }
           
        return toHit;
    }
View Full Code Here

     * To-hit number for the specified leg to kick
     */
    public static ToHitData toHit(IGame game, int attackerId, Targetable target) {
        final Entity ae = game.getEntity(attackerId);
        if (ae == null) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "You can't attack from a null entity!");
        }

        if (!game.getOptions().booleanOption("tacops_trip_attack")) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "no Trip attack");
        }

        String impossible = PhysicalAttackAction.toHitIsImpossible(game, ae, target);
        if (impossible != null) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "impossible");
        }

        if ( ae.getGrappled() != Entity.NONE ) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "impossible");
        }

        if (!game.getOptions().booleanOption("friendly_fire")) {
            // a friendly unit can never be the target of a direct attack.
            if (target.getTargetType() == Targetable.TYPE_ENTITY
                    && (((Entity)target).getOwnerId() == ae.getOwnerId()
                            || (((Entity)target).getOwner().getTeam() != Player.TEAM_NONE
                                    && ae.getOwner().getTeam() != Player.TEAM_NONE
                                    && ae.getOwner().getTeam() == ((Entity)target).getOwner().getTeam()))) {
                return new ToHitData(TargetRoll.IMPOSSIBLE, "A friendly unit can never be the target of a direct attack.");
            }
        }

        ToHitData toHit;

        // non-mechs can't trip or be tripped
        if (!(ae instanceof Mech) || !(target instanceof Mech)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Only mechs can trip other mechs");
        }

        // described as a leg hook
        // needs 2 legs present
        if (ae.isLocationBad(Mech.LOC_LLEG) || ae.isLocationBad(Mech.LOC_RLEG)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Leg missing");
        }

        // check range
        final int range = ae.getPosition().distance(target.getPosition());
        if (range > 1) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target out of range");
        }

        int limb1 = Entity.LOC_NONE;

        // check facing
        if (!Compute.isInArc(ae.getPosition(), ae.getFacing(), target.getPosition(), Compute.ARC_FORWARD)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target not in arc");
        }

        // can't trip while prone
        if (ae.isProne()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Attacker is prone");
        }
        if (((Entity) target).isProne()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target is prone");
        }

        IHex attHex = game.getBoard().getHex(ae.getPosition());
        IHex targHex = game.getBoard().getHex(target.getPosition());
        final int attackerElevation = ae.getElevation() + attHex.getElevation();
        final int targetElevation = target.getElevation()
                + targHex.getElevation();

        if (attackerElevation != targetElevation){
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Attacker and Target must be at the same elevation");
        }

        // check if attacker has fired leg-mounted weapons
        boolean usedWeapons[] = new boolean[ae.locations()];
        for (int i = 0; i < ae.locations(); i++) {
            usedWeapons[i] = false;
        }

        for (Mounted mounted : ae.getWeaponList()) {
            if (mounted.isUsedThisRound()) {
                int loc = mounted.getLocation();
                if (loc != Entity.LOC_NONE) {
                    usedWeapons[loc] = true;
                }
            }
        }

        // check for good hips / shoulders
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_HIP, Mech.LOC_RLEG)) {
            usedWeapons[Mech.LOC_RLEG] = true;
        }
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_HIP, Mech.LOC_LLEG)) {
            usedWeapons[Mech.LOC_LLEG] = true;
        }
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_HIP, Mech.LOC_RARM)) {
            usedWeapons[Mech.LOC_RARM] = true;
        }
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_HIP, Mech.LOC_LARM)) {
            usedWeapons[Mech.LOC_LARM] = true;
        }

        if (ae instanceof QuadMech) {
            if (usedWeapons[Mech.LOC_RARM]) {
                if (usedWeapons[Mech.LOC_LARM]) {
                    return new ToHitData(TargetRoll.IMPOSSIBLE, "both legs unusable");
                }
                limb1 = Mech.LOC_LARM;
            }
        }
        // normal attack uses both legs
        else if (usedWeapons[Mech.LOC_RLEG]) {
            if (usedWeapons[Mech.LOC_LLEG]) {
                return new ToHitData(TargetRoll.IMPOSSIBLE, "both legs unusable");
            }
            limb1 = Mech.LOC_LLEG;
        }

        // Set the base BTH
        int base = ae.getCrew().getPiloting() - 1;

        // Start the To-Hit
        toHit = new ToHitData(base, "base");

        PhysicalAttackAction.setCommonModifiers(toHit, game, ae, target);

        // Get best leg
        if ( ae instanceof QuadMech ) {
            if (limb1 == Entity.LOC_NONE) {
                ToHitData left = TripAttackAction.getLimbModifier(Mech.LOC_LARM, ae);
                ToHitData right = TripAttackAction.getLimbModifier(Mech.LOC_RARM, ae);
                if (left.getValue() < right.getValue()) {
                    toHit.append(left);
                } else {
                    toHit.append(right);
                }
            } else {
                toHit.append(TripAttackAction.getLimbModifier(limb1, ae));
            }
        }
        else if (limb1 == Entity.LOC_NONE) {
            ToHitData left = TripAttackAction.getLimbModifier(Mech.LOC_LLEG, ae);
            ToHitData right = TripAttackAction.getLimbModifier(Mech.LOC_RLEG, ae);
            if (left.getValue() < right.getValue()) {
                toHit.append(left);
            } else {
                toHit.append(right);
            }
        } else {
View Full Code Here

        // done!
        return toHit;
    }

    private static ToHitData getLimbModifier(int loc, Entity ae) {
        ToHitData toHit = new ToHitData();
        // damaged or missing actuators
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_UPPER_LEG, loc)) {
            toHit.addModifier(2, "Upper leg actuator destroyed");
        }
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_LOWER_LEG, loc)) {
            toHit.addModifier(2, "Lower leg actuator destroyed");
        }
        if (!ae.hasWorkingSystem(Mech.ACTUATOR_FOOT, loc)) {
            toHit.addModifier(1, "Foot actuator destroyed");
        }
        return toHit;
    }
View Full Code Here

            throw new IllegalStateException("Attacker is null");
        }

        // Do to pretreatment of physical attacks, the target may be null.
        if (target == null) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target is null");
        }
       
        if(!(ae instanceof Aero)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Attacker is not Aero");
        }
       
        if(!(target instanceof Aero)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target is not Aero");
        }  
       
        if(ae instanceof FighterSquadron || target instanceof FighterSquadron) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "fighter squadrons may not ram nor be the target of a ramming attc");
        }

        Entity te = null;
        if (target.getTargetType() == Targetable.TYPE_ENTITY) {
            te = (Entity) target;
        }
       
        if (!game.getOptions().booleanOption("friendly_fire")) {
            // a friendly unit can never be the target of a direct attack.
            if (target.getTargetType() == Targetable.TYPE_ENTITY
                    && (((Entity)target).getOwnerId() == ae.getOwnerId()
                            || (((Entity)target).getOwner().getTeam() != Player.TEAM_NONE
                                    && ae.getOwner().getTeam() != Player.TEAM_NONE
                                    && ae.getOwner().getTeam() == ((Entity)target).getOwner().getTeam())))
                return new ToHitData(TargetRoll.IMPOSSIBLE, "A friendly unit can never be the target of a direct attack.");
        }
        IHex attHex = game.getBoard().getHex(src);
        IHex targHex = game.getBoard().getHex(target.getPosition());
        final int attackerElevation = elevation + attHex.getElevation();
        final int targetElevation = target.getElevation()
                + targHex.getElevation();
        ToHitData toHit = null;
        // can't target yourself
        if (ae.equals(te)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "You can't target yourself");
        }

        // Can't target a transported entity.
        if (te != null && Entity.NONE != te.getTransportId()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is a passenger.");
        }

        // check range
        if (src.distance(target.getPosition()) > 0) {
            return new ToHitData(TargetRoll.IMPOSSIBLE, "Target not in range");
        }

        // target must be at same elevation level
        if (attackerElevation != targetElevation) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target must be at the same elevation level");
        }

        // can't attack Aero making a different ramming attack
        if (te != null && te.isRamming()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target is already making a ramming attack");
        }

        //attacker
       
        // target must have moved already
        if (te != null && !te.isDone()) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Target must be done with movement");
        }
       
        //Set the base BTH      
        int base = 6 + te.getCrew().getPiloting() - ae.getCrew().getPiloting();
       
        toHit = new ToHitData(base, "base");

        Aero a = (Aero)ae;
       
        //target type
        if(target instanceof SpaceStation) {
            toHit.addModifier(-1,"target is a space station");
        } else if(target instanceof Warship) {
            toHit.addModifier(+1,"target is a warship");
        } else if(target instanceof Jumpship) {
            toHit.addModifier(+0,"target is a jumpship");
        } else if(target instanceof Dropship) {
            toHit.addModifier(+2,"target is a dropship");
        } else {
            toHit.addModifier(+4,"target is a fighter/small craft");
        }
       
        //attacker type
        if(a instanceof SpaceStation) {
            toHit.addModifier(+0,"attacker is a space station");
        } else if(a instanceof Warship) {
            toHit.addModifier(+1,"attacker is a warship");
        } else if(a instanceof Jumpship) {
            toHit.addModifier(+0,"attacker is a jumpship");
        } else if(a instanceof Dropship) {
            toHit.addModifier(-1,"attacker is a dropship");
        } else {
            toHit.addModifier(-2,"attacker is a fighter/small craft");
        }
       
        //can the target unit move
        if(target.isImmobile() || te.getWalkMP() == 0)
            toHit.addModifier(-2,"target cannot spend thrust");
           
        //sensor damage
        if(a.getSensorHits() > 0)
            toHit.addModifier(+1, "sensor damage");
           
        //avionics damage
        int avionics = a.getAvionicsHits();
        if(avionics > 3)
            avionics = 3;
        if(avionics > 0)
            toHit.addModifier(avionics, "avionics damage");
       
        //evading bonuses
        if (target.getTargetType() == Targetable.TYPE_ENTITY && te.isEvading()) {
            toHit.addModifier(te.getEvasionBonus(), "target is evading");
        }
       
        //determine hit direction
        toHit.setSideTable(te.sideTable(priorSrc));
       
        toHit.setHitTable(ToHitData.HIT_NORMAL);

        // done!
        return toHit;
    }
View Full Code Here

        Coords priorSrc = md.getSecondFinalPosition(ae.getPosition());
        MoveStep ramStep = null;

        // let's just check this
        if (!md.contains(MovePath.STEP_RAM)) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Ram action not found in movement path");
        }

        // determine last valid step
        md.compile(game, ae);
        for (final Enumeration<MoveStep> i = md.getSteps(); i.hasMoreElements();) {
            final MoveStep step = i.nextElement();
            if (step.getMovementType() == IEntityMovementType.MOVE_ILLEGAL) {
                break;
            }
            if (step.getType() == MovePath.STEP_RAM) {
                ramStep = step;
                ramSrc = step.getPosition();
                ramEl = step.getElevation();
            }
        }

        // need to reach target
        if (ramStep == null
                || !target.getPosition().equals(ramStep.getPosition())) {
            return new ToHitData(TargetRoll.IMPOSSIBLE,
                    "Could not reach target with movement");
        }
       
        return toHit(game, target, ramSrc, ramEl, priorSrc, ramStep.getMovementType());
    }
View Full Code Here

TOP

Related Classes of megamek.common.ToHitData

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.