Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support engine tracking card mover vs. controller #6420

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions forge-game/src/main/java/forge/game/GameAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,29 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer
c.getController().setRevolt(true);
}

// currently only matters for ETB
// still rather just cover remaining cases with quick default
Player putter = c.getController();

// Don't copy Tokens, copy only cards leaving the battlefield
// and returning to hand (to recreate their spell ability information)
if (toBattlefield || (suppress && zoneTo.getZoneType().isHidden())) {
copied = c;

// in some cases it's always affected that puts them in play (initially)
String defPutter;
if (cause == null || (!cause.hasParam("Putter") && (c.isToken() ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if I like it there

I probably would move the Putter logic into AbilityKey.addCardZoneTableParams

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmn, the problem is the Putter can be different players during the same effect

and most effects currently don't need to modify moveParams between cards and reuse them instead

so I'd have to refactor those further, especially when they pass down to helpers in SpellAbilityEffect like with discard?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo it would be more clean if the stuff is done in the specific SpellAbilityEffect classes (or a helper function)

cause.getApi() == ApiType.Cloak || cause.getApi() == ApiType.Manifest || cause.getApi() == ApiType.ManifestDread))) {
defPutter = "Owner";
} else {
defPutter = cause.getParamOrDefault("Putter", "You");
}
if ("Owner".equals(defPutter)) {
putter = c.getOwner();
} else {
putter = AbilityUtils.getDefinedPlayers(cause.getHostCard(), defPutter, cause).getFirst();
}

if (lastKnownInfo == null) {
lastKnownInfo = CardCopyService.getLKICopy(c);
}
Expand Down Expand Up @@ -343,6 +361,7 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer
repParams.put(AbilityKey.EffectOnly, true);
repParams.put(AbilityKey.CounterTable, table);
repParams.put(AbilityKey.CounterMap, table.column(copied));
repParams.put(AbilityKey.Putter, putter);
}

if (params != null) {
Expand Down Expand Up @@ -632,6 +651,7 @@ private Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer
runParams.put(AbilityKey.Destination, zoneTo.getZoneType().name());
runParams.put(AbilityKey.IndividualCostPaymentInstance, game.costPaymentStack.peek());
runParams.put(AbilityKey.MergedCards, mergedCards);
runParams.put(AbilityKey.Putter, putter);

if (params != null) {
runParams.putAll(params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ public enum AbilityKey {
Player("Player"),
PreventedAmount("PreventedAmount"),
Produced("Produced"),
Putter("Putter"),
Regeneration("Regeneration"),
ReplacementEffect("ReplacementEffect"),
ReplacementResult("ReplacementResult"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public void resolve(SpellAbility sa) {
}

protected void manifestLoop(SpellAbility sa, Player p, final int amount) {

final Card source = sa.getHostCard();
final Player activator = sa.getActivatingPlayer();
final Game game = source.getGame();
Expand Down
3 changes: 1 addition & 2 deletions forge-game/src/main/java/forge/game/card/CardDamageMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public void triggerExcessDamage(boolean isCombat, Map<Card, Integer> lethalDamag

damaged.getKey().setHasBeenDealtExcessDamageThisTurn(true);
damaged.getKey().logExcessDamage(excess);
// Run triggers

final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put(AbilityKey.DamageTarget, damaged.getKey());
runParams.put(AbilityKey.DamageAmount, excess);
Expand All @@ -158,7 +158,6 @@ public void triggerExcessDamage(boolean isCombat, Map<Card, Integer> lethalDamag
}

if (!damagedList.isEmpty()) {
// Run triggers
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put(AbilityKey.DamageTargets, damagedList);
runParams.put(AbilityKey.IsCombatDamage, isCombat);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (!matchesValidParam("ValidCause", runParams.get(AbilityKey.Cause))) {
return false;
}
if (!matchesValidParam("ValidPutter", runParams.get(AbilityKey.Putter))) {
return false;
}

if (hasParam("Origin")) {
ZoneType zt = (ZoneType) runParams.get(AbilityKey.Origin);
Expand Down Expand Up @@ -113,7 +116,7 @@ public boolean canReplace(Map<AbilityKey, Object> runParams) {
@Override
public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject(AbilityKey.Card, runParams.get(AbilityKey.Affected));
sa.setReplacingObjectsFrom(runParams, AbilityKey.NewCard, AbilityKey.CardLKI, AbilityKey.Cause,
sa.setReplacingObjectsFrom(runParams, AbilityKey.NewCard, AbilityKey.CardLKI, AbilityKey.Cause, AbilityKey.Putter,
AbilityKey.LastStateBattlefield, AbilityKey.LastStateGraveyard, AbilityKey.CounterTable, AbilityKey.CounterMap);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ public final boolean performTest(final Map<AbilityKey, Object> runParams) {
return false;
}

if (!matchesValidParam("ValidPutter", runParams.get(AbilityKey.Putter))) {
return false;
}

if (hasParam("Fizzle")) {
if (!runParams.containsKey(AbilityKey.Fizzle)) {
return false;
Expand Down Expand Up @@ -203,7 +207,7 @@ public final void setTriggeringObjects(final SpellAbility sa, Map<AbilityKey, Ob
sa.setTriggeringObject(AbilityKey.Card, runParams.get(AbilityKey.CardLKI));
sa.setTriggeringObject(AbilityKey.NewCard, runParams.get(AbilityKey.Card));
} else {
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Card, AbilityKey.CardLKI);
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Card, AbilityKey.CardLKI, AbilityKey.Putter);
}
}

Expand Down
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/a/all_hallows_eve.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | IsPresent$ Card.Self+counters_GE1_SCREAM | PresentZone$ Exile | Execute$ TrigRemoveCounter | TriggerZones$ Exile | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is exiled with a scream counter on it, remove a scream counter from it. If there are no more scream counters on it, put it into your graveyard and each player returns all creature cards from their graveyard to the battlefield.
SVar:TrigRemoveCounter:DB$ RemoveCounter | Defined$ Self | CounterType$ SCREAM | CounterNum$ 1 | SubAbility$ DBMoveToGraveyard
SVar:DBMoveToGraveyard:DB$ ChangeZone | Origin$ Exile | Destination$ Graveyard | Defined$ Self | SubAbility$ DBResurrection | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_SCREAM
SVar:DBResurrection:DB$ ChangeZoneAll | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_SCREAM
SVar:DBResurrection:DB$ ChangeZoneAll | Putter$ Owner | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_SCREAM
SVar:IsReanimatorCard:TRUE
SVar:NeedsToPlayVar:CountOpps LECountMe
SVar:CountMe:Count$ValidGraveyard Creature.YouOwn/Minus.NumOpps
Expand Down
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/a/arboria.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Types:World Enchantment
S:Mode$ CantAttack | ValidCard$ Creature | Target$ Player.IsNotRemembered | Description$ Creatures can't attack a player unless that player cast a spell or put a nontoken permanent onto the battlefield during their last turn.
T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Player.Active+IsNotRemembered | Static$ True | Execute$ RememberCaster
SVar:RememberCaster:DB$ Pump | Defined$ TriggeredCardController | RememberObjects$ TriggeredCardController
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.ActivePlayerCtrl+nonToken | Static$ True | Execute$ RememberController
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidPutter$ Player.Active | ValidCard$ Card.nonToken | Static$ True | Execute$ RememberController
SVar:RememberController:DB$ Pump | Defined$ TriggeredCardController | RememberObjects$ TriggeredCardController
T:Mode$ TurnBegin | ValidPlayer$ Player | Execute$ ClearActivePlayer | Static$ True
SVar:ClearActivePlayer:DB$ Cleanup | ForgetDefined$ ActivePlayer
Expand Down
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/a/assassins_trophy.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Name:Assassin's Trophy
ManaCost:B G
Types:Instant
A:SP$ Destroy | ValidTgts$ Permanent.OppCtrl | AITgts$ Permanent.nonLand,Land.nonBasic | TgtPrompt$ Select target permanent an opponent controls | SubAbility$ DBChange | SpellDescription$ Destroy target permanent an opponent controls. Its controller may search their library for a basic land card, put it onto the battlefield, then shuffle.
SVar:DBChange:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.Basic | DefinedPlayer$ TargetedController | ShuffleNonMandatory$ True
SVar:DBChange:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.Basic | DefinedPlayer$ TargetedController | Putter$ Owner | ShuffleNonMandatory$ True
Oracle:Destroy target permanent an opponent controls. Its controller may search their library for a basic land card, put it onto the battlefield, then shuffle.
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/a/avatar_of_growth.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ PT:4/4
K:Trample
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ Trample
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSearch | TriggerDescription$ When CARDNAME enters, each player searches their library for up to two basic land cards, puts them onto the battlefield, then shuffles.
SVar:TrigSearch:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.Basic | DefinedPlayer$ Player | ChangeNum$ 2 | Shuffle$ True
SVar:TrigSearch:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.Basic | DefinedPlayer$ Player | Putter$ Owner | ChangeNum$ 2 | Shuffle$ True
SVar:X:PlayerCountOpponents$Amount
Oracle:This spell costs {1} less to cast for each opponent you have.\nTrample\nWhen Avatar of Growth enters, each player searches their library for up to two basic land cards, puts them onto the battlefield, then shuffles.
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/b/balthor_the_defiled.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ ManaCost:2 B B
Types:Legendary Creature Zombie Dwarf
PT:2/2
S:Mode$ Continuous | Affected$ Creature.Minion | AddPower$ 1 | AddToughness$ 1 | Description$ Minion creatures get +1/+1.
A:AB$ ChangeZoneAll | Cost$ B B B Exile<1/CARDNAME> | ChangeType$ Creature.Black,Creature.Red | Origin$ Graveyard | Destination$ Battlefield | SpellDescription$ Each player returns all black and all red creature cards from their graveyard to the battlefield.
A:AB$ ChangeZoneAll | Cost$ B B B Exile<1/CARDNAME> | ChangeType$ Creature.Black,Creature.Red | Origin$ Graveyard | Destination$ Battlefield | Putter$ Owner | SpellDescription$ Each player returns all black and all red creature cards from their graveyard to the battlefield.
AI:RemoveDeck:All
Oracle:Minion creatures get +1/+1.\n{B}{B}{B}, Exile Balthor the Defiled: Each player returns all black and all red creature cards from their graveyard to the battlefield.
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/b/blessed_reincarnation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ ManaCost:3 U
Types:Instant
K:Rebound
A:SP$ ChangeZone | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBDig | SpellDescription$ Exile target creature an opponent controls. That player reveals cards from the top of their library until a creature card is revealed. The player puts that card onto the battlefield, then shuffles the rest into their library.
SVar:DBDig:DB$ DigUntil | Defined$ TargetedController | Valid$ Creature | ValidDescription$ creature | FoundDestination$ Battlefield | RevealedDestination$ Library | Shuffle$ True
SVar:DBDig:DB$ DigUntil | Defined$ TargetedController | Valid$ Creature | ValidDescription$ creature | FoundDestination$ Battlefield | RevealedDestination$ Library | Shuffle$ True | Putter$ Owner
AI:RemoveDeck:All
Oracle:Exile target creature an opponent controls. That player reveals cards from the top of their library until a creature card is revealed. The player puts that card onto the battlefield, then shuffles the rest into their library.\nRebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/b/bloodbond_march.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ Name:Bloodbond March
ManaCost:2 B G
Types:Enchantment
T:Mode$ SpellCast | ValidCard$ Creature | TriggerZones$ Battlefield | Execute$ TrigReturn | TriggerDescription$ Whenever a player casts a creature spell, each player returns all cards with the same name as that spell from their graveyard to the battlefield.
SVar:TrigReturn:DB$ ChangeZoneAll | ChangeType$ Triggered.sameName | Origin$ Graveyard | Destination$ Battlefield
SVar:TrigReturn:DB$ ChangeZoneAll | ChangeType$ Triggered.sameName | Origin$ Graveyard | Destination$ Battlefield | Putter$ Owner
AI:RemoveDeck:Random
Oracle:Whenever a player casts a creature spell, each player returns all cards with the same name as that spell from their graveyard to the battlefield.
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/b/boldwyr_heavyweights.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ Types:Creature Giant Warrior
PT:8/8
K:Trample
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChange | TriggerDescription$ When CARDNAME enters, each opponent may search their library for a creature card and put it onto the battlefield. Then each player who searched their library this way shuffles.
SVar:TrigChange:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | ChangeType$ Creature | DefinedPlayer$ Player.Opponent | ChangeNum$ 1 | ShuffleNonMandatory$ True
SVar:TrigChange:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | ChangeType$ Creature | DefinedPlayer$ Player.Opponent | Putter$ Owner | ChangeNum$ 1 | ShuffleNonMandatory$ True
Oracle:Trample\nWhen Boldwyr Heavyweights enters, each opponent may search their library for a creature card and put it onto the battlefield. Then each player who searched their library this way shuffles.
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/b/boseiju_who_endures.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ManaCost:no cost
Types:Legendary Land
A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G}.
A:AB$ Destroy | PrecostDesc$ Channel — | Cost$ 1 G Discard<1/CARDNAME> | ValidTgts$ Artifact.OppCtrl,Enchantment.OppCtrl,Land.nonBasic+OppCtrl | TgtPrompt$ Select target artifact, enchantment, or nonbasic land an opponent controls | SubAbility$ DBChangeZone | ReduceCost$ X | ActivationZone$ Hand | SpellDescription$ Destroy target artifact, enchantment, or nonbasic land an opponent controls. That player may search their library for a land card with a basic land type, put it onto the battlefield, then shuffle. This ability costs {1} less to activate for each legendary creature you control.
SVar:DBChangeZone:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.hasABasicLandType | ChangeNum$ 1 | DefinedPlayer$ TargetedController | ShuffleNonMandatory$ True
SVar:DBChangeZone:DB$ ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.hasABasicLandType | ChangeNum$ 1 | DefinedPlayer$ TargetedController | Putter$ Owner | ShuffleNonMandatory$ True
SVar:X:Count$Valid Creature.Legendary+YouCtrl
DeckHints:Type$Legendary
DeckHas:Ability$Discard
Expand Down
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/b/braids_conjurer_adept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ ManaCost:2 U U
Types:Legendary Creature Human Wizard
PT:2/2
T:Mode$ Phase | Phase$ Upkeep | TriggerZones$ Battlefield | Execute$ TrigChangeZone | TriggerDescription$ At the beginning of each player's upkeep, that player may put an artifact, creature, or land card from their hand onto the battlefield.
SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature,Artifact,Land | DefinedPlayer$ TriggeredPlayer | ChangeNum$ 1
SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature,Artifact,Land | DefinedPlayer$ TriggeredPlayer | Putter$ Owner | ChangeNum$ 1
AI:RemoveDeck:Random
Oracle:At the beginning of each player's upkeep, that player may put an artifact, creature, or land card from their hand onto the battlefield.
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/b/bringer_of_the_last_gift.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ PT:6/6
K:Flying
T:Mode$ ChangesZone | ValidCard$ Card.Self+wasCastByYou | Destination$ Battlefield | Execute$ TrigSacAll | TriggerDescription$ When CARDNAME enters, if you cast it, each player sacrifices all other creatures they control. Then each player returns all creature cards from their graveyard that weren't put there this way to the battlefield.
SVar:TrigSacAll:DB$ SacrificeAll | ValidCards$ Creature.StrictlyOther | RememberSacrificed$ True | SubAbility$ DBReturnAll
SVar:DBReturnAll:DB$ ChangeZoneAll | ChangeType$ Creature.IsNotRemembered | Origin$ Graveyard | Destination$ Battlefield | SubAbility$ DBCleanup
SVar:DBReturnAll:DB$ ChangeZoneAll | ChangeType$ Creature.IsNotRemembered | Origin$ Graveyard | Destination$ Battlefield | Putter$ Owner | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
DeckHas:Ability$Graveyard|Sacrifice
DeckHints:Ability$Graveyard|Discard|Mill
Expand Down
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/c/chaos_mutation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ManaCost:3 U R
Types:Instant
A:SP$ ChangeZone | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Creature | TgtPrompt$ Select any number of target creatures controlled by different players | TargetMin$ 0 | TargetMax$ MaxTgt | TargetsWithDifferentControllers$ True | SubAbility$ DBRepeatEach | RememberLKI$ True | SpellDescription$ Exile any number of target creatures controlled by different players.
SVar:DBRepeatEach:DB$ RepeatEach | DefinedCards$ DirectRemembered | Zone$ Exile | UseImprinted$ True | RepeatSubAbility$ DBDig | SubAbility$ DBCleanup | SpellDescription$ For each creature exiled this way, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then puts the rest on the bottom of their library in a random order.
SVar:DBDig:DB$ DigUntil | Defined$ ImprintedController | Amount$ 1 | Valid$ Creature | ValidDescription$ creature | FoundDestination$ Battlefield | RevealedDestination$ Library | RevealedLibraryPosition$ -1 | RevealRandomOrder$ True
SVar:DBDig:DB$ DigUntil | Defined$ ImprintedController | Amount$ 1 | Valid$ Creature | ValidDescription$ creature | FoundDestination$ Battlefield | RevealedDestination$ Library | RevealedLibraryPosition$ -1 | RevealRandomOrder$ True | Putter$ Owner
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:MaxTgt:PlayerCountPlayers$Amount
Oracle:Exile any number of target creatures controlled by different players. For each creature exiled this way, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then puts the rest on the bottom of their library in a random order.
2 changes: 1 addition & 1 deletion forge-gui/res/cardsfolder/c/chaos_warp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Name:Chaos Warp
ManaCost:2 R
Types:Instant
A:SP$ ChangeZone | Origin$ Battlefield | Destination$ Library | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | SubAbility$ DBDig | Shuffle$ True | SpellDescription$ The owner of target permanent shuffles it into their library, then reveals the top card of their library. If it's a permanent card, they put it onto the battlefield.
SVar:DBDig:DB$ Dig | Defined$ TargetedOwner | DigNum$ 1 | Reveal$ True | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition2$ 0 | ChangeNum$ All | ChangeValid$ Permanent
SVar:DBDig:DB$ Dig | Defined$ TargetedOwner | DigNum$ 1 | Reveal$ True | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition2$ 0 | ChangeNum$ All | ChangeValid$ Permanent | Putter$ Owner
Oracle:The owner of target permanent shuffles it into their library, then reveals the top card of their library. If it's a permanent card, they put it onto the battlefield.
Loading
Loading