Merge branch 'tokenAttach' into 'master'

TokenEffect: Add AttachTo effect for Estrid

See merge request core-developers/forge!839
This commit is contained in:
Michael Kamensky
2018-08-06 12:20:07 +00:00
5 changed files with 114 additions and 10 deletions

View File

@@ -27,6 +27,7 @@ import forge.game.event.GameEventCardAttachment.AttachMethod;
import forge.game.keyword.Keyword;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.trigger.TriggerType;
import forge.util.collect.FCollection;
@@ -338,6 +339,17 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
}
}
public boolean canBeEnchantedBy(final Card aura) {
SpellAbility sa = aura.getFirstAttachSpell();
TargetRestrictions tgt = null;
if (sa != null) {
tgt = sa.getTargetRestrictions();
}
return !(hasProtectionFrom(aura)
|| ((tgt != null) && !isValid(tgt.getValidTgts(), aura.getController(), aura, sa)));
}
public abstract boolean hasProtectionFrom(final Card source);
// Counters!

View File

@@ -27,14 +27,18 @@ import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import forge.card.CardType;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameObject;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardUtil;
import forge.game.combat.Combat;
import forge.game.event.GameEventCombatChanged;
import forge.game.event.GameEventTokenCreated;
@@ -42,6 +46,7 @@ import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerHandler;
import forge.game.zone.ZoneType;
import forge.item.PaperToken;
import forge.util.collect.FCollectionView;
import forge.util.MyRandom;
@@ -291,6 +296,11 @@ public class TokenEffect extends SpellAbilityEffect {
if (this.tokenTapped) {
tok.setTapped(true);
}
if (sa.hasParam("AttachedTo") && !attachTokenTo(tok, sa)) {
continue;
}
// Should this be catching the Card that's returned?
Card c = game.getAction().moveToPlay(tok, sa);
@@ -469,4 +479,79 @@ public class TokenEffect extends SpellAbilityEffect {
}
return combatChanged;
}
private boolean attachTokenTo(Card tok, SpellAbility sa) {
final Card host = sa.getHostCard();
final Game game = host.getGame();
GameObject aTo = Iterables.getFirst(
AbilityUtils.getDefinedObjects(host, sa.getParam("AttachedTo"), sa), null);
if (aTo instanceof GameEntity) {
GameEntity ge = (GameEntity)aTo;
// check what the token would be on the battlefield
Card lki = CardUtil.getLKICopy(tok);
lki.setLastKnownZone(tok.getController().getZone(ZoneType.Battlefield));
CardCollection preList = new CardCollection(lki);
game.getAction().checkStaticAbilities(false, Sets.newHashSet(lki), preList);
// TODO update when doing Attach Update
boolean canAttach = lki.isAura() || lki.isEquipment() || lki.isFortification();
if (lki.isAura()) {
if (!ge.canBeEnchantedBy(lki)) {
canAttach = false;
}
}
if (lki.isEquipment()) {
if (ge instanceof Card) {
Card gc = (Card) ge;
if (!gc.canBeEquippedBy(lki)) {
canAttach = false;
}
} else {
canAttach = false;
}
}
if (lki.isFortification()) {
if (ge instanceof Card) {
Card gc = (Card) ge;
if (!gc.isLand()) {
canAttach = false;
}
} else {
canAttach = false;
}
}
// reset static abilities
game.getAction().checkStaticAbilities(false);
if (!canAttach) {
// Token can't attach it
return false;
}
// TODO update when doing Attach Update
if (lki.isAura()) {
tok.enchantEntity(ge);
} else if (lki.isEquipment()) {
if (ge instanceof Card) {
Card gc = (Card) ge;
tok.equipCard(gc);
}
} else if (lki.isFortification()) {
if (ge instanceof Card) {
Card gc = (Card) ge;
tok.fortifyCard(gc);
}
}
return true;
} else {
// not a GameEntity, cant be attach
return false;
}
}
}

View File

@@ -5151,16 +5151,6 @@ public class Card extends GameEntity implements Comparable<Card> {
result.setFalse();
}
break;
case "CARDNAME can't be enchanted.":
if (source.isAura()) {
result.setFalse();
}
break;
case "CARDNAME can't be equipped.":
if (source.isEquipment()) {
result.setFalse();
}
break;
case "CARDNAME can't be the target of spells.":
if (sa.isSpell()) {
result.setFalse();

View File

@@ -0,0 +1,14 @@
Name:Estrid, the Masked
ManaCost:1 G W U
Types:Legendary Planeswalker Estrid
Loyalty:3
A:AB$ UntapAll | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ValidCards$ Permanent.enchanted+YouCtrl | SpellDescription$ Untap each enchanted permanent you control.
SVar:BuffedBy:Permanent.enchanted
A:AB$ Token | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenName$ Mask | TokenImage$ mask | TokenTypes$ Enchantment,Aura | TokenOwner$ You | TokenColors$ White | TokenKeywords$ Enchant permanent<>Totem armor | TokenAbilities$ DBFirstAttach | AttachedTo$ Targeted | ValidTgts$ Permanent.Other | TgtPrompt$ Select target permanent to attach Mask Token | SpellDescription$ Create a white Aura enchantment token named Mask attached to another target permanent. The token has enchant permanent and totem armor.
SVar:DBFirstAttach:SP$ Attach | Cost$ 0 | ValidTgts$ Permanent | AILogic$ Pump
A:AB$ Mill | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Ultimate$ True | NumCards$ 7 | Defined$ You | SubAbility$ DBChangeZone | SpellDescription$ Put the top seven cards of your library into your graveyard. Return all non-Aura enchantment cards from your graveyard to the battlefield, then do the same for Aura cards.
SVar:DBChangeZone:DB$ ChangeZoneAll | ChangeType$ Enchantment.nonAura+YouCtrl | Origin$ Graveyard | Destination$ Battlefield | SubAbility$ DBChangeZone2
SVar:DBChangeZone2:DB$ ChangeZoneAll | ChangeType$ Enchantment.Aura+YouCtrl | Origin$ Graveyard | Destination$ Battlefield
K:CARDNAME can be your commander.
Oracle:[+2]: Untap each enchanted permanent you control.\n[-1]: Create a white Aura enchantment token named Mask attached to another target permanent. The token has enchant permanent and totem armor.\n[-7]: Put the top seven cards of your library into your graveyard. Return all non-Aura enchantment cards from your graveyard to the battlefield, then do the same for Aura cards.\nEstrid, the Masked can be your commander.

View File

@@ -272,6 +272,7 @@ Treasure
Vehicle
[WalkerTypes]
Ajani
Aminatou
Angrath
Arlinn
Ashiok
@@ -281,6 +282,7 @@ Dack
Daretti
Domri
Dovin
Estrid
Elspeth
Freyalise
Garruk
@@ -311,6 +313,7 @@ Ugin
Venser
Vraska
Will
Windgrace
Xenagos
Yanggu
Yanling