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

📄 loseffects.java

📁 MegaMek is a networked Java clone of BattleTech, a turn-based sci-fi boardgame for 2+ players. Fight
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
        if (lightSmoke + (heavySmoke * 2) + lightWoods + (heavyWoods * 2) > 2) {            return new ToHitData(ToHitData.IMPOSSIBLE, "LOS blocked by smoke and woods.");        }                if (lightWoods > 0) {            if(eistatus > 0) {                modifiers.addModifier(1, "firing through light woods with EI system");            } else {                modifiers.addModifier(lightWoods, lightWoods + " intervening light woods");            }        }                if (heavyWoods > 0) {            if(eistatus > 0) {                modifiers.addModifier(heavyWoods, heavyWoods + " intervening heavy woods");            } else {                modifiers.addModifier(heavyWoods * 2, heavyWoods + " intervening heavy woods");            }        }             if (lightSmoke > 0) {            modifiers.addModifier(lightSmoke, lightSmoke + " intervening light smoke");        }                if (heavySmoke > 0) {            StringBuffer text = new StringBuffer(heavySmoke);            text.append(" intervening");            if (game.getOptions().booleanOption("maxtech_fire"))                text.append(" heavy");            text.append(" smoke");            if(eistatus > 0) {                modifiers.addModifier(heavySmoke, text.toString());            } else {                modifiers.addModifier(heavySmoke * 2, text.toString());            }        }        if (targetCover != COVER_NONE) {            if (game.getOptions().booleanOption("maxtech_partial_cover")) {                if (targetCover == COVER_75LEFT || targetCover == COVER_75RIGHT)                    modifiers.addModifier(1, "target has 75% cover");                else if(targetCover >= COVER_HORIZONTAL)                     modifiers.addModifier(1, "target has 50% cover");                else                    //no bth mod for 25% cover                    modifiers.addModifier(0, "target has 25% cover");            } else {                modifiers.addModifier(3, "target has partial cover");            }        }                return modifiers;    }    /**     * Returns LosEffects for a line that never passes exactly between two      * hexes.  Since intervening() returns all the coordinates, we just     * add the effects of all those hexes.     */    private static LosEffects losStraight(IGame game, AttackInfo ai) {        ArrayList<Coords> in = Coords.intervening(ai.attackPos, ai.targetPos);        LosEffects los = new LosEffects();        boolean targetInBuilding = false;        if (ai.targetEntity) {            targetInBuilding = Compute.isInBuilding(game, ai.targetAbsHeight - game.getBoard().getHex(ai.targetPos).surface(), ai.targetPos);        }            // If the target and attacker are both in a        // building, set that as the first LOS effect.        if ( targetInBuilding && Compute.isInBuilding( game, ai.attackAbsHeight - game.getBoard().getHex(ai.attackPos).surface(), ai.attackPos ) ) {            los.setThruBldg( game.getBoard().getBuildingAt( in.get(0) ) );        }            for (Coords c : in) {            los.add( LosEffects.losForCoords(game, ai, c, los.getThruBldg()) );        }        if ((ai.minimumWaterDepth < 1) && ai.underWaterCombat) {            los.blocked = true;        }        // Infantry inside a building can only be        // targeted by units in the same building.        if ( ai.targetInfantry && targetInBuilding &&             null == los.getThruBldg() ) {            los.infProtected = true;        }            // If a target Entity is at a different elevation as its        // attacker, and if the attack is through a building, the        // target has cover.        if ( null != los.getThruBldg() &&             ai.attackAbsHeight != ai.targetAbsHeight ) {            los.setTargetCover( COVER_HORIZONTAL );        }            return los;    }    /**     * Returns LosEffects for a line that passes between two hexes at least     * once.  The rules say that this situation is resolved in favor of the     * defender.     *     * The intervening() function returns both hexes in these circumstances,     * and, when they are in line order, it's not hard to figure out which hexes      * are split and which are not.     *     * The line always looks like:     *       ___     ___     *   ___/ 1 \___/...\___     *  / 0 \___/ 3 \___/etc\     *  \___/ 2 \___/...\___/     *      \___/   \___/     *     * We go thru and figure out the modifiers for the non-split hexes first.     * Then we go to each of the two split hexes and determine which gives us     * the bigger modifier.  We use the bigger modifier.     *     * This is not perfect as it takes partial cover as soon as it can, when     * perhaps later might be better.     * Also, it doesn't account for the fact that attacker partial cover blocks     * leg weapons, as we want to return the same sequence regardless of     * what weapon is attacking.     */    private static LosEffects losDivided(IGame game, AttackInfo ai) {        ArrayList<Coords> in = Coords.intervening(ai.attackPos, ai.targetPos, true);        LosEffects los = new LosEffects();        boolean targetInBuilding = false;        if (ai.targetEntity) {            targetInBuilding = Compute.isInBuilding(game, ai.targetAbsHeight - game.getBoard().getHex(ai.targetPos).surface(), ai.targetPos);        }            // If the target and attacker are both in a        // building, set that as the first LOS effect.        if ( targetInBuilding && Compute.isInBuilding( game, ai.attackAbsHeight - game.getBoard().getHex(ai.attackPos).surface(), ai.attackPos ) ) {            los.setThruBldg( game.getBoard().getBuildingAt( in.get(0)) );        }        // add non-divided line segments        for (int i = 3; i < in.size() - 2; i += 3) {            los.add( losForCoords(game, ai, in.get(i), los.getThruBldg()) );        }        if ((ai.minimumWaterDepth < 1) && ai.underWaterCombat) {            los.blocked = true;        }        // if blocked already, return that        if (los.losModifiers(game).getValue() == ToHitData.IMPOSSIBLE) {            return los;        }        // go through divided line segments        for (int i = 1; i < in.size() - 2; i += 3) {            // get effects of each side            LosEffects left = losForCoords( game, ai, in.get(i), los.getThruBldg());            LosEffects right = losForCoords( game, ai, in.get(i+1), los.getThruBldg());                // If a target Entity is at a different elevation as its            // attacker, and if the attack is through a building, the            // target has cover.            final boolean isElevDiff = ai.attackAbsHeight != ai.targetAbsHeight;            if ((ai.minimumWaterDepth < 1) && ai.underWaterCombat) {                los.blocked = true;            }            if ( targetInBuilding && isElevDiff ) {                 if ( null != left.getThruBldg() ) {                     left.setTargetCover(COVER_HORIZONTAL);                 }                 if ( null != right.getThruBldg() ) {                     right.setTargetCover(COVER_HORIZONTAL);                 }            }                // Include all previous LOS effects.            left.add(los);            right.add(los);                // Infantry inside a building can only be            // targeted by units in the same building.            if ( ai.targetInfantry && targetInBuilding ) {                if ( null == left.getThruBldg() ) {                    left.infProtected = true;                }                else if ( null == right.getThruBldg() ) {                    right.infProtected = true;                }            }                // which is better?            int lVal = left.losModifiers(game).getValue();            int rVal = right.losModifiers(game).getValue();            if (lVal > rVal || (lVal == rVal && left.isAttackerCover())) {                los = left;            } else {                los = right;            }            if (game.getOptions().booleanOption("maxtech_partial_cover")) {                int cover = (left.targetCover & (COVER_LEFT | COVER_LOWLEFT)) |                            (right.targetCover & (COVER_RIGHT | COVER_LOWRIGHT));                if (cover < COVER_FULL && !(left.blocked && right.blocked)) {                    los.blocked = false;                    los.targetCover = cover;                }                cover = (left.attackerCover & (COVER_LEFT | COVER_LOWLEFT)) |                        (right.attackerCover & (COVER_RIGHT | COVER_LOWRIGHT));                if (cover < COVER_FULL && !(left.blocked && right.blocked)) {                    los.blocked = false;                    los.attackerCover = cover;                }            }        }        return los;    }    /**     * Returns a LosEffects object representing the LOS effects of anything at     * the specified coordinate.       */    private static LosEffects losForCoords(IGame game, AttackInfo ai,                                           Coords coords, Building thruBldg) {        LosEffects los = new LosEffects();                // ignore hexes not on board        if (!game.getBoard().contains(coords)) {            return los;        }            // Is there a building in this hex?        Building bldg = game.getBoard().getBuildingAt(coords);            // We're only tracing thru a single building if there        // is a building in this hex, and if it isn't the same        // building that we'be been tracing LOS thru.        if ( bldg != null && bldg.equals(thruBldg) ) {            los.setThruBldg( thruBldg );        }            // ignore hexes the attacker or target are in        if ( coords.equals(ai.attackPos) ||             coords.equals(ai.targetPos) ) {            return los;        }            IHex hex = game.getBoard().getHex(coords);        int hexEl = ai.underWaterCombat ? hex.floor() : hex.surface();        // Handle minimum water depth.        // Applies to Torpedos.        if (!(hex.containsTerrain(Terrains.WATER)))            ai.minimumWaterDepth = 0;        else if ((hex.terrainLevel(Terrains.WATER) >= 0)                && ((ai.minimumWaterDepth == -1)                || (hex.terrainLevel(Terrains.WATER) < ai.minimumWaterDepth)))            ai.minimumWaterDepth = hex.terrainLevel(Terrains.WATER);            // Handle building elevation.        // Attacks thru a building are not blocked by that building.        // ASSUMPTION: bridges don't block LOS.        int bldgEl = 0;        if ( null == los.getThruBldg() &&             hex.containsTerrain( Terrains.BLDG_ELEV ) ) {            bldgEl = hex.terrainLevel( Terrains.BLDG_ELEV );        }            // TODO: Identify when LOS travels *above* a building's hex.        //       Alternatively, force all building hexes to be same height.            // check for block by terrain                //check for LOS according to diagramming rule from MaxTech, page 22        if (game.getOptions().booleanOption("maxtech_LOS1")) {            if (hexEl + bldgEl > (ai.targetAbsHeight * ai.attackPos.distance(coords) +                                  ai.attackAbsHeight * ai.targetPos.distance(coords)) /                                  (ai.targetPos.distance(coords) +                                   ai.attackPos.distance(coords))) {                los.blocked = true;                    }        }        if ((hexEl + bldgEl > ai.attackAbsHeight && hexEl + bldgEl > ai.targetAbsHeight)        || (hexEl + bldgEl > ai.attackAbsHeight && ai.attackPos.distance(coords) == 1)        || (hexEl + bldgEl > ai.targetAbsHeight && ai.targetPos.distance(coords) == 1)) {            los.blocked = true;        }                // check if there's a clear hex between the targets that's higher than        // one of them, if we're in underwater combat        if (ai.underWaterCombat && hex.terrainLevel(Terrains.WATER) == ITerrain.LEVEL_NONE &&            (hexEl + bldgEl > ai.attackAbsHeight || hexEl + bldgEl > ai.targetAbsHeight)) {            los.blocked = true;        }            // check for woods or smoke only if not under water        if (!ai.underWaterCombat) {            if ((hexEl + 2 > ai.attackAbsHeight && hexEl + 2 > ai.targetAbsHeight)            || (hexEl + 2 > ai.attackAbsHeight && ai.attackPos.distance(coords) == 1)            || (hexEl + 2 > ai.targetAbsHeight && ai.targetPos.distance(coords) == 1)) {                // smoke overrides any woods in the hex if L3 smoke rule is off                if (!game.getOptions().booleanOption("maxtech_fire")) {                  if (hex.containsTerrain(Terrains.SMOKE)) {                    los.heavySmoke++;                  }                  else if (hex.terrainLevel(Terrains.WOODS) == 1                          || hex.terrainLevel(Terrains.JUNGLE) == 1) {                    los.lightWoods++;                  }                  else if (hex.terrainLevel(Terrains.WOODS) == 2                          || hex.terrainLevel(Terrains.JUNGLE) == 2) {                    los.heavyWoods++;                  }                  else if (hex.terrainLevel(Terrains.WOODS) == 3                          || hex.terrainLevel(Terrains.JUNGLE) == 3) {                      los.ultraWoods++;                  }                }                // if the L3 fire/smoke rule is on, smoke and woods stack for LOS                // so check them both                else {                  if (hex.containsTerrain(Terrains.SMOKE)) {                    if (hex.terrainLevel(Terrains.SMOKE) == 1) {                      los.lightSmoke++;                    }                    else if (hex.terrainLevel(Terrains.SMOKE) > 1) {                      los.heavySmoke++;                    }                  }                  if (hex.terrainLevel(Terrains.WOODS) == 1                          || hex.terrainLevel(Terrains.JUNGLE) == 1) {                    los.lightWoods++;                  }                  else if (hex.terrainLevel(Terrains.WOODS) == 2                          || hex.terrainLevel(Terrains.JUNGLE) == 2) {                    los.heavyWoods++;                  }                  else if (hex.terrainLevel(Terrains.WOODS) == 3                          || hex.terrainLevel(Terrains.JUNGLE) == 3) {                    los.ultraWoods++;                  }                }            }        }                // check for target partial cover        if ( ai.targetPos.distance(coords) == 1) {            if (los.blocked && game.getOptions().booleanOption("maxtech_partial_cover")) {                los.targetCover = COVER_FULL;            }             else if(hexEl + bldgEl == ai.targetAbsHeight &&             ai.attackAbsHeight <= ai.targetAbsHeight && ai.targetHeight > 0) {                los.targetCover |= COVER_HORIZONTAL;            }        }            // check for attacker partial cover        if (ai.attackPos.distance(coords) == 1) {            if (los.blocked && game.getOptions().booleanOption("maxtech_partial_cover")) {                los.attackerCover = COVER_FULL;            }             else if(hexEl + bldgEl == ai.attackAbsHeight &&               ai.attackAbsHeight >= ai.targetAbsHeight && ai.attackHeight > 0) {                los.attackerCover |= COVER_HORIZONTAL;            }        }                return los;    }}

⌨️ 快捷键说明

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