mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
rework warp implementation (#13874)
This commit is contained in:
parent
8aafba38b9
commit
cdf23ac18a
3 changed files with 57 additions and 22 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
package mage.cards.f;
|
package mage.cards.f;
|
||||||
|
|
||||||
import mage.MageObjectReference;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
|
|
@ -17,7 +16,6 @@ import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetControlledCreaturePermanent;
|
import mage.target.common.TargetControlledCreaturePermanent;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -63,11 +61,7 @@ class FullBoreEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (permanent == null
|
if (permanent == null || !WarpAbility.checkIfPermanentWarped(permanent, game)) {
|
||||||
|| !game
|
|
||||||
.getPermanentCostsTags()
|
|
||||||
.getOrDefault(new MageObjectReference(permanent, game, -1), Collections.emptyMap())
|
|
||||||
.containsKey(WarpAbility.WARP_ACTIVATION_VALUE_KEY)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
game.addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance())
|
game.addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance())
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
import mage.MageIdentifier;
|
import mage.MageIdentifier;
|
||||||
|
import mage.MageObjectReference;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||||
|
|
@ -10,14 +11,33 @@ import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
import mage.watchers.Watcher;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 702.185. Warp
|
||||||
|
* <p>
|
||||||
|
* 702.185a Warp represents two static abilities that function while the card with warp is on the stack,
|
||||||
|
* one of which may create a delayed triggered ability. “Warp [cost]” means
|
||||||
|
* “You may cast this card from your hand by paying [cost] rather than its mana cost” and
|
||||||
|
* “If this spell’s warp cost was paid, exile the permanent this spell becomes at the beginning of the next end step.
|
||||||
|
* Its owner may cast this card after the current turn has ended for as long as it remains exiled.”
|
||||||
|
* Casting a spell for its warp cost follows the rules for paying alternative costs in rules 601.2b and 601.2f–h.
|
||||||
|
* <p>
|
||||||
|
* 702.185b Some effects refer to “warped” cards in exile. A warped card in exile is one
|
||||||
|
* that was exiled by the delayed triggered ability created by a warp ability.
|
||||||
|
* <p>
|
||||||
|
* 702.185c Some effects refer to whether “a spell was warped this turn.”
|
||||||
|
* This means that a spell was cast for its warp cost this turn.
|
||||||
|
*
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
*/
|
*/
|
||||||
public class WarpAbility extends SpellAbility {
|
public class WarpAbility extends SpellAbility {
|
||||||
|
|
@ -41,6 +61,7 @@ public class WarpAbility extends SpellAbility {
|
||||||
this.addCost(new ManaCostsImpl<>(manaString));
|
this.addCost(new ManaCostsImpl<>(manaString));
|
||||||
this.setAdditionalCostsRuleVisible(false);
|
this.setAdditionalCostsRuleVisible(false);
|
||||||
this.allowGraveyard = allowGraveyard;
|
this.allowGraveyard = allowGraveyard;
|
||||||
|
this.addWatcher(new WarpAbilityWatcher());
|
||||||
}
|
}
|
||||||
|
|
||||||
private WarpAbility(final WarpAbility ability) {
|
private WarpAbility(final WarpAbility ability) {
|
||||||
|
|
@ -48,15 +69,6 @@ public class WarpAbility extends SpellAbility {
|
||||||
this.allowGraveyard = ability.allowGraveyard;
|
this.allowGraveyard = ability.allowGraveyard;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The ability sets up a delayed trigger which can't be set up using the cost tag system
|
|
||||||
public static void addDelayedTrigger(SpellAbility spellAbility, Game game) {
|
|
||||||
if (spellAbility instanceof WarpAbility) {
|
|
||||||
game.addDelayedTriggeredAbility(
|
|
||||||
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new WarpExileEffect()), spellAbility
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActivationStatus canActivate(UUID playerId, Game game) {
|
public ActivationStatus canActivate(UUID playerId, Game game) {
|
||||||
switch (game.getState().getZone(getSourceId())) {
|
switch (game.getState().getZone(getSourceId())) {
|
||||||
|
|
@ -104,6 +116,13 @@ public class WarpAbility extends SpellAbility {
|
||||||
public static String makeWarpString(UUID playerId) {
|
public static String makeWarpString(UUID playerId) {
|
||||||
return playerId + "- Warped";
|
return playerId + "- Warped";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean checkIfPermanentWarped(Permanent permanent, Game game) {
|
||||||
|
return permanent != null
|
||||||
|
&& game.getPermanentCostsTags()
|
||||||
|
.getOrDefault(new MageObjectReference(permanent, game, -1), Collections.emptyMap())
|
||||||
|
.containsKey(WarpAbility.WARP_ACTIVATION_VALUE_KEY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WarpExileEffect extends OneShotEffect {
|
class WarpExileEffect extends OneShotEffect {
|
||||||
|
|
@ -122,8 +141,9 @@ class WarpExileEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WarpExileEffect() {
|
WarpExileEffect(Permanent permanent, Game game) {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
|
this.setTargetPointer(new FixedTarget(permanent, game));
|
||||||
staticText = "exile this creature if it was cast for its warp cost";
|
staticText = "exile this creature if it was cast for its warp cost";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,9 +158,12 @@ class WarpExileEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
if (permanent == null) {
|
||||||
if (permanent == null || permanent.getZoneChangeCounter(game) != source.getSourceObjectZoneChangeCounter() + 1) {
|
return false;
|
||||||
|
}
|
||||||
|
Player player = game.getPlayer(permanent.getOwnerId());
|
||||||
|
if (player == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
player.moveCardsToExile(
|
player.moveCardsToExile(
|
||||||
|
|
@ -155,3 +178,23 @@ class WarpExileEffect extends OneShotEffect {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WarpAbilityWatcher extends Watcher {
|
||||||
|
|
||||||
|
WarpAbilityWatcher() {
|
||||||
|
super(WatcherScope.GAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void watch(GameEvent event, Game game) {
|
||||||
|
if (event.getType() != GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||||
|
if (WarpAbility.checkIfPermanentWarped(permanent, game)) {
|
||||||
|
game.addDelayedTriggeredAbility(
|
||||||
|
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new WarpExileEffect(permanent, game)), permanent.getSpellAbility()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import mage.abilities.costs.mana.ManaCosts;
|
||||||
import mage.abilities.keyword.BestowAbility;
|
import mage.abilities.keyword.BestowAbility;
|
||||||
import mage.abilities.keyword.PrototypeAbility;
|
import mage.abilities.keyword.PrototypeAbility;
|
||||||
import mage.abilities.keyword.TransformAbility;
|
import mage.abilities.keyword.TransformAbility;
|
||||||
import mage.abilities.keyword.WarpAbility;
|
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.counters.Counter;
|
import mage.counters.Counter;
|
||||||
|
|
@ -422,7 +421,6 @@ public class Spell extends StackObjectImpl implements Card {
|
||||||
} else {
|
} else {
|
||||||
MageObjectReference mor = new MageObjectReference(getSpellAbility());
|
MageObjectReference mor = new MageObjectReference(getSpellAbility());
|
||||||
game.storePermanentCostsTags(mor, getSpellAbility());
|
game.storePermanentCostsTags(mor, getSpellAbility());
|
||||||
WarpAbility.addDelayedTrigger(getSpellAbility(), game);
|
|
||||||
return controller.moveCards(card, Zone.BATTLEFIELD, ability, game, false, faceDown, false, null);
|
return controller.moveCards(card, Zone.BATTLEFIELD, ability, game, false, faceDown, false, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue