Merge branch 'exchangeControlTrickster' into 'master'

ExchangeControl: add Optional and two Targets also TargetsWithSameCardType

See merge request core-developers/forge!3705
This commit is contained in:
Michael Kamensky
2021-02-02 17:06:19 +00:00
20 changed files with 163 additions and 54 deletions

View File

@@ -81,7 +81,12 @@ public class ControlExchangeAi extends SpellAbilityAi {
final TargetRestrictions tgt = sa.getTargetRestrictions(); final TargetRestrictions tgt = sa.getTargetRestrictions();
CardCollection list = CardLists.getValidCards(aiPlayer.getGame().getCardsIn(ZoneType.Battlefield), // for TrigTwoTargets logic, only get the opponents' cards for the first target
CardCollectionView unfilteredList = "TrigTwoTargets".equals(sa.getParam("AILogic")) ?
aiPlayer.getOpponents().getCardsIn(ZoneType.Battlefield) :
aiPlayer.getGame().getCardsIn(ZoneType.Battlefield);
CardCollection list = CardLists.getValidCards(unfilteredList,
tgt.getValidTgts(), aiPlayer, sa.getHostCard(), sa); tgt.getValidTgts(), aiPlayer, sa.getHostCard(), sa);
// only select the cards that can be targeted // only select the cards that can be targeted
@@ -106,7 +111,51 @@ public class ControlExchangeAi extends SpellAbilityAi {
// add best Target // add best Target
sa.getTargets().add(best); sa.getTargets().add(best);
// second target needed (the AI's own worst)
if ("TrigTwoTargets".equals(sa.getParam("AILogic"))) {
return doTrigTwoTargetsLogic(aiPlayer, sa, best);
}
return true; return true;
} }
private boolean doTrigTwoTargetsLogic(Player ai, SpellAbility sa, Card bestFirstTgt) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final int creatureThreshold = 100; // TODO: make this configurable from the AI profile
final int nonCreatureThreshold = 2;
CardCollection list = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield),
tgt.getValidTgts(), ai, sa.getHostCard(), sa);
// only select the cards that can be targeted
list = CardLists.getTargetableCards(list, sa);
if (list.isEmpty()) {
return false;
}
Card aiWorst = ComputerUtilCard.getWorstAI(list);
if (aiWorst == null) {
return false;
}
if (aiWorst != null && aiWorst != bestFirstTgt) {
if (bestFirstTgt.isCreature() && aiWorst.isCreature()) {
if ((ComputerUtilCard.evaluateCreature(bestFirstTgt) > ComputerUtilCard.evaluateCreature(aiWorst) + creatureThreshold) || sa.isMandatory()) {
sa.getTargets().add(aiWorst);
return true;
}
} else {
// TODO: compare non-creatures by CMC - can be improved, at least shouldn't give control of things like the Power Nine
if ((bestFirstTgt.getCMC() > aiWorst.getCMC() + nonCreatureThreshold) || sa.isMandatory()) {
sa.getTargets().add(aiWorst);
return true;
}
}
}
sa.clearTargets();
return false;
}
} }

View File

