ST: CantAttach begins to replace other cases

This commit is contained in:
Hanmac
2018-11-20 23:36:41 +01:00
parent 52438170ac
commit df83e7c783
13 changed files with 123 additions and 101 deletions

View File

@@ -975,7 +975,7 @@ public class ComputerUtil {
playNow = false;
break;
}
if (!playNow && c.isCreature() && ComputerUtilCombat.canAttackNextTurn(c) && c.canBeEquippedBy(card)) {
if (!playNow && c.isCreature() && ComputerUtilCombat.canAttackNextTurn(c) && c.canBeAttachedBy(card)) {
playNow = true;
}
}

View File

@@ -1275,6 +1275,12 @@ public class AttachAi extends SpellAbilityAi {
if (attachSource.hasSVar("DontEquip")) {
return null;
}
// is no attachment so no using attach
if (!attachSource.isAttachment()) {
return null;
}
// Don't fortify if already fortifying
if (attachSource.getAttachingCard() != null && attachSource.getAttachingCard().getController() == aiPlayer) {
return null;
@@ -1286,11 +1292,7 @@ public class AttachAi extends SpellAbilityAi {
} else {
list = CardLists.getValidCards(aiPlayer.getGame().getCardsIn(tgt.getZone()), tgt.getValidTgts(), sa.getActivatingPlayer(), attachSource, sa);
if (attachSource.isAura()) {
list = CardLists.filter(list, CardPredicates.canBeEnchantedBy(attachSource));
} else if (attachSource.isEquipment()) {
list = CardLists.filter(list, CardPredicates.canBeEquippedBy(attachSource));
}
list = CardLists.filter(list, CardPredicates.canBeAttachedBy(attachSource));
// TODO If Attaching without casting, don't need to actually target.
// I believe this is the only case where mandatory will be true, so just

View File

@@ -39,7 +39,7 @@ public class ZoneExchangeAi extends SpellAbilityAi {
}
if (type.equals("Aura")) {
Card c = object1.getEnchantingCard();
if (!c.canBeEnchantedBy(object2)) {
if (!c.canBeAttachedBy(object2)) {
return false;
}
}

View File

@@ -29,7 +29,9 @@ import forge.game.keyword.Keyword;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.staticability.StaticAbility;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.collect.FCollection;
import java.util.Map;
@@ -372,11 +374,20 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
public boolean canBeAttachedBy(final Card attach, boolean checkSBA) {
// master mode
if (!attach.isAttachment()) {
if (!attach.isAttachment() || attach.isCreature()) {
return false;
}
if (attach.isAura() && !canBeEnchantedBy(attach, checkSBA)) {
// CantTarget static abilities
for (final Card ca : getGame().getCardsIn(ZoneType.listValueOf("Battlefield,Command"))) {
for (final StaticAbility stAb : ca.getStaticAbilities()) {
if (stAb.applyAbility("CantAttach", attach, this)) {
return false;
}
}
}
if (attach.isAura() && !canBeEnchantedBy(attach)) {
return false;
}
if (attach.isEquipment() && !canBeEquippedBy(attach)) {
@@ -385,21 +396,24 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
if (attach.isFortification() && !canBeFortifiedBy(attach)) {
return false;
}
// true for all
if (hasProtectionFrom(attach, checkSBA)) {
return false;
}
return true;
}
public boolean canBeEquippedBy(final Card aura) {
protected boolean canBeEquippedBy(final Card aura) {
return false;
}
public boolean canBeFortifiedBy(final Card aura) {
protected boolean canBeFortifiedBy(final Card aura) {
return false;
}
public boolean canBeEnchantedBy(final Card aura, final boolean checkSBA) {
if (!aura.isAura()) {
return false;
}
protected boolean canBeEnchantedBy(final Card aura) {
SpellAbility sa = aura.getFirstAttachSpell();
TargetRestrictions tgt = null;
@@ -407,8 +421,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
tgt = sa.getTargetRestrictions();
}
return !(hasProtectionFrom(aura, checkSBA)
|| ((tgt != null) && !isValid(tgt.getValidTgts(), aura.getController(), aura, sa)));
return !((tgt != null) && !isValid(tgt.getValidTgts(), aura.getController(), aura, sa));
}
public boolean hasProtectionFrom(final Card source) {

View File

@@ -101,7 +101,7 @@ public class AttachEffect extends SpellAbilityEffect {
// Although honestly, I'm not sure if the three of those could
// handle being scripted
// 303.4h: If the card can't be enchanted, the aura doesn't move
if (c.canBeEnchantedBy(card)) {
if (c.canBeAttachedBy(card)) {
handleAura(card, c);
}
} else {

View File

@@ -77,7 +77,7 @@ public class ZoneExchangeEffect extends SpellAbilityEffect {
Card c = null;
if (type != null && type.equals("Aura") && object1.getEnchantingCard() != null) {
c = object1.getEnchantingCard();
if (!c.canBeEnchantedBy(object2)) {
if (!c.canBeAttachedBy(object2)) {
return;
}
}

View File

@@ -5162,26 +5162,14 @@ public class Card extends GameEntity implements Comparable<Card> {
return !(hasKeyword("Other players can't gain control of CARDNAME.") && !getController().equals(newController));
}
public final boolean canBeEnchantedBy(final Card aura) {
return canBeEnchantedBy(aura, false);
}
public final boolean canBeEnchantedBy(final Card aura, final boolean checkSBA) {
@Override
protected final boolean canBeEnchantedBy(final Card aura) {
SpellAbility sa = aura.getFirstAttachSpell();
TargetRestrictions tgt = null;
if (sa != null) {
tgt = sa.getTargetRestrictions();
}
if (aura.isCreature()) {
return false;
}
// phase check there
if (isPhasedOut() && !aura.isPhasedOut()) {
return false;
}
if (tgt != null) {
boolean zoneValid = false;
// check the zone types
@@ -5201,19 +5189,14 @@ public class Card extends GameEntity implements Comparable<Card> {
}
}
return !(hasProtectionFrom(aura, checkSBA)
|| (hasKeyword("CARDNAME can't be enchanted in the future.") && !isEnchantedBy(aura))
return !((hasKeyword("CARDNAME can't be enchanted in the future.") && !isEnchantedBy(aura))
|| (hasKeyword("CARDNAME can't be enchanted.") && !aura.getName().equals("Anti-Magic Aura")
&& !(aura.getName().equals("Consecrate Land") && aura.isInZone(ZoneType.Battlefield))));
}
public final boolean canBeEquippedBy(final Card equip) {
if (!isCreature() || !isInPlay() || equip.isCreature()) {
return false;
}
// phase check there
if (isPhasedOut() && !equip.isPhasedOut()) {
@Override
protected final boolean canBeEquippedBy(final Card equip) {
if (!isCreature() || !isInPlay()) {
return false;
}
@@ -5228,20 +5211,29 @@ public class Card extends GameEntity implements Comparable<Card> {
return false;
}
}
return !(hasProtectionFrom(equip)
|| hasKeyword("CARDNAME can't be equipped."));
return true;
}
public boolean canBeFortifiedBy(final Card fort) {
if (!isLand() || !isInPlay() || fort.isCreature() || fort.isLand()) {
@Override
protected boolean canBeFortifiedBy(final Card fort) {
if (!isLand() || !isInPlay() || fort.isLand()) {
return false;
}
return true;
}
/* (non-Javadoc)
* @see forge.game.GameEntity#canBeAttachedBy(forge.game.card.Card, boolean)
*/
@Override
public boolean canBeAttachedBy(Card attach, boolean checkSBA) {
// phase check there
if (isPhasedOut() && !fort.isPhasedOut()) {
if (isPhasedOut() && !attach.isPhasedOut()) {
return false;
}
return !hasProtectionFrom(fort);
return super.canBeAttachedBy(attach, checkSBA);
}
public FCollectionView<ReplacementEffect> getReplacementEffects() {

View File

@@ -216,20 +216,11 @@ public final class CardPredicates {
};
};
public static final Predicate<Card> canBeEnchantedBy(final Card aura) {
public static final Predicate<Card> canBeAttachedBy(final Card aura) {
return new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.canBeEnchantedBy(aura);
}
};
};
public static final Predicate<Card> canBeEquippedBy(final Card eq) {
return new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.canBeEquippedBy(eq);
return c.canBeAttachedBy(aura);
}
};
};

View File

@@ -508,11 +508,11 @@ public class CardProperty {
final String restriction = property.substring(10);
if (restriction.equals("Remembered")) {
for (final Object rem : source.getRemembered()) {
if (!(rem instanceof Card) || !((Card) rem).canBeEnchantedBy(card))
if (!(rem instanceof Card) || !((Card) rem).canBeAttachedBy(card))
return false;
}
} else if (restriction.equals("Source")) {
if (!source.canBeEnchantedBy(card)) return false;
if (!source.canBeAttachedBy(card)) return false;
}
} else if (property.startsWith("CanBeEnchantedBy")) {
if (property.substring(16).equals("Targeted")) {
@@ -520,7 +520,7 @@ public class CardProperty {
final SpellAbility saTargeting = sa.getSATargetingCard();
if (saTargeting != null) {
for (final Card c : saTargeting.getTargets().getTargetCards()) {
if (!card.canBeEnchantedBy(c)) {
if (!card.canBeAttachedBy(c)) {
return false;
}
}
@@ -530,13 +530,13 @@ public class CardProperty {
for (final Object rem : source.getRemembered()) {
if (rem instanceof Card) {
final Card c = (Card) rem;
if (!card.canBeEnchantedBy(c)) {
if (!card.canBeAttachedBy(c)) {
return false;
}
}
}
} else {
if (!card.canBeEnchantedBy(source)) {
if (!card.canBeAttachedBy(source)) {
return false;
}
}
@@ -566,8 +566,8 @@ public class CardProperty {
if (!card.isFortifiedBy(source)) {
return false;
}
} else if (property.startsWith("CanBeEquippedBy")) {
if (!card.canBeEquippedBy(source)) {
} else if (property.startsWith("CanBeAttachedBy")) {
if (!card.canBeAttachedBy(source)) {
return false;
}
} else if (property.startsWith("Equipped")) {

View File

@@ -462,6 +462,8 @@ public class StaticAbility extends CardTraitBase implements Comparable<StaticAbi
return StaticAbilityCantAttackBlock.applyCantAttackAbility(this, card, target);
} else if (mode.equals("CantBlockBy") && target instanceof Card) {
return StaticAbilityCantAttackBlock.applyCantBlockByAbility(this, card, (Card)target);
} else if (mode.equals("CantAttach")) {
return StaticAbilityCantAttach.applyCantAttachAbility(this, card, target);
}
return false;

View File

@@ -0,0 +1,22 @@
package forge.game.staticability;
import forge.game.GameEntity;
import forge.game.card.Card;
public class StaticAbilityCantAttach {
public static boolean applyCantAttachAbility(final StaticAbility stAb, final Card card, final GameEntity target) {
final Card hostCard = stAb.getHostCard();
if (stAb.hasParam("ValidCard")
&& !card.isValid(stAb.getParam("ValidCard").split(","), hostCard.getController(), hostCard, null)) {
return false;
}
if (stAb.hasParam("Target")
&& !target.isValid(stAb.getParam("Target").split(","), hostCard.getController(), hostCard, null)) {
return false;
}
return true;
}
}

View File

@@ -3,6 +3,6 @@ ManaCost:2 R
Types:Creature Goblin Warrior
PT:2/2
K:First Strike
K:CARDNAME can't be equipped.
S:Mode$ CantAttach | ValidCard$ Card.Equipment | Target$ Card.Self | Description$ CARDNAME can't be equipped.
SVar:Picture:http://www.wizards.com/global/images/magic/general/goblin_brawler.jpg
Oracle:First strike\nGoblin Brawler can't be equipped.

View File

@@ -4,7 +4,7 @@ Types:Artifact Equipment
K:Equip:1
K:Flash
K:ETBReplacement:Other:ChooseC
SVar:ChooseC:DB$ ChooseCard | Defined$ You | Choices$ Creature.YouCtrl+CanBeEquippedBy | Amount$ 1 | Mandatory$ True | SubAbility$ DBAttach | SpellDescription$ As CARDNAME enters the battlefield, choose a creature you control it could be attached to. If you do, it enters the battlefield attached to that creature.
SVar:ChooseC:DB$ ChooseCard | Defined$ You | Choices$ Creature.YouCtrl+CanBeAttachedBy | Amount$ 1 | Mandatory$ True | SubAbility$ DBAttach | SpellDescription$ As CARDNAME enters the battlefield, choose a creature you control it could be attached to. If you do, it enters the battlefield attached to that creature.
SVar:DBAttach:DB$ Attach | Object$ Self | Defined$ ChosenCard
S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 1 | AddToughness$ 1 | Description$ Equipped creature gets +1/+1.
SVar:Picture:http://www.wizards.com/global/images/magic/general/grifters_blade.jpg