mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Bunch of fixes (#2706)
* Fix Tawnos's Coffin not using ETB counters * Cost fix * Saga tweaks --------- Co-authored-by: tool4EvEr <tool4EvEr@192.168.0.59>
This commit is contained in:
@@ -355,6 +355,31 @@ public class AiController {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (final Trigger tr : card.getTriggers()) {
|
||||||
|
if (!card.hasStartOfKeyword("Saga") && !card.hasStartOfKeyword("Read ahead")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tr.getMode() != TriggerType.CounterAdded) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpellAbility exSA = tr.ensureAbility().copy(activator);
|
||||||
|
|
||||||
|
if (api != null && exSA.getApi() == api) {
|
||||||
|
rightapi = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exSA instanceof AbilitySub && !doTrigger(exSA, false)) {
|
||||||
|
// AI would not run this chapter if given the chance
|
||||||
|
// TODO eventually we'll want to consider playing it anyway, especially if Read ahead would still allow an immediate benefit
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (api != null && !rightapi) {
|
if (api != null && !rightapi) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
|||||||
// TODO Determine exile from same zone for AI
|
// TODO Determine exile from same zone for AI
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
CardCollectionView chosen = ComputerUtil.chooseExileFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c, ability);
|
CardCollectionView chosen = ComputerUtil.chooseExileFrom(player, cost, source, c, ability);
|
||||||
return null == chosen ? null : PaymentDecision.card(chosen);
|
return null == chosen ? null : PaymentDecision.card(chosen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ import forge.game.combat.Combat;
|
|||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.cost.CostDiscard;
|
import forge.game.cost.CostDiscard;
|
||||||
|
import forge.game.cost.CostExile;
|
||||||
import forge.game.cost.CostPart;
|
import forge.game.cost.CostPart;
|
||||||
import forge.game.cost.CostPayment;
|
import forge.game.cost.CostPayment;
|
||||||
import forge.game.cost.CostPutCounter;
|
import forge.game.cost.CostPutCounter;
|
||||||
@@ -641,9 +642,14 @@ public class ComputerUtil {
|
|||||||
return sacList;
|
return sacList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CardCollection chooseExileFrom(final Player ai, final ZoneType zone, final String type, final Card activate,
|
public static CardCollection chooseExileFrom(final Player ai, CostExile cost, final Card activate, final int amount, SpellAbility sa) {
|
||||||
final Card target, final int amount, SpellAbility sa) {
|
CardCollection typeList;
|
||||||
CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(zone), type.split(";"), activate.getController(), activate, sa);
|
if (cost.zoneRestriction != 1) {
|
||||||
|
typeList = new CardCollection(ai.getGame().getCardsIn(cost.from));
|
||||||
|
} else {
|
||||||
|
typeList = new CardCollection(ai.getCardsIn(cost.from));
|
||||||
|
}
|
||||||
|
typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), activate.getController(), activate, sa);
|
||||||
|
|
||||||
// don't exile the card we're pumping
|
// don't exile the card we're pumping
|
||||||
typeList = ComputerUtilCost.paymentChoicesWithoutTargets(typeList, sa, ai);
|
typeList = ComputerUtilCost.paymentChoicesWithoutTargets(typeList, sa, ai);
|
||||||
|
|||||||
@@ -2410,7 +2410,6 @@ public class ComputerUtilCombat {
|
|||||||
// (currently looks for the creature with maximum raw power since that's what the AI usually judges by when
|
// (currently looks for the creature with maximum raw power since that's what the AI usually judges by when
|
||||||
// deciding whether the creature is worth blocking).
|
// deciding whether the creature is worth blocking).
|
||||||
// If the creature doesn't change into anything, returns the original creature.
|
// If the creature doesn't change into anything, returns the original creature.
|
||||||
if (attacker == null) { return null; }
|
|
||||||
Card attackerAfterTrigs = attacker;
|
Card attackerAfterTrigs = attacker;
|
||||||
|
|
||||||
// Test for some special triggers that can change the creature in combat
|
// Test for some special triggers that can change the creature in combat
|
||||||
|
|||||||
@@ -1412,7 +1412,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// avoid randomly moving the equipment back and forth between several creatures in one turn
|
// avoid randomly moving the equipment back and forth between several creatures in one turn
|
||||||
if (AiCardMemory.isRememberedCard(aiPlayer, sa.getHostCard(), AiCardMemory.MemorySet.ATTACHED_THIS_TURN) && !mandatory) {
|
if (AiCardMemory.isRememberedCard(aiPlayer, attachSource, AiCardMemory.MemorySet.ATTACHED_THIS_TURN) && !mandatory) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1423,7 +1423,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AiCardMemory.rememberCard(aiPlayer, sa.getHostCard(), AiCardMemory.MemorySet.ATTACHED_THIS_TURN);
|
AiCardMemory.rememberCard(aiPlayer, attachSource, AiCardMemory.MemorySet.ATTACHED_THIS_TURN);
|
||||||
|
|
||||||
if (c == null && mandatory) {
|
if (c == null && mandatory) {
|
||||||
CardLists.shuffle(list);
|
CardLists.shuffle(list);
|
||||||
@@ -1674,12 +1674,6 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
if (c == null) {
|
if (c == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (sa.getHostCard() == null) {
|
|
||||||
// FIXME: Not sure what should the resolution be if a SpellAbility has no host card. This should
|
|
||||||
// not happen normally. Possibly remove this block altogether? (if it's an impossible condition).
|
|
||||||
System.out.println("AttachAi: isUsefulAttachAction unexpectedly called with SpellAbility with no host card. Assuming it's a determined useful action.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// useless to equip a creature that can't attack or block.
|
// useless to equip a creature that can't attack or block.
|
||||||
return !sa.getHostCard().isEquipment() || !ComputerUtilCard.isUselessCreature(ai, c);
|
return !sa.getHostCard().isEquipment() || !ComputerUtilCard.isUselessCreature(ai, c);
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ public class CloneAi extends SpellAbilityAi {
|
|||||||
bFlag = true;
|
bFlag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bFlag) { // All of the defined stuff is cloned, not very useful
|
if (!bFlag) { // All of the defined stuff is cloned, not very useful
|
||||||
|
|||||||
@@ -1221,4 +1221,12 @@ public class CountersPutAi extends CountersAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int chooseNumber(Player player, SpellAbility sa, int min, int max, Map<String, Object> params) {
|
||||||
|
if (sa.hasParam("ReadAhead")) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.GameEntityCounterTable;
|
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CounterType;
|
import forge.game.card.CounterType;
|
||||||
@@ -21,19 +19,16 @@ public class CountersNoteEffect extends SpellAbilityEffect {
|
|||||||
@Override
|
@Override
|
||||||
public void resolve(SpellAbility sa) {
|
public void resolve(SpellAbility sa) {
|
||||||
Card source = sa.getHostCard();
|
Card source = sa.getHostCard();
|
||||||
final Game game = source.getGame();
|
|
||||||
Player p = sa.getActivatingPlayer();
|
Player p = sa.getActivatingPlayer();
|
||||||
String mode = sa.getParamOrDefault("Mode", "Load");
|
String mode = sa.getParamOrDefault("Mode", "Load");
|
||||||
|
|
||||||
GameEntityCounterTable table = new GameEntityCounterTable();
|
|
||||||
for (Card c : getDefinedCardsOrTargeted(sa)) {
|
for (Card c : getDefinedCardsOrTargeted(sa)) {
|
||||||
if (mode.equals(MODE_STORE)) {
|
if (mode.equals(MODE_STORE)) {
|
||||||
noteCounters(c, source);
|
noteCounters(c, source);
|
||||||
} else if (mode.equals(MODE_LOAD)) {
|
} else if (mode.equals(MODE_LOAD)) {
|
||||||
loadCounters(c, source, p, sa, table);
|
loadCounters(c, source, p, sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
table.replaceCounterEffect(game, sa, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void noteCounters(Card notee, Card source) {
|
public static void noteCounters(Card notee, Card source) {
|
||||||
@@ -44,13 +39,13 @@ public class CountersNoteEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadCounters(Card notee, Card source, final Player p, final SpellAbility sa, GameEntityCounterTable table) {
|
private void loadCounters(Card notee, Card source, final Player p, final SpellAbility sa) {
|
||||||
for (Entry<String, String> svar : source.getSVars().entrySet()) {
|
for (Entry<String, String> svar : source.getSVars().entrySet()) {
|
||||||
String key = svar.getKey();
|
String key = svar.getKey();
|
||||||
if (key.startsWith(NOTE_COUNTERS)) {
|
if (key.startsWith(NOTE_COUNTERS)) {
|
||||||
notee.addCounter(
|
notee.addEtbCounter(
|
||||||
CounterType.getType(key.substring(NOTE_COUNTERS.length())),
|
CounterType.getType(key.substring(NOTE_COUNTERS.length())),
|
||||||
Integer.parseInt(svar.getValue()), p, table);
|
Integer.parseInt(svar.getValue()), p);
|
||||||
}
|
}
|
||||||
// TODO Probably should "remove" the svars that were temporarily used
|
// TODO Probably should "remove" the svars that were temporarily used
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6374,7 +6374,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.get("Destination").equals(ZoneType.Battlefield.toString())) {
|
if (!ZoneType.Battlefield.toString().equals(params.get("Destination"))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Creeping Chill
|
|||||||
ManaCost:3 B
|
ManaCost:3 B
|
||||||
Types:Sorcery
|
Types:Sorcery
|
||||||
A:SP$ DamageAll | StackDescription$ CARDNAME deals 3 damage to each opponent and | Cost$ 3 B | ValidPlayers$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 3 damage to each opponent and you gain 3 life.
|
A:SP$ DamageAll | StackDescription$ CARDNAME deals 3 damage to each opponent and | Cost$ 3 B | ValidPlayers$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 3 damage to each opponent and you gain 3 life.
|
||||||
T:Mode$ ChangesZone | Origin$ Library | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ When CARDNAME is put into your graveyard from your library, you may exile it. If you do, then a opponent and you gain 3 life.
|
T:Mode$ ChangesZone | Origin$ Library | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ When CARDNAME is put into your graveyard from your library, you may exile it. If you do, CARDNAME deals 3 damage to each opponent and you gain 3 life.
|
||||||
SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredCardLKICopy | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBDamage
|
SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredCardLKICopy | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBDamage
|
||||||
SVar:DBDamage:DB$ DealDamage | Defined$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife
|
SVar:DBDamage:DB$ DealDamage | Defined$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife
|
||||||
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 3
|
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 3
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ Types:Legendary Creature Phyrexian Vampire
|
|||||||
PT:5/4
|
PT:5/4
|
||||||
K:Flying
|
K:Flying
|
||||||
T:Mode$ ChangesZone | ValidCard$ Creature.nonToken+Other+YouCtrl | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ Whenever another nontoken creature you control dies, you may pay 2 life and exile it. If you do, create a token that's a copy of that creature, except it's 1/1 and has toxic 1. (Players dealt combat damage by it also get a poison counter.)
|
T:Mode$ ChangesZone | ValidCard$ Creature.nonToken+Other+YouCtrl | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ Whenever another nontoken creature you control dies, you may pay 2 life and exile it. If you do, create a token that's a copy of that creature, except it's 1/1 and has toxic 1. (Players dealt combat damage by it also get a poison counter.)
|
||||||
SVar:TrigExile:AB$ CopyPermanent | Cost$ PayLife<2> ExileFromGrave<1/Card.TriggeredCard/Exile nontoken creature that just died> | AddKeywords$ Toxic:1 | Defined$ TriggeredCardLKICopy | SetPower$ 1 | SetToughness$ 1
|
SVar:TrigExile:AB$ CopyPermanent | Cost$ PayLife<2> ExileAnyGrave<1/Card.TriggeredCard/Exile nontoken creature that just died> | AddKeywords$ Toxic:1 | Defined$ TriggeredCardLKICopy | SetPower$ 1 | SetToughness$ 1
|
||||||
DeckHas:Ability$Token
|
DeckHas:Ability$Token
|
||||||
Oracle:Flying\nWhenever another nontoken creature you control dies, you may pay 2 life and exile it. If you do, create a token that's a copy of that creature, except it's 1/1 and has toxic 1. (Players dealt combat damage by it also get a poison counter.)
|
Oracle:Flying\nWhenever another nontoken creature you control dies, you may pay 2 life and exile it. If you do, create a token that's a copy of that creature, except it's 1/1 and has toxic 1. (Players dealt combat damage by it also get a poison counter.)
|
||||||
|
|||||||
@@ -2,16 +2,12 @@ Name:Tawnos's Coffin
|
|||||||
ManaCost:4
|
ManaCost:4
|
||||||
Types:Artifact
|
Types:Artifact
|
||||||
K:You may choose not to untap CARDNAME during your untap step.
|
K:You may choose not to untap CARDNAME during your untap step.
|
||||||
A:AB$ Pump | Cost$ 3 T | ValidTgts$ Creature | ImprintCards$ Targeted | SubAbility$ DBRememberAura | StackDescription$ SpellDescription | SpellDescription$ Exile target creature and all Auras attached to it. Note the number and kind of counters that were on that creature. When CARDNAME leaves the battlefield or becomes untapped, return that exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the other exiled cards to the battlefield under their owner's control attached to that permanent.
|
A:AB$ Effect | Cost$ 3 T | ValidTgts$ Creature | Triggers$ LeavesPlay,Untap | ImprintCards$ Targeted | RememberObjects$ Valid Aura.AttachedTo Targeted | NoteCounterDefined$ Targeted | Duration$ Permanent | SubAbility$ DBExile | StackDescription$ SpellDescription | SpellDescription$ Exile target creature and all Auras attached to it. Note the number and kind of counters that were on that creature. When CARDNAME leaves the battlefield or becomes untapped, return that exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the other exiled cards to the battlefield under their owner's control attached to that permanent.
|
||||||
SVar:DBRememberAura:DB$ PumpAll | ValidCards$ Aura.AttachedTo Creature.IsImprinted | RememberAllPumped$ True | StackDescription$ None | SubAbility$ DBEffect
|
SVar:DBExile:DB$ ChangeZoneAll | Origin$ Battlefield | Destination$ Exile | ChangeType$ Targeted.Self,Aura.AttachedTo Card.Self
|
||||||
SVar:DBEffect:DB$ Effect | Triggers$ LeavesPlay,Untap | ImprintCards$ ParentTarget | RememberObjects$ Remembered | NoteCounterDefined$ Imprinted | Duration$ Permanent | SubAbility$ DBExile
|
SVar:LeavesPlay:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.EffectSource | Execute$ TrigCounters | TriggerController$ TriggeredCardController | OneOff$ True | TriggerDescription$ When EFFECTSOURCE leaves the battlefield or becomes untapped, return that exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the other exiled cards to the battlefield under their owner's control attached to that permanent.
|
||||||
SVar:DBExile:DB$ ChangeZoneAll | Origin$ Battlefield | Destination$ Exile | ChangeType$ Card.IsRemembered,Card.IsImprinted | SubAbility$ DBCleanup
|
SVar:Untap:Mode$ Untaps | ValidCard$ Card.EffectSource | Execute$ TrigCounters | TriggerController$ TriggeredCardController | OneOff$ True | Secondary$ True | TriggerDescription$ When EFFECTSOURCE leaves the battlefield or becomes untapped, return that exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the other exiled cards to the battlefield under their owner's control attached to that permanent.
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True
|
SVar:TrigCounters:DB$ NoteCounters | Mode$ Load | Defined$ Imprinted | SubAbility$ TrigReturn
|
||||||
SVar:LeavesPlay:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.EffectSource | Execute$ RestoreCounters | TriggerController$ TriggeredCardController | TriggerDescription$ When EFFECTSOURCE leaves the battlefield or becomes untapped, return that exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the other exiled cards to the battlefield under their owner's control attached to that permanent.
|
SVar:TrigReturn:DB$ ChangeZone | Defined$ Imprinted | Origin$ Exile | Destination$ Battlefield | Tapped$ True | SubAbility$ TrigAuraReturn
|
||||||
SVar:Untap:Mode$ Untaps | ValidCard$ Card.EffectSource | Execute$ TrigReturn | TriggerController$ TriggeredCardController | Secondary$ True | TriggerDescription$ When EFFECTSOURCE leaves the battlefield or becomes untapped, return that exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the other exiled cards to the battlefield under their owner's control attached to that permanent.
|
SVar:TrigAuraReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | AttachedTo$ Imprinted
|
||||||
SVar:TrigReturn:DB$ ChangeZone | Defined$ Imprinted | Origin$ Exile | Destination$ Battlefield | Tapped$ True | SubAbility$ RestoreCounters
|
|
||||||
SVar:RestoreCounters:DB$ NoteCounters | Mode$ Load | Defined$ Imprinted | SubAbility$ TrigAuraReturn
|
|
||||||
SVar:TrigAuraReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | AttachedTo$ Valid Creature.IsImprinted | SubAbility$ ExileSelf
|
|
||||||
SVar:ExileSelf:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Self
|
|
||||||
AI:RemoveDeck:All
|
AI:RemoveDeck:All
|
||||||
Oracle:You may choose not to untap Tawnos's Coffin during your untap step.\n{3}, {T}: Exile target creature and all Auras attached to it. Note the number and kind of counters that were on that creature. When Tawnos's Coffin leaves the battlefield or becomes untapped, return that exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the other exiled cards to the battlefield under their owner's control attached to that permanent.
|
Oracle:You may choose not to untap Tawnos's Coffin during your untap step.\n{3}, {T}: Exile target creature and all Auras attached to it. Note the number and kind of counters that were on that creature. When Tawnos's Coffin leaves the battlefield or becomes untapped, return that exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the other exiled cards to the battlefield under their owner's control attached to that permanent.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Legendary Creature Vampire Noble
|
|||||||
PT:4/4
|
PT:4/4
|
||||||
K:Ward:Discard<1/Card>
|
K:Ward:Discard<1/Card>
|
||||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Vampire.Other+nonToken+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever another nontoken Vampire you control dies, you may pay {1} and exile it. If you do, create a 1/1 black Bat creature token with flying. It gains "When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped."
|
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Vampire.Other+nonToken+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever another nontoken Vampire you control dies, you may pay {1} and exile it. If you do, create a 1/1 black Bat creature token with flying. It gains "When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped."
|
||||||
SVar:TrigToken:AB$ Token | Cost$ 1 ExileFromGrave<1/Card.TriggeredNewCard/the Vampire card> | TokenRemembered$ ExiledCards | TokenScript$ b_1_1_bat_flying | ImprintTokens$ True | SubAbility$ DBAnimate
|
SVar:TrigToken:AB$ Token | Cost$ 1 ExileAnyGrave<1/Card.TriggeredNewCard/the Vampire card> | TokenRemembered$ ExiledCards | TokenScript$ b_1_1_bat_flying | ImprintTokens$ True | SubAbility$ DBAnimate
|
||||||
SVar:DBAnimate:DB$ Animate | Defined$ Imprinted | Duration$ Permanent | Triggers$ CDTrigger
|
SVar:DBAnimate:DB$ Animate | Defined$ Imprinted | Duration$ Permanent | Triggers$ CDTrigger
|
||||||
SVar:CDTrigger:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigSac | TriggerZones$ Battlefield | TriggerDescription$ When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped.
|
SVar:CDTrigger:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigSac | TriggerZones$ Battlefield | TriggerDescription$ When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped.
|
||||||
SVar:TrigSac:DB$ Sacrifice | SubAbility$ DBReturn
|
SVar:TrigSac:DB$ Sacrifice | SubAbility$ DBReturn
|
||||||
|
|||||||
@@ -320,7 +320,13 @@ public class HumanPlay {
|
|||||||
costExile.payAsDecided(p, PaymentDecision.card(p.getCardsIn(ZoneType.Graveyard)), sourceAbility, hcd.isEffect());
|
costExile.payAsDecided(p, PaymentDecision.card(p.getCardsIn(ZoneType.Graveyard)), sourceAbility, hcd.isEffect());
|
||||||
} else {
|
} else {
|
||||||
from = costExile.getFrom();
|
from = costExile.getFrom();
|
||||||
CardCollection list = CardLists.getValidCards(p.getCardsIn(from), part.getType().split(";"), p, source, sourceAbility);
|
CardCollection list;
|
||||||
|
if (costExile.zoneRestriction != 1) {
|
||||||
|
list = new CardCollection(p.getGame().getCardsIn(from));
|
||||||
|
} else {
|
||||||
|
list = new CardCollection(p.getCardsIn(from));
|
||||||
|
}
|
||||||
|
list = CardLists.getValidCards(list, part.getType().split(";"), p, source, sourceAbility);
|
||||||
final int nNeeded = getAmountFromPart(part, source, sourceAbility);
|
final int nNeeded = getAmountFromPart(part, source, sourceAbility);
|
||||||
if (list.size() < nNeeded) {
|
if (list.size() < nNeeded) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user