@@ -352,6 +352,9 @@ public final class AbilityFactory {
if (mapParams.containsKey("TargetsWithSameCreatureType")) { if (mapParams.containsKey("TargetsWithSameCreatureType")) {
abTgt.setWithSameCreatureType(true); abTgt.setWithSameCreatureType(true);
} }
if (mapParams.containsKey("TargetsWithSameCardType")) {
abTgt.setWithSameCardType(true);
}
if (mapParams.containsKey("TargetsWithSameController")) { if (mapParams.containsKey("TargetsWithSameController")) {
abTgt.setSameController(true); abTgt.setSameController(true);
} }

View File

@@ -1,14 +1,16 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.game.Game;
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.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions; import forge.util.CardTranslation;
import forge.util.Localizer;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -21,21 +23,27 @@ public class ControlExchangeEffect extends SpellAbilityEffect {
protected String getStackDescription(SpellAbility sa) { protected String getStackDescription(SpellAbility sa) {
Card object1 = null; Card object1 = null;
Card object2 = null; Card object2 = null;
final TargetRestrictions tgt = sa.getTargetRestrictions(); List<Card> tgts = null;
List<Card> tgts = tgt == null ? new ArrayList<>() : Lists.newArrayList(sa.getTargets().getTargetCards()); if (sa.usesTargeting()) {
if (tgts.size() > 0) { tgts = Lists.newArrayList(sa.getTargets().getTargetCards());
object1 = tgts.get(0); if (tgts.size() > 0) {
object1 = tgts.get(0);
}
} }
if (sa.hasParam("Defined")) { if (sa.hasParam("Defined")) {
List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa); List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
object2 = cards.isEmpty() ? null : cards.get(0); object2 = cards.isEmpty() ? null : cards.get(0);
if (cards.size() > 1 && sa.hasParam("BothDefined")) { if (cards.size() > 1 && !sa.usesTargeting()) {
object1 = cards.get(1); object1 = cards.get(1);
} }
} else if (tgts.size() > 1) { } else if (tgts.size() > 1) {
object2 = tgts.get(1); object2 = tgts.get(1);
} }
if (object1 == null || object2 == null) {
return "";
}
return object1 + " exchanges controller with " + object2; return object1 + " exchanges controller with " + object2;
} }
@@ -44,17 +52,22 @@ public class ControlExchangeEffect extends SpellAbilityEffect {
*/ */
@Override @Override
public void resolve(SpellAbility sa) { public void resolve(SpellAbility sa) {
Card host = sa.getHostCard();
Game game = host.getGame();
Card object1 = null; Card object1 = null;
Card object2 = null; Card object2 = null;
final TargetRestrictions tgt = sa.getTargetRestrictions();
List<Card> tgts = tgt == null ? new ArrayList<>() : Lists.newArrayList(sa.getTargets().getTargetCards()); List<Card> tgts = null;
if (tgts.size() > 0) { if (sa.usesTargeting()) {
object1 = tgts.get(0); tgts = Lists.newArrayList(sa.getTargets().getTargetCards());
if (tgts.size() > 0) {
object1 = tgts.get(0);
}
} }
if (sa.hasParam("Defined")) { if (sa.hasParam("Defined")) {
final List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa); final List<Card> cards = AbilityUtils.getDefinedCards(host, sa.getParam("Defined"), sa);
object2 = cards.isEmpty() ? null : cards.get(0); object2 = cards.isEmpty() ? null : cards.get(0);
if (cards.size() > 1 && sa.hasParam("BothDefined")) { if (cards.size() > 1 && !sa.usesTargeting()) {
object1 = cards.get(1); object1 = cards.get(1);
} }
} else if (tgts.size() > 1) { } else if (tgts.size() > 1) {
@@ -73,7 +86,16 @@ public class ControlExchangeEffect extends SpellAbilityEffect {
return; return;
} }
final long tStamp = sa.getActivatingPlayer().getGame().getNextTimestamp(); if (sa.hasParam("Optional")) {
if (!sa.getActivatingPlayer().getController().confirmAction(sa, null,
Localizer.getInstance().getMessage("lblExchangeControl",
CardTranslation.getTranslatedName(object1.getName()),
CardTranslation.getTranslatedName(object2.getName())))) {
return;
}
}
final long tStamp = game.getNextTimestamp();
object2.setController(player1, tStamp); object2.setController(player1, tStamp);
object1.setController(player2, tStamp); object1.setController(player2, tStamp);
if (sa.hasParam("RememberExchanged")) { if (sa.hasParam("RememberExchanged")) {

View File

@@ -1056,29 +1056,26 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
final Card c = (Card) entity; final Card c = (Card) entity;
CardCollection pl = AbilityUtils.getDefinedCards(getHostCard(), getParam("TargetsWithSharedCardType"), this); CardCollection pl = AbilityUtils.getDefinedCards(getHostCard(), getParam("TargetsWithSharedCardType"), this);
for (final Card crd : pl) { for (final Card crd : pl) {
if (!c.sharesCardTypeWith(crd)) { // one of those types
return false; if (hasParam("TargetsWithSharedTypes")) {
boolean flag = false;
for (final String type : getParam("TargetsWithSharedTypes").split(",")) {
if (c.getType().hasStringType(type) && crd.getType().hasStringType(type)) {
flag = true;
break;
}
}
if (!flag) {
return false;
}
} else {
if (!c.sharesCardTypeWith(crd)) {
return false;
}
} }
} }
} }
if (hasParam("TargetsWithSharedTypes") && entity instanceof Card) {
final Card c = (Card) entity;
final SpellAbility parent = getParentTargetingCard();
final Card parentTargeted = parent != null ? parent.getTargetCard() : null;
if (parentTargeted == null) {
return false;
}
boolean flag = false;
for (final String type : getParam("TargetsWithSharedTypes").split(",")) {
if (c.getType().hasStringType(type) && parentTargeted.getType().hasStringType(type)) {
flag = true;
break;
}
}
if (!flag) {
return false;
}
}
if (hasParam("TargetsWithControllerProperty") && entity instanceof Card) { if (hasParam("TargetsWithControllerProperty") && entity instanceof Card) {
final String prop = getParam("TargetsWithControllerProperty"); final String prop = getParam("TargetsWithControllerProperty");
final Card c = (Card) entity; final Card c = (Card) entity;
@@ -1172,6 +1169,16 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
} }
} }
if (tr.isWithSameCardType()) {
if (entity instanceof Card) {
for (final Card c : targetChosen.getTargetCards()) {
if (entity != c && !c.sharesCardTypeWith((Card) entity)) {
return false;
}
}
}
}
String[] validTgt = tr.getValidTgts(); String[] validTgt = tr.getValidTgts();
if (entity instanceof GameEntity) { if (entity instanceof GameEntity) {
GameEntity e = (GameEntity)entity; GameEntity e = (GameEntity)entity;

View File

@@ -65,6 +65,7 @@ public class TargetRestrictions {
private boolean sameController = false; private boolean sameController = false;
private boolean withoutSameCreatureType = false; private boolean withoutSameCreatureType = false;
private boolean withSameCreatureType = false; private boolean withSameCreatureType = false;
private boolean withSameCardType = false;
private boolean singleTarget = false; private boolean singleTarget = false;
private boolean randomTarget = false; private boolean randomTarget = false;
@@ -108,6 +109,7 @@ public class TargetRestrictions {
this.sameController = target.isSameController(); this.sameController = target.isSameController();
this.withoutSameCreatureType = target.isWithoutSameCreatureType(); this.withoutSameCreatureType = target.isWithoutSameCreatureType();
this.withSameCreatureType = target.isWithSameCreatureType(); this.withSameCreatureType = target.isWithSameCreatureType();
this.withSameCardType = target.isWithSameCardType();
this.singleTarget = target.isSingleTarget(); this.singleTarget = target.isSingleTarget();
this.randomTarget = target.isRandomTarget(); this.randomTarget = target.isRandomTarget();
} }
@@ -622,6 +624,20 @@ public class TargetRestrictions {
this.withSameCreatureType = b; this.withSameCreatureType = b;
} }
/**
* @return the withSameCardType
*/
public boolean isWithSameCardType() {
return withSameCardType;
}
/**
* @param b the withSameCardType to set
*/
public void setWithSameCardType(boolean b) {
this.withSameCardType = b;
}
/** /**
* <p> * <p>
* copy. * copy.

View File

@@ -5,9 +5,7 @@ T:Mode$ PlaneswalkedTo | ValidCard$ Card.Self | Execute$ TrigLife | OptionalDeci
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigLife | TriggerZones$ Command | Secondary$ True | OptionalDecider$ You | TriggerDescription$ When you planeswalk to CARDNAME or at the beginning of your upkeep, you may exchange life totals with target player. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigLife | TriggerZones$ Command | Secondary$ True | OptionalDecider$ You | TriggerDescription$ When you planeswalk to CARDNAME or at the beginning of your upkeep, you may exchange life totals with target player.
SVar:TrigLife:DB$ ExchangeLife | Optional$ True | ValidTgts$ Player | TgtPrompt$ Select target player to exchange life totals with SVar:TrigLife:DB$ ExchangeLife | Optional$ True | ValidTgts$ Player | TgtPrompt$ Select target player to exchange life totals with
T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll {CHAOS}, exchange control of two target permanents that share a card type. T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll {CHAOS}, exchange control of two target permanents that share a card type.
SVar:RolledChaos:DB$ Pump | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | SubAbility$ DBExchange SVar:RolledChaos:DB$ ExchangeControl | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Permanent | TgtPrompt$ Select target permanents that share a permanent type | TargetsWithSameCardType$ True
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent card | TargetsWithSharedTypes$ Creature,Artifact,Enchantment,Planeswalker,Land,Tribal | TargetUnique$ True
AI:RemoveDeck:All AI:RemoveDeck:All
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/cliffside_market.jpg
Oracle:When you planeswalk to Cliffside Market or at the beginning of your upkeep, you may exchange life totals with target player.\nWhenever you roll {CHAOS}, exchange control of two target permanents that share a card type. Oracle:When you planeswalk to Cliffside Market or at the beginning of your upkeep, you may exchange life totals with target player.\nWhenever you roll {CHAOS}, exchange control of two target permanents that share a card type.

View File

@@ -4,5 +4,4 @@ Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Artifact,Creature,Enchantment | TriggerZones$ Battlefield | Execute$ TrigExchangeControl | TriggerDescription$ Whenever an artifact, creature, or enchantment enters the battlefield, its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Artifact,Creature,Enchantment | TriggerZones$ Battlefield | Execute$ TrigExchangeControl | TriggerDescription$ Whenever an artifact, creature, or enchantment enters the battlefield, its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents.
SVar:TrigExchangeControl:DB$ ExchangeControl | Defined$ TriggeredCard | TargetingPlayer$ TriggeredCardController | TargetsWithDefinedController$ NonTriggeredCardController | ValidTgts$ Permanent | TargetsWithSharedCardType$ TriggeredCard SVar:TrigExchangeControl:DB$ ExchangeControl | Defined$ TriggeredCard | TargetingPlayer$ TriggeredCardController | TargetsWithDefinedController$ NonTriggeredCardController | ValidTgts$ Permanent | TargetsWithSharedCardType$ TriggeredCard
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/confusion_in_the_ranks.jpg
Oracle:Whenever an artifact, creature, or enchantment enters the battlefield, its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents. Oracle:Whenever an artifact, creature, or enchantment enters the battlefield, its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents.

View File

@@ -4,8 +4,7 @@ Types:Creature Human Rogue
PT:2/3 PT:2/3
T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigExchangeControl | OptionalDecider$ You | TriggerDescription$ Inspired — Whenever CARDNAME becomes untapped, you may exchange control of target nonland permanent you control and target permanent an opponent controls that shares a card type with it. T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigExchangeControl | OptionalDecider$ You | TriggerDescription$ Inspired — Whenever CARDNAME becomes untapped, you may exchange control of target nonland permanent you control and target permanent an opponent controls that shares a card type with it.
SVar:TrigExchangeControl:DB$ Pump | ValidTgts$ Permanent.YouCtrl+nonLand | TgtPrompt$ Select target nonland permanent you control | SubAbility$ DBExchange SVar:TrigExchangeControl:DB$ Pump | ValidTgts$ Permanent.YouCtrl+nonLand | TgtPrompt$ Select target nonland permanent you control | SubAbility$ DBExchange
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls that shares a card type with it | TargetsWithSharedTypes$ Creature,Artifact,Enchantment,Planeswalker,Tribal SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls that shares a card type with it | TargetsWithSharedCardType$ ParentTarget
AI:RemoveDeck:All AI:RemoveDeck:All
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/daring_thief.jpg
Oracle:Inspired — Whenever Daring Thief becomes untapped, you may exchange control of target nonland permanent you control and target permanent an opponent controls that shares a card type with it. Oracle:Inspired — Whenever Daring Thief becomes untapped, you may exchange control of target nonland permanent you control and target permanent an opponent controls that shares a card type with it.

View File

@@ -2,9 +2,8 @@ Name:Gauntlets of Chaos
ManaCost:5 ManaCost:5
Types:Artifact Types:Artifact
A:AB$ Pump | Cost$ 5 Sac<1/CARDNAME> | ValidTgts$ Artifact.YouCtrl,Creature.YouCtrl,Land.YouCtrl | TgtPrompt$ target artifact, creature, or land you control | StackDescription$ None | SubAbility$ DBExchange | SpellDescription$ Exchange control of target artifact, creature, or land you control and target permanent an opponent controls that shares one of those types with it. If those permanents are exchanged this way, destroy all Auras attached to them. A:AB$ Pump | Cost$ 5 Sac<1/CARDNAME> | ValidTgts$ Artifact.YouCtrl,Creature.YouCtrl,Land.YouCtrl | TgtPrompt$ target artifact, creature, or land you control | StackDescription$ None | SubAbility$ DBExchange | SpellDescription$ Exchange control of target artifact, creature, or land you control and target permanent an opponent controls that shares one of those types with it. If those permanents are exchanged this way, destroy all Auras attached to them.
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls that shares one of those types | TargetsWithSharedTypes$ Artifact,Creature,Land | RememberExchanged$ True | SubAbility$ DBDestroyAll SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls that shares one of those types | TargetsWithSharedCardType$ ParentTarget | TargetsWithSharedTypes$ Artifact,Creature,Land | RememberExchanged$ True | SubAbility$ DBDestroyAll
SVar:DBDestroyAll:DB$ DestroyAll | ValidCards$ Aura.AttachedTo Card.IsRemembered | SubAbility$ DBCleanup SVar:DBDestroyAll:DB$ DestroyAll | ValidCards$ Aura.AttachedTo Card.IsRemembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/gauntlets_of_chaos.jpg
Oracle:{5}, Sacrifice Gauntlets of Chaos: Exchange control of target artifact, creature, or land you control and target permanent an opponent controls that shares one of those types with it. If those permanents are exchanged this way, destroy all Auras attached to them. Oracle:{5}, Sacrifice Gauntlets of Chaos: Exchange control of target artifact, creature, or land you control and target permanent an opponent controls that shares one of those types with it. If those permanents are exchanged this way, destroy all Auras attached to them.

View File

@@ -3,16 +3,15 @@ ManaCost:3 U
Types:Sorcery Types:Sorcery
A:SP$ ChooseCard | Cost$ 3 U | ValidTgts$ Player | Choices$ Creature.cmcEQY | TargetControls$ True | References$ Y | Mandatory$ True | AILogic$ WorstCard | RememberChosen$ True | SubAbility$ DBChooseCreatureYou | SpellDescription$ You and target player exchange control of the creature you each control with the highest converted mana cost. Then exchange control of artifacts the same way. If two or more permanents a player controls are tied for highest cost, their controller chooses one of them. A:SP$ ChooseCard | Cost$ 3 U | ValidTgts$ Player | Choices$ Creature.cmcEQY | TargetControls$ True | References$ Y | Mandatory$ True | AILogic$ WorstCard | RememberChosen$ True | SubAbility$ DBChooseCreatureYou | SpellDescription$ You and target player exchange control of the creature you each control with the highest converted mana cost. Then exchange control of artifacts the same way. If two or more permanents a player controls are tied for highest cost, their controller chooses one of them.
SVar:DBChooseCreatureYou:DB$ ChooseCard | Choices$ Creature.YouCtrl+cmcEQX | References$ X | Mandatory$ True | RememberChosen$ True | SubAbility$ DBExchangeCreature SVar:DBChooseCreatureYou:DB$ ChooseCard | Choices$ Creature.YouCtrl+cmcEQX | References$ X | Mandatory$ True | RememberChosen$ True | SubAbility$ DBExchangeCreature
SVar:DBExchangeCreature:DB$ ExchangeControl | BothDefined$ True | Defined$ Remembered | SubAbility$ DBCleanCreature SVar:DBExchangeCreature:DB$ ExchangeControl | Defined$ Remembered | SubAbility$ DBCleanCreature
SVar:DBCleanCreature:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBChooseArtifactYou SVar:DBCleanCreature:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBChooseArtifactYou
SVar:DBChooseArtifactYou:DB$ ChooseCard | Choices$ Artifact.YouCtrl+cmcEQZ | References$ Z | Mandatory$ True | RememberChosen$ True | SubAbility$ DBChooseArtifactOpp SVar:DBChooseArtifactYou:DB$ ChooseCard | Choices$ Artifact.YouCtrl+cmcEQZ | References$ Z | Mandatory$ True | RememberChosen$ True | SubAbility$ DBChooseArtifactOpp
SVar:DBChooseArtifactOpp:DB$ ChooseCard | Defined$ ParentTarget | Choices$ Artifact.cmcEQW | TargetControls$ True | References$ W | Mandatory$ True | AILogic$ WorstCard | RememberChosen$ True | SubAbility$ DBExchangeArtifact SVar:DBChooseArtifactOpp:DB$ ChooseCard | Defined$ ParentTarget | Choices$ Artifact.cmcEQW | TargetControls$ True | References$ W | Mandatory$ True | AILogic$ WorstCard | RememberChosen$ True | SubAbility$ DBExchangeArtifact
SVar:DBExchangeArtifact:DB$ ExchangeControl | BothDefined$ True | Defined$ Remembered | SubAbility$ DBCleanup SVar:DBExchangeArtifact:DB$ ExchangeControl | Defined$ Remembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$HighestCMC_Creature.YouCtrl+inZoneBattlefield SVar:X:Count$HighestCMC_Creature.YouCtrl+inZoneBattlefield
SVar:Y:Count$HighestCMC_Creature.TargetedPlayerCtrl+inZoneBattlefield SVar:Y:Count$HighestCMC_Creature.TargetedPlayerCtrl+inZoneBattlefield
SVar:Z:Count$HighestCMC_Artifact.YouCtrl+inZoneBattlefield SVar:Z:Count$HighestCMC_Artifact.YouCtrl+inZoneBattlefield
SVar:W:Count$HighestCMC_Artifact.TargetedPlayerCtrl+inZoneBattlefield SVar:W:Count$HighestCMC_Artifact.TargetedPlayerCtrl+inZoneBattlefield
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/juxtapose.jpg
Oracle:You and target player exchange control of the creature you each control with the highest converted mana cost. Then exchange control of artifacts the same way. If two or more permanents a player controls are tied for highest cost, their controller chooses one of them. Oracle:You and target player exchange control of the creature you each control with the highest converted mana cost. Then exchange control of artifacts the same way. If two or more permanents a player controls are tied for highest cost, their controller chooses one of them.

View File

@@ -5,7 +5,7 @@ HandLifeModifier:-1/+8
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigExchangeChoose | TriggerDescription$ At the beginning of your upkeep, exchange control of a permanent you control chosen at random and a permanent target opponent controls chosen at random. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigExchangeChoose | TriggerDescription$ At the beginning of your upkeep, exchange control of a permanent you control chosen at random and a permanent target opponent controls chosen at random.
SVar:TrigExchangeChoose:DB$ ChooseCard | ValidTgts$ Opponent | Choices$ Permanent.TargetedPlayerCtrl | AtRandom$ True | Amount$ 1 | RememberChosen$ True | SubAbility$ ChooseYou SVar:TrigExchangeChoose:DB$ ChooseCard | ValidTgts$ Opponent | Choices$ Permanent.TargetedPlayerCtrl | AtRandom$ True | Amount$ 1 | RememberChosen$ True | SubAbility$ ChooseYou
SVar:ChooseYou:DB$ ChooseCard | Choices$ Permanent.YouCtrl | Amount$ 1 | AtRandom$ True | RememberChosen$ True | SubAbility$ DBExchange SVar:ChooseYou:DB$ ChooseCard | Choices$ Permanent.YouCtrl | Amount$ 1 | AtRandom$ True | RememberChosen$ True | SubAbility$ DBExchange
SVar:DBExchange:DB$ ExchangeControl | Defined$ Remembered | BothDefined$ True | SubAbility$ DBCleanup SVar:DBExchange:DB$ ExchangeControl | Defined$ Remembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:Picture:https://downloads.cardforge.org/images/cards/VAN/Karona, False God Avatar.full.jpg SVar:Picture:https://downloads.cardforge.org/images/cards/VAN/Karona, False God Avatar.full.jpg
Oracle:Hand -1, life +8\nAt the beginning of your upkeep, exchange control of a permanent you control chosen at random and a permanent target opponent controls chosen at random. Oracle:Hand -1, life +8\nAt the beginning of your upkeep, exchange control of a permanent you control chosen at random and a permanent target opponent controls chosen at random.

View File

@@ -2,7 +2,7 @@ Name:Legerdemain
ManaCost:2 U U ManaCost:2 U U
Types:Sorcery Types:Sorcery
A:SP$ Pump | Cost$ 2 U U | ValidTgts$ Artifact,Creature | TgtPrompt$ target artifact or creature | StackDescription$ None | SubAbility$ DBExchange | SpellDescription$ Exchange control of target artifact or creature and another target permanent that shares one of those types with it. (This effect lasts indefinitely.) A:SP$ Pump | Cost$ 2 U U | ValidTgts$ Artifact,Creature | TgtPrompt$ target artifact or creature | StackDescription$ None | SubAbility$ DBExchange | SpellDescription$ Exchange control of target artifact or creature and another target permanent that shares one of those types with it. (This effect lasts indefinitely.)
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent that shares one of those types | TargetsWithSharedTypes$ Artifact,Creature | TargetUnique$ True SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent that shares one of those types | TargetsWithSharedCardType$ ParentTarget | TargetsWithSharedTypes$ Artifact,Creature | TargetUnique$ True
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/legerdemain.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/legerdemain.jpg
Oracle:Exchange control of target artifact or creature and another target permanent that shares one of those types with it. (This effect lasts indefinitely.) Oracle:Exchange control of target artifact or creature and another target permanent that shares one of those types with it. (This effect lasts indefinitely.)

View File

@@ -1,8 +1,7 @@
Name:Role Reversal Name:Role Reversal
ManaCost:U U R ManaCost:U U R
Types:Sorcery Types:Sorcery
A:SP$ Pump | Cost$ U U R | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | SubAbility$ DBExchange | StackDescription$ None | SpellDescription$ Exchange control of two target permanents that share a permanent type. A:SP$ ExchangeControl | Cost$ U U R | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Permanent | TgtPrompt$ Select target permanents that share a permanent type | TargetsWithSameCardType$ True | SpellDescription$ Exchange control of two target permanents that share a permanent type.
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent shares a card type with it | TargetsWithSharedTypes$ Creature,Artifact,Enchantment,Planeswalker,Land | TargetUnique$ True
AI:RemoveDeck:All AI:RemoveDeck:All
AI:RemoveDeck:Random AI:RemoveDeck:Random
Oracle:Exchange control of two target permanents that share a permanent type. Oracle:Exchange control of two target permanents that share a permanent type.

View File

@@ -1,9 +1,7 @@
Name:Shifting Loyalties Name:Shifting Loyalties
ManaCost:5 U ManaCost:5 U
Types:Sorcery Types:Sorcery
A:SP$ Pump | Cost$ 5 U | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | SubAbility$ DBExchange | StackDescription$ None | SpellDescription$ Exchange control of two target permanents that share a card type. A:SP$ ExchangeControl | Cost$ 5 U | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Permanent | TgtPrompt$ Select target permanents that share a permanent type | TargetsWithSameCardType$ True | SpellDescription$ Exchange control of two target permanents that share a card type.
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent shares a card type with it | TargetsWithSharedTypes$ Creature,Artifact,Enchantment,Planeswalker,Land,Tribal | TargetUnique$ True
AI:RemoveDeck:All AI:RemoveDeck:All
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/shifting_loyalties.jpg
Oracle:Exchange control of two target permanents that share a card type. (Artifact, creature, enchantment, land, and planeswalker are card types.) Oracle:Exchange control of two target permanents that share a card type. (Artifact, creature, enchantment, land, and planeswalker are card types.)

View File

@@ -0,0 +1,11 @@
Name:The Trickster-God's Heist
ManaCost:2 U B
Types:Enchantment Saga
K:Saga:3:DBCreature,DBNonCreature,DBDrain
SVar:DBCreature:DB$ ExchangeControl | ValidTgts$ Creature | TargetMin$ 2 | TargetMax$ 2 | TgtPrompt$ Choose two target creatures | Optional$ True | AILogic$ TrigTwoTargets | StackDescription$ SpellDescription | SpellDescription$ You may exchange control of two target creatures.
SVar:DBNonCreature:DB$ ExchangeControl | ValidTgts$ Card.nonBasic+nonCreature | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Permanent | TgtPrompt$ Choose two target nonbasic, noncreature permanent | TargetsWithSameCardType$ True | Optional$ True | AILogic$ TrigTwoTargets | StackDescription$ SpellDescription | SpellDescription$ You may exchange control of two target nonbasic, noncreature permanents that share a card type.
SVar:DBDrain:DB$ LoseLife | ValidTgts$ Player | TgtPrompt$ Select a player | LifeAmount$ 3 | SubAbility$ DBGainLife | SpellDescription$ Target player loses 3 life and you gain 3 life.
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 3
DeckHas:Ability$LifeGain
AI:RemoveDeck:Random
Oracle:I - You may exchange control of two target creatures.\nII - You may exchange control of two target nonbasic, noncreature permanents that share a card type.\nIII - Target player loses 3 life and you gain 3 life.

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=gewinnt Fehde
lblLosesClash=verliert Fehde lblLosesClash=verliert Fehde
#CloneEffect.java #CloneEffect.java
lblDoYouWantCopy=Möchtest du {0} kopieren? lblDoYouWantCopy=Möchtest du {0} kopieren?
#ControlExchangeEffect.java
lblExchangeControl=Do you want to exchange control of {0} and {1}?
#ControlExchangeVariantEffect.java #ControlExchangeVariantEffect.java
lblChooseCards=Wähle Karten lblChooseCards=Wähle Karten
#CopyPermanentEffect.java #CopyPermanentEffect.java

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=wins clash
lblLosesClash=loses clash lblLosesClash=loses clash
#CloneEffect.java #CloneEffect.java
lblDoYouWantCopy=Do you want to copy {0}? lblDoYouWantCopy=Do you want to copy {0}?
#ControlExchangeEffect.java
lblExchangeControl=Do you want to exchange control of {0} and {1}?
#ControlExchangeVariantEffect.java #ControlExchangeVariantEffect.java
lblChooseCards=Choose cards lblChooseCards=Choose cards
#CopyPermanentEffect.java #CopyPermanentEffect.java

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=gana el enfrentamiento
lblLosesClash=pierde el enfrentamiento lblLosesClash=pierde el enfrentamiento
#CloneEffect.java #CloneEffect.java
lblDoYouWantCopy=¿Quieres copiar {0}? lblDoYouWantCopy=¿Quieres copiar {0}?
#ControlExchangeEffect.java
lblExchangeControl=¿Quieres intercambiar de {0} y {1}?
#ControlExchangeVariantEffect.java #ControlExchangeVariantEffect.java
lblChooseCards=Elige las cartas lblChooseCards=Elige las cartas
#CopyPermanentEffect.java #CopyPermanentEffect.java

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=wins clash
lblLosesClash=loses clash lblLosesClash=loses clash
#CloneEffect.java #CloneEffect.java
lblDoYouWantCopy=Do you want to copy {0}? lblDoYouWantCopy=Do you want to copy {0}?
#ControlExchangeEffect.java
lblExchangeControl=Do you want to exchange control of {0} and {1}?
#ControlExchangeVariantEffect.java #ControlExchangeVariantEffect.java
lblChooseCards=Choose cards lblChooseCards=Choose cards
#CopyPermanentEffect.java #CopyPermanentEffect.java

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=比点赢了
lblLosesClash=比点输了 lblLosesClash=比点输了
#CloneEffect.java #CloneEffect.java
lblDoYouWantCopy=你想要复制{0}吗? lblDoYouWantCopy=你想要复制{0}吗?
#ControlExchangeEffect.java
lblExchangeControl=Do you want to exchange control of {0} and {1}?
#ControlExchangeVariantEffect.java #ControlExchangeVariantEffect.java
lblChooseCards=选择牌 lblChooseCards=选择牌
#CopyPermanentEffect.java #CopyPermanentEffect.java