Merge pull request #2548 from Card-Forge/IfReachStatic

Dragon Hunter as StaticAbility instead of fake Keyword
This commit is contained in:
Anthony Calosa
2023-02-24 14:43:52 +08:00
committed by GitHub
5 changed files with 51 additions and 51 deletions

View File

@@ -2000,11 +2000,6 @@ public class Card extends GameEntity implements Comparable<Card>, 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<Card>, 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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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<Integer, Integer> result) {
public static void applyMinMaxBlockerAbility(final StaticAbility stAb, final Card attacker, final Player defender,
MutablePair<Integer, Integer> result) {
if (!stAb.matchesValidParam("ValidCard", attacker)) {
return;
}

View File

@@ -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.