mirror of
https://github.com/magefree/mage.git
synced 2026-01-19 01:39:58 -08:00
a few card rewrites
This commit is contained in:
parent
63ab41d8da
commit
7c0d7105ee
5 changed files with 100 additions and 162 deletions
|
|
@ -1,36 +1,37 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ReturnFromExileForSourceEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterNonlandPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.util.CardUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class DetentionSphere extends CardImpl {
|
||||
|
||||
static final protected FilterPermanent filter = new FilterNonlandPermanent("nonland permanent not named Detention Sphere");
|
||||
private static final FilterPermanent filter = new FilterNonlandPermanent("nonland permanent not named Detention Sphere");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(new NamePredicate("Detention Sphere")));
|
||||
|
|
@ -48,7 +49,7 @@ public final class DetentionSphere extends CardImpl {
|
|||
|
||||
// When Detention Sphere leaves the battlefield, return the exiled
|
||||
// cards to the battlefield under their owner's control.
|
||||
this.addAbility(new LeavesBattlefieldTriggeredAbility(new DetentionSphereLeavesEffect(), false));
|
||||
this.addAbility(new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false));
|
||||
}
|
||||
|
||||
private DetentionSphere(final DetentionSphere card) {
|
||||
|
|
@ -65,7 +66,8 @@ class DetentionSphereEntersEffect extends OneShotEffect {
|
|||
|
||||
DetentionSphereEntersEffect() {
|
||||
super(Outcome.Exile);
|
||||
staticText = "you may exile target nonland permanent not named Detention Sphere and all other permanents with the same name as that permanent";
|
||||
staticText = "exile target nonland permanent not named Detention Sphere " +
|
||||
"and all other permanents with the same name as that permanent";
|
||||
}
|
||||
|
||||
private DetentionSphereEntersEffect(final DetentionSphereEntersEffect effect) {
|
||||
|
|
@ -74,25 +76,23 @@ class DetentionSphereEntersEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = game.getObject(source);
|
||||
if (sourceObject != null && exileId != null && targetPermanent != null && controller != null) {
|
||||
|
||||
if (CardUtil.haveEmptyName(targetPermanent)) { // face down creature
|
||||
controller.moveCardToExileWithInfo(targetPermanent, exileId, sourceObject.getIdName(), source, game, Zone.BATTLEFIELD, true);
|
||||
} else {
|
||||
String name = targetPermanent.getName();
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
|
||||
if (permanent != null && CardUtil.haveSameNames(permanent, name, game)) {
|
||||
controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source, game, Zone.BATTLEFIELD, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (player == null || permanent == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Set<Card> permanents = game
|
||||
.getBattlefield()
|
||||
.getActivePermanents(StaticFilters.FILTER_PERMANENT, source.getControllerId(), source, game)
|
||||
.stream()
|
||||
.filter(p -> p.sharesName(permanent, game))
|
||||
.collect(Collectors.toSet());
|
||||
permanents.add(permanent);
|
||||
return player.moveCardsToExile(
|
||||
permanents, source, game, true,
|
||||
CardUtil.getExileZoneId(game, source),
|
||||
CardUtil.getSourceName(game, source)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -100,39 +100,3 @@ class DetentionSphereEntersEffect extends OneShotEffect {
|
|||
return new DetentionSphereEntersEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DetentionSphereLeavesEffect extends OneShotEffect {
|
||||
|
||||
DetentionSphereLeavesEffect() {
|
||||
super(Outcome.Neutral);
|
||||
staticText = "return the exiled cards to the battlefield under their owner's control";
|
||||
}
|
||||
|
||||
private DetentionSphereLeavesEffect(final DetentionSphereLeavesEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (sourceObject != null && controller != null) {
|
||||
Permanent permanentLeftBattlefield = (Permanent) getValue("permanentLeftBattlefield");
|
||||
if (permanentLeftBattlefield == null) {
|
||||
Logger.getLogger(ReturnFromExileForSourceEffect.class).error("Permanent not found: " + sourceObject.getName());
|
||||
return false;
|
||||
}
|
||||
ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), permanentLeftBattlefield.getZoneChangeCounter(game)));
|
||||
if (exile != null) {
|
||||
controller.moveCards(exile.getCards(game), Zone.BATTLEFIELD, source, game, false, false, true, null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetentionSphereLeavesEffect copy() {
|
||||
return new DetentionSphereLeavesEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,18 +200,7 @@ class GrimoireThiefCounterspellEffect extends OneShotEffect {
|
|||
for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext(); ) {
|
||||
StackObject stackObject = iterator.next();
|
||||
MageObject mageObject = game.getObject(card.getId());
|
||||
String name1;
|
||||
String name2;
|
||||
if (mageObject instanceof SplitCard) {
|
||||
name1 = ((SplitCard) mageObject).getLeftHalfCard().getName();
|
||||
name2 = ((SplitCard) mageObject).getRightHalfCard().getName();
|
||||
} else {
|
||||
// modal double faces cards, adventure cards -- all have one name in non stack/battlefield zone
|
||||
name1 = mageObject.getName();
|
||||
name2 = name1;
|
||||
}
|
||||
|
||||
if (CardUtil.haveSameNames(stackObject, name1, game) || CardUtil.haveSameNames(stackObject, name2, game)) {
|
||||
if (stackObject.sharesName(mageObject, game)) {
|
||||
Spell spell = (Spell) stackObject;
|
||||
game.getStack().counter(stackObject.getId(), source, game);
|
||||
game.informPlayers(sourceObject.getLogName() + ": spell " + spell.getIdName() + " was countered.");
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ import mage.game.events.GameEvent;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -59,7 +57,8 @@ class ReflectorMageEffect extends OneShotEffect {
|
|||
|
||||
ReflectorMageEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "return target creature an opponent controls to its owner's hand. That creature's owner can't cast spells with the same name as that creature until your next turn";
|
||||
this.staticText = "return target creature an opponent controls to its owner's hand. " +
|
||||
"That creature's owner can't cast spells with the same name as that creature until your next turn";
|
||||
}
|
||||
|
||||
private ReflectorMageEffect(final ReflectorMageEffect effect) {
|
||||
|
|
@ -74,35 +73,31 @@ class ReflectorMageEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (targetCreature != null) {
|
||||
controller.moveCards(targetCreature, Zone.HAND, source, game);
|
||||
if (!CardUtil.haveEmptyName(targetCreature)) { // if the creature had no name, no restrict effect will be created
|
||||
game.addEffect(new ExclusionRitualReplacementEffect(targetCreature.getName(), targetCreature.getOwnerId()), source);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (controller == null || targetCreature == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
controller.moveCards(targetCreature, Zone.HAND, source, game);
|
||||
game.addEffect(new ReflectorMageReplacementEffect(targetCreature, targetCreature.getOwnerId()), source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
class ReflectorMageReplacementEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
private final String creatureName;
|
||||
private final Permanent creature;
|
||||
private final UUID ownerId;
|
||||
|
||||
ExclusionRitualReplacementEffect(String creatureName, UUID ownerId) {
|
||||
ReflectorMageReplacementEffect(Permanent creature, UUID ownerId) {
|
||||
super(Duration.UntilYourNextTurn, Outcome.Detriment);
|
||||
staticText = "That creature's owner can't cast spells with the same name as that creature until your next turn";
|
||||
this.creatureName = creatureName;
|
||||
this.creature = creature.copy();
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
private ExclusionRitualReplacementEffect(final ExclusionRitualReplacementEffect effect) {
|
||||
private ReflectorMageReplacementEffect(final ReflectorMageReplacementEffect effect) {
|
||||
super(effect);
|
||||
this.creatureName = effect.creatureName;
|
||||
this.creature = effect.creature.copy();
|
||||
this.ownerId = effect.ownerId;
|
||||
}
|
||||
|
||||
|
|
@ -114,18 +109,12 @@ class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl
|
|||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
SpellAbility spellAbility = SpellAbility.getSpellAbilityFromEvent(event, game);
|
||||
if (spellAbility == null) {
|
||||
return false;
|
||||
}
|
||||
Card card = spellAbility.getCharacteristics(game);
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
return CardUtil.haveSameNames(card, creatureName, game) && Objects.equals(ownerId, card.getOwnerId());
|
||||
return spellAbility != null && card != null && card.isOwnedBy(ownerId) && card.sharesName(creature, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExclusionRitualReplacementEffect copy() {
|
||||
return new ExclusionRitualReplacementEffect(this);
|
||||
public ReflectorMageReplacementEffect copy() {
|
||||
return new ReflectorMageReplacementEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,30 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.PlayCardTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.turn.TurnMod;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
|
@ -37,7 +39,6 @@ public final class SearchTheCity extends CardImpl {
|
|||
|
||||
// Whenever you play a card with the same name as one of the exiled cards, you may put one of those cards with that name into its owner's hand. Then if there are no cards exiled with Search the City, sacrifice it. If you do, take an extra turn after this one.
|
||||
this.addAbility(new SearchTheCityTriggeredAbility());
|
||||
|
||||
}
|
||||
|
||||
private SearchTheCity(final SearchTheCity card) {
|
||||
|
|
@ -64,17 +65,10 @@ class SearchTheCityExileEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
// move cards from library to exile
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (player.getLibrary().hasCards()) {
|
||||
Card topCard = player.getLibrary().getFromTop(game);
|
||||
topCard.moveToExile(source.getSourceId(), "Cards exiled by Search the City", source, game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return player != null && player.moveCardsToExile(
|
||||
player.getLibrary().getTopCards(game, 5), source, game, true,
|
||||
CardUtil.getExileZoneId(game, source), CardUtil.getSourceName(game, source)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -86,8 +80,8 @@ class SearchTheCityExileEffect extends OneShotEffect {
|
|||
class SearchTheCityTriggeredAbility extends PlayCardTriggeredAbility {
|
||||
|
||||
public SearchTheCityTriggeredAbility() {
|
||||
super(TargetController.YOU, Zone.BATTLEFIELD, new SearchTheCityExiledCardToHandEffect(), true);
|
||||
setTriggerPhrase("Whenever you play a card with the same name as one of the exiled cards, " );
|
||||
super(TargetController.YOU, Zone.BATTLEFIELD, new SearchTheCityExiledCardToHandEffect());
|
||||
setTriggerPhrase("Whenever you play a card with the same name as one of the exiled cards, ");
|
||||
}
|
||||
|
||||
private SearchTheCityTriggeredAbility(final SearchTheCityTriggeredAbility ability) {
|
||||
|
|
@ -99,30 +93,33 @@ class SearchTheCityTriggeredAbility extends PlayCardTriggeredAbility {
|
|||
if (!super.checkTrigger(event, game)) {
|
||||
return false;
|
||||
}
|
||||
String cardName = "";
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (spell != null) {
|
||||
cardName = spell.getName();
|
||||
}
|
||||
MageObject object;
|
||||
switch (event.getType()) {
|
||||
case SPELL_CAST:
|
||||
object = game.getStack().getSpell(event.getTargetId());
|
||||
break;
|
||||
case LAND_PLAYED:
|
||||
object = game.getCard(event.getTargetId());
|
||||
break;
|
||||
default:
|
||||
object = null;
|
||||
}
|
||||
if (event.getType() == GameEvent.EventType.LAND_PLAYED) {
|
||||
Card card = game.getCard(event.getTargetId());
|
||||
if (card != null) {
|
||||
cardName = card.getName();
|
||||
}
|
||||
}
|
||||
if (cardName.isEmpty()) {
|
||||
if (object == null) {
|
||||
return false;
|
||||
}
|
||||
ExileZone searchTheCityExileZone = game.getExile().getExileZone(this.getSourceId());
|
||||
FilterCard filter = new FilterCard();
|
||||
filter.add(new NamePredicate(cardName));
|
||||
|
||||
if (searchTheCityExileZone.count(filter, game) == 0) {
|
||||
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, this));
|
||||
if (exileZone == null || exileZone.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().get(0).setValue("cardName", cardName);
|
||||
Set<Card> cards = exileZone
|
||||
.getCards(game)
|
||||
.stream()
|
||||
.filter(card -> card.sharesName(object, game))
|
||||
.collect(Collectors.toSet());
|
||||
if (cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().setTargetPointer(new FixedTargets(cards, game));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +133,8 @@ class SearchTheCityExiledCardToHandEffect extends OneShotEffect {
|
|||
|
||||
SearchTheCityExiledCardToHandEffect() {
|
||||
super(Outcome.DrawCard);
|
||||
staticText = "you may put one of those cards with that name into its owner's hand. Then if there are no cards exiled with {this}, sacrifice it. If you do, take an extra turn after this one";
|
||||
staticText = "you may put one of those cards with that name into its owner's hand. Then if there are " +
|
||||
"no cards exiled with {this}, sacrifice it. If you do, take an extra turn after this one";
|
||||
}
|
||||
|
||||
private SearchTheCityExiledCardToHandEffect(final SearchTheCityExiledCardToHandEffect effect) {
|
||||
|
|
@ -145,33 +143,27 @@ class SearchTheCityExiledCardToHandEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
String cardName = (String) this.getValue("cardName");
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
ExileZone searchTheCityExileZone = game.getExile().getExileZone(source.getSourceId());
|
||||
if (cardName != null
|
||||
&& searchTheCityExileZone != null) {
|
||||
for (Card card : searchTheCityExileZone.getCards(game)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
if (controller.moveCards(card, Zone.HAND, source, game)) {
|
||||
game.informPlayers("Search the City: put " + card.getName() + " into owner's hand");
|
||||
}
|
||||
searchTheCityExileZone.remove(card);
|
||||
if (searchTheCityExileZone.isEmpty()) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
permanent.sacrifice(source, game);
|
||||
// extra turn
|
||||
game.getState().getTurnMods().add(new TurnMod(source.getControllerId()).withExtraTurn());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Cards cards = new CardsImpl(getTargetPointer().getTargets(game, source));
|
||||
cards.retainZone(Zone.EXILED, game);
|
||||
TargetCard target = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD);
|
||||
controller.choose(outcome, cards, target, source, game);
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
controller.moveCards(card, Zone.HAND, source, game);
|
||||
}
|
||||
return false;
|
||||
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source));
|
||||
if (exileZone != null && !exileZone.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (sourcePermanent != null && sourcePermanent.sacrifice(source, game)) {
|
||||
game.getState().getTurnMods().add(new TurnMod(source.getControllerId()).withExtraTurn());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -776,6 +776,10 @@ public final class CardUtil {
|
|||
return object1 != null && object2 != null && haveSameNames(object1.getName(), object2.getName(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaced by hasName method, kept to reduce refactoring of old cards
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean haveSameNames(MageObject object, String needName, Game game) {
|
||||
return object.hasName(needName, game);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue