⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compute.java

📁 MegaMek is a networked Java clone of BattleTech, a turn-based sci-fi boardgame for 2+ players. Fight
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
        // allow naval units on surface to be attacked from above or below        Entity te = null;        if (target instanceof Entity) {            te = (Entity) target;            if (targBottom == 0                    && UnitType.determineUnitTypeCode(te) == UnitType.NAVAL) {                targetInPartialWater = true;            }        }        // allow naval units to target underwater units,        // torpedo tubes are mounted underwater        if ((targetUnderwater || wtype.getAmmoType() == AmmoType.T_LRM_TORPEDO                || wtype.getAmmoType() == AmmoType.T_SRM_TORPEDO)                && UnitType.determineUnitTypeCode(ae) == UnitType.NAVAL) {            weaponUnderwater = true;            weaponRanges = wtype.getWRanges();        }        // allow ice to be cleared from below        if(targHex.containsTerrain(Terrains.WATER)                && target.getTargetType() == Targetable.TYPE_HEX_CLEAR) {            targetInPartialWater = true;        }        if (weaponUnderwater) {            weaponRanges = wtype.getWRanges();            // HACK on ranges: for those without underwater range,            // long == medium; iteration in rangeBracket() allows this            if (weaponRanges[RangeType.RANGE_SHORT] == 0) {                return new ToHitData(ToHitData.IMPOSSIBLE,                        "Weapon cannot fire underwater.");            }            if (!targetUnderwater && !targetInPartialWater) {                // target on land or over water                return new ToHitData(ToHitData.IMPOSSIBLE,                        "Weapon underwater, but not target.");            }            // special case: mechs can only fire upper body weapons at surface            // naval            if (te != null                    && UnitType.determineUnitTypeCode(te) == UnitType.NAVAL                    && ae instanceof Mech && ae.height() > 0                    && ae.getElevation() == -1) {                return new ToHitData(ToHitData.IMPOSSIBLE,                        "Partially submerged mech cannot fire leg weapons at surface naval vessels.");            }        } else if (targetUnderwater) {            return new ToHitData(ToHitData.IMPOSSIBLE,                    "Target underwater, but not weapon.");        } else if (wtype.getAmmoType() == AmmoType.T_LRM_TORPEDO                || wtype.getAmmoType() == AmmoType.T_SRM_TORPEDO) {            // Torpedos only fire underwater.            return new ToHitData(ToHitData.IMPOSSIBLE,                    "Weapon can only fire underwater.");        }        // determine base distance & range bracket        int distance = effectiveDistance(game, ae, target);        int range = RangeType.rangeBracket(distance, weaponRanges,                useExtremeRange);        // short circuit if at zero range or out of range        if (range == RangeType.RANGE_OUT) {            return new ToHitData(ToHitData.AUTOMATIC_FAIL,                    "Target out of range");        }        if (distance == 0 && !isAttackerInfantry                && !(ae instanceof Mech && ((Mech)ae).getGrappled() == target.getTargetId())) {            return new ToHitData(ToHitData.AUTOMATIC_FAIL,                    "Only infantry shoot at zero range");        }        // find any c3 spotters that could help        Entity c3spotter = findC3Spotter(game, ae, target);        if (isIndirect) {            c3spotter = ae; // no c3 when using indirect fire        }        if (isIndirect && game.getOptions().booleanOption("indirect_fire")                && !game.getOptions().booleanOption("indirect_always_possible")                && LosEffects.calculateLos(game, ae.getId(), target).canSee()) {            return new ToHitData(ToHitData.IMPOSSIBLE,                    "Indirect fire impossible with direct LOS");        }        int c3dist = effectiveDistance(game, c3spotter, target);        int c3range = RangeType.rangeBracket(c3dist, weaponRanges,                useExtremeRange);        // determine which range we're using        int usingRange = Math.min(range, c3range);        String targSysType = "";        // Get the targeting system type string ready, if necessary        if ((ae.getTargSysType() == MiscType.T_TARGSYS_LONGRANGE)                && (ae.getTargSysType() == MiscType.T_TARGSYS_SHORTRANGE)) {            targSysType = " (w/"                    + MiscType.getTargetSysName(ae.getTargSysType()) + ")";        }        // add range modifier        if (usingRange == range) {            // no c3 adjustment            if ((range == RangeType.RANGE_SHORT || range == RangeType.RANGE_MINIMUM)                    && (ae.getShortRangeModifier() != 0)) {                mods.addModifier(ae.getShortRangeModifier(), "short range"                        + targSysType);            } else if (range == RangeType.RANGE_MEDIUM) {                // Right now, the range-mod affecting targeting systems DON'T                // affect medium range, so we won't add that here ever.                mods.addModifier(ae.getMediumRangeModifier(), "medium range");            } else if (range == RangeType.RANGE_LONG) {                // Protos that loose head sensors can't shoot long range.                if ((ae instanceof Protomech)                        && (2 == ((Protomech) ae)                                .getCritsHit(Protomech.LOC_HEAD))) {                    mods                            .addModifier(ToHitData.IMPOSSIBLE,                                    "No long range attacks with destroyed head sensors.");                } else {                    mods.addModifier(ae.getLongRangeModifier(), "long range"                            + targSysType);                }            } else if (range == RangeType.RANGE_EXTREME) {                // Protos that loose head sensors can't shoot extreme range.                if ((ae instanceof Protomech)                        && (2 == ((Protomech) ae)                                .getCritsHit(Protomech.LOC_HEAD))) {                    mods                            .addModifier(ToHitData.IMPOSSIBLE,                                    "No extreme range attacks with destroyed head sensors.");                } else {                    mods.addModifier(ae.getExtremeRangeModifier(),                            "extreme range" + targSysType);                }            }        } else {            // report c3 adjustment            if (c3range == RangeType.RANGE_SHORT || range == RangeType.RANGE_MINIMUM) {                mods.addModifier(ae.getShortRangeModifier(),                        "short range due to C3 spotter" + targSysType);            } else if (c3range == RangeType.RANGE_MEDIUM) {                mods.addModifier(ae.getMediumRangeModifier(),                        "medium range due to C3 spotter" + targSysType);            } else if (c3range == RangeType.RANGE_LONG) {                mods.addModifier(ae.getLongRangeModifier(),                        "long range due to C3 spotter" + targSysType);            }        }        // add infantry LRM maximum range penalty        if (isLRMInfantry && distance == weaponRanges[RangeType.RANGE_LONG]) {            mods.addModifier(1, "infantry LRM maximum range");        }        // add infantry zero-range modifier        // TODO: this is not the right place to hardcode these        if (isWeaponInfantry && distance == 0) {            // Infantry platoons attacking with infantry weapons can attack            // in the same hex with a base of 2, except for flamers and            // SRMs, which have a base of 3 and LRMs, which suffer badly.            if (wtype.hasFlag(WeaponType.F_FLAMER)) {                mods.addModifier(-1, "infantry flamer assault");            } else if (wtype.getAmmoType() == AmmoType.T_SRM) {                mods.addModifier(-1, "infantry SRM assault");            } else if (wtype.getAmmoType() != AmmoType.T_LRM) {                mods.addModifier(-2, "infantry assault");            }        }        // add minimum range modifier        int minRange = weaponRanges[RangeType.RANGE_MINIMUM];        if (minRange > 0 && distance <= minRange) {            int minPenalty = (minRange - distance) + 1;            // Infantry LRMs suffer double minimum range penalties.            if (isLRMInfantry) {                mods.addModifier(minPenalty * 2, "infantry LRM minimum range");            } else {                mods.addModifier(minPenalty, "minimum range");            }        }        // add any target stealth modifier        if (target instanceof Entity) {            TargetRoll tmpTR = ((Entity)target).getStealthModifier(usingRange);            if (tmpTR.getValue() != 0)                mods.append(((Entity)target).getStealthModifier(usingRange));        }        return mods;    }    /**     * Finds the effective distance between an attacker and a target. Includes     * the distance bonus if the attacker and target are in the same building     * and on different levels.     *      * @return the effective distance     */    public static int effectiveDistance(IGame game, Entity attacker,            Targetable target) {        int distance = attacker.getPosition().distance(target.getPosition());        // If the attack is completely inside a building, add the difference        // in elevations between the attacker and target to the range.        // TODO: should the player be explcitly notified?        if (isInSameBuilding(game, attacker, target)) {            int aElev = attacker.getElevation();            int tElev = target.getElevation();            distance += Math.abs(aElev - tElev);        }        return distance;    }    /**     * Attempts to find a C3 spotter that is closer to the target than the     * attacker.     *      * @return A closer C3 spotter, or the attack if no spotters are found     */    private static Entity findC3Spotter(IGame game, Entity attacker,            Targetable target) {        if (!attacker.hasC3() && !attacker.hasC3i()) {            return attacker;        }        Entity c3spotter = attacker;        int c3range = attacker.getPosition().distance(target.getPosition());        for (java.util.Enumeration i = game.getEntities(); i.hasMoreElements();) {            Entity friend = (Entity) i.nextElement();            // TODO : can units being transported be used for C3 spotting?            if (attacker.equals(friend) || !friend.isActive()                    || !attacker.onSameC3NetworkAs(friend)                    || !canSee(game, friend, target)) {                continue; // useless to us...            }            int buddyRange = effectiveDistance(game, friend, target);            if (buddyRange < c3range) {                c3range = buddyRange;                c3spotter = friend;            }        }        return c3spotter;    }    /**     * Gets the modifiers, if any, that the mech receives from being prone.     *      * @return any applicable modifiers due to being prone     */    public static ToHitData getProneMods(IGame game, Entity attacker,            int weaponId) {        if (!attacker.isProne()) {            return null; // no modifier        }        ToHitData mods = new ToHitData();        Mounted weapon = attacker.getEquipment(weaponId);        if (attacker.entityIsQuad()) {            int legsDead = ((Mech) attacker).countBadLegs();            if (legsDead == 0) {                // No legs destroyed: no penalty and can fire all weapons                return null; // no modifier            } else if (legsDead >= 3) {                return new ToHitData(ToHitData.IMPOSSIBLE,                        "Prone with three or more legs destroyed.");            }            // we have one or two dead legs...            // Need an intact front leg            if (attacker.isLocationBad(Mech.LOC_RARM)                    && attacker.isLocationBad(Mech.LOC_LARM)) {                return new ToHitData(ToHitData.IMPOSSIBLE,                        "Prone with both front legs destroyed.");            }            // front leg-mounted weapons have addidional trouble            if (weapon.getLocation() == Mech.LOC_RARM                    || weapon.getLocation() == Mech.LOC_LARM) {                int otherArm = weapon.getLocation() == Mech.LOC_RARM ? Mech.LOC_LARM                        : Mech.LOC_RARM;                // check previous attacks for weapons fire from the other arm                if (isFiringFromArmAlready(game, weaponId, attacker, otherArm)) {                    return new ToHitData(ToHitData.IMPOSSIBLE,                            "Prone and firing from other front leg already.");                }            }            // can't fire rear leg weapons            if (weapon.getLocation() == Mech.LOC_LLEG                    || weapon.getLocation() == Mech.LOC_RLEG) {                return new ToHitData(ToHitData.IMPOSSIBLE,                        "Can't fire rear leg-mounted weapons while prone with destroyed legs.");            }            mods.addModifier(2, "attacker prone");        } else {            int l3ProneFiringArm = Entity.LOC_NONE;            if (attacker.isLocationBad(Mech.LOC_RARM)                    || attacker.isLocationBad(Mech.LOC_LARM)) {                if (game.getOptions().booleanOption("maxtech_prone_fire")) {                    // Can fire with only one arm                    if (attacker.isLocationBad(Mech.LOC_RARM)                            && attacker.isLocationBad(Mech.LOC_LARM)) {                        return new ToHitData(ToHitData.IMPOSSIBLE,                                "Prone with both arms destroyed.");                    }                    l3ProneFiringArm = attacker.isLocationBad(Mech.LOC_RARM) ? Mech.LOC_LARM                            : Mech.LOC_RARM;                } else {                    // must have an arm intact                    return new ToHitData(ToHitData.IMPOSSIBLE,                            "Prone with one or both arms destroyed.");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -