diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index a4a3e6d3436..16eed5c2fc0 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -2000,11 +2000,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { if (keyword.startsWith("CantBeCounteredBy")) { final String[] p = keyword.split(":"); sbLong.append(p[2]).append("\r\n"); - } else if (keyword.startsWith("IfReach")) { - String[] k = keyword.split(":"); - sbLong.append(getName()).append(" can block ") - .append(CardType.getPluralType(k[1])) - .append(" as though it had reach.\r\n"); } else { sbLong.append(keyword).append("\r\n"); } @@ -2313,11 +2308,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { sb.append(Localizer.getInstance().getMessage("lblReadAhead")).append(" (").append(Localizer.getInstance().getMessage("lblReadAheadDesc")); sb.append(" ").append(Localizer.getInstance().getMessage("lblSagaFooter")).append(" ").append(TextUtil.toRoman(getFinalChapterNr())).append("."); sb.append(")").append("\r\n\r\n"); - } else if (keyword.startsWith("IfReach")) { - String[] k = keyword.split(":"); - sbLong.append(getName()).append(" can block ") - .append(CardType.getPluralType(k[1])) - .append(" as though it had reach.\r\n"); } else if (keyword.startsWith("MayEffectFromOpening")) { final String[] k = keyword.split(":"); // need to get SpellDescription from Svar diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index 9fde3bf9fe3..cb2f2d5b066 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -63,7 +63,7 @@ public final class CardUtil { "Cycling", "Echo", "Kicker", "Flashback", "Madness", "Morph", "Affinity", "Entwine", "Splice", "Ninjutsu", "Presence", "Transmute", "Replicate", "Recover", "Squad", "Suspend", "Aura swap", - "Fortify", "Transfigure", "Champion", "Evoke", "Prowl", "IfReach", + "Fortify", "Transfigure", "Champion", "Evoke", "Prowl", "Reinforce", "Unearth", "Level up", "Miracle", "Overload", "Cleave", "Scavenge", "Encore", "Bestow", "Outlast", "Dash", "Surge", "Emerge", "Hexproof:", "etbCounter", "Reflect", "Ward").build(); diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCanAttackDefender.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCanAttackDefender.java index a1100fc5602..6c9ee7cc6e1 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCanAttackDefender.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCanAttackDefender.java @@ -17,7 +17,6 @@ */ package forge.game.staticability; -import forge.game.Game; import forge.game.GameEntity; import forge.game.card.Card; import forge.game.zone.ZoneType; @@ -47,8 +46,6 @@ public class StaticAbilityCanAttackDefender { } public static boolean applyCanAttackAbility(final StaticAbility stAb, final Card card, final GameEntity target) { - final Card hostCard = stAb.getHostCard(); - final Game game = hostCard.getGame(); if (!stAb.matchesValidParam("ValidCard", card)) { return false; diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantAttackBlock.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantAttackBlock.java index 3fc1204041f..930457af01b 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantAttackBlock.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantAttackBlock.java @@ -30,7 +30,6 @@ import forge.game.card.CardCollectionView; import forge.game.card.CardPredicates; import forge.game.cost.Cost; import forge.game.keyword.Keyword; -import forge.game.keyword.KeywordInterface; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -40,7 +39,8 @@ import forge.game.zone.ZoneType; public class StaticAbilityCantAttackBlock { public static String CantAttackMode = "CantAttack"; public static String CantBlockByMode = "CantBlockBy"; - public static String CanAttackHasteMode = "CanAttackIfHaste"; + public static String CanAttackIfHasteMode = "CanAttackIfHaste"; + public static String CanBlockIfReachMode = "CanBlockIfReach"; public static String MinMaxBlockerMode = "MinMaxBlocker"; public static boolean cantAttack(final Card attacker, final GameEntity defender) { @@ -67,10 +67,8 @@ public class StaticAbilityCantAttackBlock { /** * TODO Write javadoc for this method. * - * @param stAb - * a StaticAbility - * @param card - * the card + * @param stAb a StaticAbility + * @param card the card * @return a Cost */ public static boolean applyCantAttackAbility(final StaticAbility stAb, final Card card, final GameEntity target) { @@ -86,7 +84,7 @@ public class StaticAbilityCantAttackBlock { } if (stAb.hasParam("DefenderKeyword")) { - //check for "can attack as if didn't have defender" static + // check for "can attack as if didn't have defender" static if (StaticAbilityCanAttackDefender.canAttack(card, target)) { return false; } @@ -97,19 +95,20 @@ public class StaticAbilityCantAttackBlock { if (stAb.hasParam("UnlessDefenderControls")) { String type = stAb.getParam("UnlessDefenderControls"); CardCollectionView list = defender.getCardsIn(ZoneType.Battlefield); - if (Iterables.any(list, CardPredicates.restriction(type.split(","), hostCard.getController(), hostCard, stAb))) { + if (Iterables.any(list, + CardPredicates.restriction(type.split(","), hostCard.getController(), hostCard, stAb))) { return false; } } if (stAb.hasParam("IfDefenderControls")) { String type = stAb.getParam("IfDefenderControls"); CardCollectionView list = defender.getCardsIn(ZoneType.Battlefield); - if (!Iterables.any(list, CardPredicates.restriction(type.split(","), hostCard.getController(), hostCard, stAb))) { + if (!Iterables.any(list, + CardPredicates.restriction(type.split(","), hostCard.getController(), hostCard, stAb))) { return false; } } - if (stAb.hasParam("DefenderNotNearestToYouInChosenDirection") - && (hostCard.getChosenDirection() == null + if (stAb.hasParam("DefenderNotNearestToYouInChosenDirection") && (hostCard.getChosenDirection() == null || defender.equals(game.getNextPlayerAfter(card.getController(), hostCard.getChosenDirection())))) { return false; } @@ -123,8 +122,7 @@ public class StaticAbilityCantAttackBlock { return true; } - public static boolean cantBlockBy(final Card attacker, final Card blocker) - { + public static boolean cantBlockBy(final Card attacker, final Card blocker) { for (final Card ca : attacker.getGame().getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { for (final StaticAbility stAb : ca.getStaticAbilities()) { if (!stAb.checkConditions(CantBlockByMode)) { @@ -140,6 +138,7 @@ public class StaticAbilityCantAttackBlock { /** * returns true if attacker can't be blocked by blocker + * * @param stAb * @param attacker * @param blocker @@ -155,18 +154,9 @@ public class StaticAbilityCantAttackBlock { for (final String v : stAb.getParam("ValidBlocker").split(",")) { if (blocker != null && blocker.isValid(v, host.getController(), host, stAb)) { stillblock = false; - //Dragon Hunter check - if (v.contains("withoutReach") && blocker.hasStartOfKeyword("IfReach")) { - for (KeywordInterface inst : blocker.getKeywords()) { - String k = inst.getOriginal(); - if (k.startsWith("IfReach")) { - String[] n = k.split(":"); - if (attacker.getType().hasCreatureType(n[1])) { - stillblock = true; - break; - } - } - } + // Dragon Hunter check + if (v.contains("withoutReach") && canBlockIfReach(attacker, blocker)) { + stillblock = true; } if (!stillblock) { break; @@ -192,13 +182,36 @@ public class StaticAbilityCantAttackBlock { return true; } + public static boolean canBlockIfReach(final Card attacker, final Card blocker) { + for (final Card ca : attacker.getGame().getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { + for (final StaticAbility stAb : ca.getStaticAbilities()) { + if (!stAb.checkConditions(CanBlockIfReachMode)) { + continue; + } + if (applyCanBlockIfReachAbility(stAb, attacker, blocker)) { + return true; + } + } + } + return false; + } + + public static boolean applyCanBlockIfReachAbility(final StaticAbility stAb, final Card attacker, + final Card blocker) { + if (!stAb.matchesValidParam("ValidAttacker", attacker)) { + return false; + } + if (!stAb.matchesValidParam("ValidBlocker", blocker)) { + return false; + } + return true; + } + /** * TODO Write javadoc for this method. * - * @param stAb - * a StaticAbility - * @param attacker - * the card + * @param stAb a StaticAbility + * @param attacker the card * @return a Cost */ public static Cost getAttackCost(final StaticAbility stAb, final Card attacker, final GameEntity target) { @@ -235,10 +248,8 @@ public class StaticAbilityCantAttackBlock { /** * TODO Write javadoc for this method. * - * @param stAb - * a StaticAbility - * @param blocker - * the card + * @param stAb a StaticAbility + * @param blocker the card * @return a Cost */ public static Cost getBlockCost(final StaticAbility stAb, final Card blocker, final GameEntity attacker) { @@ -266,7 +277,7 @@ public class StaticAbilityCantAttackBlock { } for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { for (final StaticAbility stAb : ca.getStaticAbilities()) { - if (!stAb.checkConditions(CanAttackHasteMode)) { + if (!stAb.checkConditions(CanAttackIfHasteMode)) { continue; } if (applyCanAttackHasteAbility(stAb, attacker, defender)) { @@ -277,7 +288,8 @@ public class StaticAbilityCantAttackBlock { return false; } - public static boolean applyCanAttackHasteAbility(final StaticAbility stAb, final Card card, final GameEntity target) { + public static boolean applyCanAttackHasteAbility(final StaticAbility stAb, final Card card, + final GameEntity target) { if (!stAb.matchesValidParam("ValidCard", card)) { return false; } @@ -313,7 +325,8 @@ public class StaticAbilityCantAttackBlock { return result; } - public static void applyMinMaxBlockerAbility(final StaticAbility stAb, final Card attacker, final Player defender, MutablePair result) { + public static void applyMinMaxBlockerAbility(final StaticAbility stAb, final Card attacker, final Player defender, + MutablePair result) { if (!stAb.matchesValidParam("ValidCard", attacker)) { return; } diff --git a/forge-gui/res/cardsfolder/d/dragon_hunter.txt b/forge-gui/res/cardsfolder/d/dragon_hunter.txt index 9311abcc069..da56997c999 100644 --- a/forge-gui/res/cardsfolder/d/dragon_hunter.txt +++ b/forge-gui/res/cardsfolder/d/dragon_hunter.txt @@ -3,5 +3,5 @@ ManaCost:W Types:Creature Human Warrior PT:2/1 K:Protection from Dragons -K:IfReach:Dragon +S:Mode$ CanBlockIfReach | ValidAttacker$ Dragon | ValidBlocker$ Card.Self | Description$ CARDNAME can block Dragons as though it had reach. Oracle:Protection from Dragons\nDragon Hunter can block Dragons as though it had reach.