mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
Merge branch 'tokenAttach' into 'master'
TokenEffect: Add AttachTo effect for Estrid See merge request core-developers/forge!839
This commit is contained in:
@@ -27,6 +27,7 @@ import forge.game.event.GameEventCardAttachment.AttachMethod;
|
|||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.util.collect.FCollection;
|
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);
|
public abstract boolean hasProtectionFrom(final Card source);
|
||||||
|
|
||||||
// Counters!
|
// Counters!
|
||||||
|
|||||||
@@ -27,14 +27,18 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardCollection;
|
||||||
|
import forge.game.card.CardUtil;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.event.GameEventCombatChanged;
|
import forge.game.event.GameEventCombatChanged;
|
||||||
import forge.game.event.GameEventTokenCreated;
|
import forge.game.event.GameEventTokenCreated;
|
||||||
@@ -42,6 +46,7 @@ import forge.game.player.Player;
|
|||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
import forge.game.trigger.TriggerHandler;
|
import forge.game.trigger.TriggerHandler;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.PaperToken;
|
import forge.item.PaperToken;
|
||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
@@ -291,6 +296,11 @@ public class TokenEffect extends SpellAbilityEffect {
|
|||||||
if (this.tokenTapped) {
|
if (this.tokenTapped) {
|
||||||
tok.setTapped(true);
|
tok.setTapped(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sa.hasParam("AttachedTo") && !attachTokenTo(tok, sa)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Should this be catching the Card that's returned?
|
// Should this be catching the Card that's returned?
|
||||||
Card c = game.getAction().moveToPlay(tok, sa);
|
Card c = game.getAction().moveToPlay(tok, sa);
|
||||||
|
|
||||||
@@ -469,4 +479,79 @@ public class TokenEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
return combatChanged;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5151,16 +5151,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
result.setFalse();
|
result.setFalse();
|
||||||
}
|
}
|
||||||
break;
|
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.":
|
case "CARDNAME can't be the target of spells.":
|
||||||
if (sa.isSpell()) {
|
if (sa.isSpell()) {
|
||||||
result.setFalse();
|
result.setFalse();
|
||||||
|
|||||||
14
forge-gui/res/cardsfolder/upcoming/estrid_the_masked.txt
Normal file
14
forge-gui/res/cardsfolder/upcoming/estrid_the_masked.txt
Normal 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.
|
||||||
|
|
||||||
@@ -272,6 +272,7 @@ Treasure
|
|||||||
Vehicle
|
Vehicle
|
||||||
[WalkerTypes]
|
[WalkerTypes]
|
||||||
Ajani
|
Ajani
|
||||||
|
Aminatou
|
||||||
Angrath
|
Angrath
|
||||||
Arlinn
|
Arlinn
|
||||||
Ashiok
|
Ashiok
|
||||||
@@ -281,6 +282,7 @@ Dack
|
|||||||
Daretti
|
Daretti
|
||||||
Domri
|
Domri
|
||||||
Dovin
|
Dovin
|
||||||
|
Estrid
|
||||||
Elspeth
|
Elspeth
|
||||||
Freyalise
|
Freyalise
|
||||||
Garruk
|
Garruk
|
||||||
@@ -311,6 +313,7 @@ Ugin
|
|||||||
Venser
|
Venser
|
||||||
Vraska
|
Vraska
|
||||||
Will
|
Will
|
||||||
|
Windgrace
|
||||||
Xenagos
|
Xenagos
|
||||||
Yanggu
|
Yanggu
|
||||||
Yanling
|
Yanling
|
||||||
|
|||||||
Reference in New Issue
Block a user