Reworked some cards with a name a card effect to use a common effect.

This commit is contained in:
LevelX2 2014-09-19 13:39:15 +02:00
parent a57ebc5314
commit 078d6fb3c6
11 changed files with 294 additions and 302 deletions

View file

@ -40,6 +40,7 @@ import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.NameACardEffect;
import mage.cards.CardImpl;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
@ -69,7 +70,7 @@ public class MeddlingMage extends CardImpl {
this.toughness = new MageInt(2);
// As Meddling Mage enters the battlefield, name a nonland card.
this.addAbility(new AsEntersBattlefieldAbility(new MeddlingMageChooseCardEffect()));
this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME)));
//The named card can't be cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MeddlingMageReplacementEffect()));
@ -85,46 +86,6 @@ public class MeddlingMage extends CardImpl {
}
}
class MeddlingMageChooseCardEffect extends OneShotEffect {
public MeddlingMageChooseCardEffect() {
super(Outcome.Detriment);
staticText = "name a nonland card";
}
public MeddlingMageChooseCardEffect(final MeddlingMageChooseCardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (controller != null && permanent != null) {
Choice cardChoice = new ChoiceImpl();
cardChoice.setChoices(CardRepository.instance.getNonLandNames());
cardChoice.clearChoice();
while (!controller.choose(Outcome.Detriment, cardChoice, game)) {
if (!controller.isInGame()) {
return false;
}
}
String cardName = cardChoice.getChoice();
game.informPlayers(permanent.getLogName() + ", named card: [" + cardName + "]");
game.getState().setValue(source.getSourceId().toString(), cardName);
permanent.addInfo("named card", CardUtil.addToolTipMarkTags("Named card: [" + cardName +"]"));
return true;
}
return false;
}
@Override
public MeddlingMageChooseCardEffect copy() {
return new MeddlingMageChooseCardEffect(this);
}
}
class MeddlingMageReplacementEffect extends ContinuousRuleModifiyingEffectImpl {
public MeddlingMageReplacementEffect() {
@ -159,7 +120,7 @@ class MeddlingMageReplacementEffect extends ContinuousRuleModifiyingEffectImpl {
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.CAST_SPELL) {
MageObject object = game.getObject(event.getSourceId());
if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString()))) {
if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) {
return true;
}
}

View file

@ -28,16 +28,16 @@
package mage.sets.alarareborn;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.NameACardEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
@ -57,6 +57,7 @@ public class ThoughtHemorrhage extends CardImpl {
// Name a nonland card. Target player reveals his or her hand. Thought Hemorrhage deals 3 damage to that player for each card with that name revealed this way. Search that player's graveyard, hand, and library for all cards with that name and exile them. Then that player shuffles his or her library.
this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME));
this.getSpellAbility().addEffect(new ThoughtHemorrhageEffect());
}
@ -72,8 +73,7 @@ public class ThoughtHemorrhage extends CardImpl {
class ThoughtHemorrhageEffect extends OneShotEffect {
String cardName;
final String rule = "Name a nonland card. Target player reveals his or her hand. Thought Hemorrhage deals 3 damage to that player for each card with that name revealed this way. Search that player's graveyard, hand, and library for all cards with that name and exile them. Then that player shuffles his or her library";
final String rule = "Target player reveals his or her hand. {this} deals 3 damage to that player for each card with that name revealed this way. Search that player's graveyard, hand, and library for all cards with that name and exile them. Then that player shuffles his or her library";
public ThoughtHemorrhageEffect() {
super(Outcome.Detriment);
@ -86,44 +86,40 @@ class ThoughtHemorrhageEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player you = game.getPlayer(source.getControllerId());
if (you != null) {
Choice cardChoice = new ChoiceImpl();
cardChoice.setChoices(CardRepository.instance.getNonLandNames());
cardChoice.clearChoice();
while (!you.choose(Outcome.Detriment, cardChoice, game)) {
if (!you.isInGame()) {
return false;
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
if (sourceObject != null && controller != null && cardName != null && !cardName.isEmpty()) {
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (targetPlayer != null) {
targetPlayer.revealCards("hand of " + targetPlayer.getName(), targetPlayer.getHand(), game);
int cardsFound = 0;
for (Card card : targetPlayer.getHand().getCards(game)) {
if (card.getName().equals(cardName)) {
cardsFound++;
}
}
}
cardName = cardChoice.getChoice();
game.informPlayers("Thought Hemorrhage, named card: [" + cardName + "]");
}
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (targetPlayer != null) {
targetPlayer.revealCards("hand of target player", targetPlayer.getHand(), game);
for (Card card : targetPlayer.getHand().getCards(game)) {
if (card.getName().equals(cardName)) {
targetPlayer.damage(3, source.getSourceId(), game, false, true);
if (cardsFound > 0) {
targetPlayer.damage(3 * cardsFound, source.getSourceId(), game, false, true);
}
}
for (Card card : targetPlayer.getGraveyard().getCards(game)) {
if (card.getName().equals(cardName)) {
card.moveToExile(null, "", source.getSourceId(), game);
for (Card card : targetPlayer.getGraveyard().getCards(game)) {
if (card.getName().equals(cardName)) {
controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.GRAVEYARD);
}
}
}
for (Card card : targetPlayer.getHand().getCards(game)) {
if (card.getName().equals(cardName)) {
card.moveToExile(null, "", source.getSourceId(), game);
for (Card card : targetPlayer.getHand().getCards(game)) {
if (card.getName().equals(cardName)) {
controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.HAND);
}
}
}
for (Card card : targetPlayer.getLibrary().getCards(game)) {
if (card.getName().equals(cardName)) {
card.moveToExile(null, "", source.getSourceId(), game);
for (Card card : targetPlayer.getLibrary().getCards(game)) {
if (card.getName().equals(cardName)) {
controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.LIBRARY);
}
}
targetPlayer.shuffleLibrary(game);
return true;
}
targetPlayer.shuffleLibrary(game);
return true;
}
return false;
}

View file

@ -43,6 +43,7 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.NameACardEffect;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
@ -76,7 +77,7 @@ public class CouncilOfTheAbsolute extends CardImpl {
this.toughness = new MageInt(4);
// As Council of the Absolute enters the battlefield, name a card other than a creature or a land card.
this.addAbility(new AsEntersBattlefieldAbility(new CouncilOfTheAbsoluteChooseCardEffect()));
this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_AND_NON_CREATURE_NAME)));
// Your opponents can't cast the chosen card.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CouncilOfTheAbsoluteReplacementEffect()));
// Spells with the chosen name cost 2 less for you to cast.
@ -96,46 +97,6 @@ public class CouncilOfTheAbsolute extends CardImpl {
}
class CouncilOfTheAbsoluteChooseCardEffect extends OneShotEffect {
public CouncilOfTheAbsoluteChooseCardEffect() {
super(Outcome.Detriment);
staticText = "name a card other than a creature or a land card";
}
public CouncilOfTheAbsoluteChooseCardEffect(final CouncilOfTheAbsoluteChooseCardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (controller != null && permanent != null) {
Choice cardChoice = new ChoiceImpl();
cardChoice.setChoices(CardRepository.instance.getNonLandAndNonCreatureNames());
cardChoice.clearChoice();
while (!controller.choose(Outcome.Detriment, cardChoice, game)) {
if (!controller.isInGame()) {
return false;
}
}
String cardName = cardChoice.getChoice();
game.informPlayers(permanent.getLogName() + ", named card: [" + cardName + "]");
game.getState().setValue(source.getSourceId().toString(), cardName);
permanent.addInfo("named card", CardUtil.addToolTipMarkTags("Named card: [" + cardName +"]"));
return true;
}
return false;
}
@Override
public CouncilOfTheAbsoluteChooseCardEffect copy() {
return new CouncilOfTheAbsoluteChooseCardEffect(this);
}
}
class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifiyingEffectImpl {
public CouncilOfTheAbsoluteReplacementEffect() {
@ -170,7 +131,7 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifiyingEffe
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.CAST_SPELL && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
MageObject object = game.getObject(event.getSourceId());
if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString()))) {
if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) {
return true;
}
}
@ -200,7 +161,7 @@ class CouncilOfTheAbsoluteCostReductionEffect extends CostModificationEffectImpl
if ((abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility)
&& abilityToModify.getControllerId().equals(source.getControllerId())) {
Card card = game.getCard(abilityToModify.getSourceId());
return card.getName().equals(game.getState().getValue(source.getSourceId().toString()));
return card.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY));
}
return false;
}

View file

@ -28,19 +28,17 @@
package mage.sets.mirrodin;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.NameACardEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
@ -58,6 +56,7 @@ public class SpoilsOfTheVault extends CardImpl {
this.color.setBlack(true);
// Name a card. Reveal cards from the top of your library until you reveal the named card, then put that card into your hand. Exile all other cards revealed this way, and you lose 1 life for each of the exiled cards.
this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.ALL));
this.getSpellAbility().addEffect(new SpoilsOfTheVaultEffect());
}
@ -76,7 +75,7 @@ class SpoilsOfTheVaultEffect extends OneShotEffect {
public SpoilsOfTheVaultEffect() {
super(Outcome.Damage);
this.staticText = "Name a card. Reveal cards from the top of your library until you reveal the named card, then put that card into your hand. Exile all other cards revealed this way, and you lose 1 life for each of the exiled cards";
this.staticText = "Reveal cards from the top of your library until you reveal the named card, then put that card into your hand. Exile all other cards revealed this way, and you lose 1 life for each of the exiled cards";
}
public SpoilsOfTheVaultEffect(final SpoilsOfTheVaultEffect effect) {
@ -90,40 +89,24 @@ class SpoilsOfTheVaultEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
String cardName;
MageObject sourceObject = game.getObject(source.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
if (sourceObject == null || controller == null || cardName == null || cardName.isEmpty()) {
return false;
}
else{
Choice cardChoice = new ChoiceImpl();
cardChoice.setChoices(CardRepository.instance.getNames());
cardChoice.clearChoice();
while (!controller.choose(Outcome.Detriment, cardChoice, game)) {
if (!controller.isInGame()) {
return false;
}
}
cardName = cardChoice.getChoice();
game.informPlayers("Spoils of the Vault, named card: [" + cardName + "]");
}
Card sourceCard = game.getCard(source.getSourceId());
if (cardName == null || sourceCard == null) {
return false;
}
Cards cards = new CardsImpl(Zone.PICK);
Cards cards = new CardsImpl();
while (controller.getLibrary().size() > 0) {
Card card = controller.getLibrary().removeFromTop(game);
if (card != null) {
cards.add(card);
if(card.getName().equals(cardName)){
card.moveToZone(Zone.HAND, source.getSourceId(), game, false);
controller.moveCardToHandWithInfo(card, source.getSourceId(), game, Zone.LIBRARY);
break;
}
else{
card.moveToExile(null, sourceCard.getName(), source.getSourceId(), game);
controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.LIBRARY);
}
}
else{
@ -131,7 +114,7 @@ class SpoilsOfTheVaultEffect extends OneShotEffect {
}
}
controller.revealCards(sourceCard.getName(), cards, game);
controller.revealCards(sourceObject.getLogName(), cards, game);
controller.loseLife(cards.size(), game);
return true;

View file

@ -30,6 +30,7 @@ package mage.sets.odyssey;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.NameACardEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.repository.CardRepository;
@ -56,6 +57,7 @@ public class Predict extends CardImpl {
this.color.setBlue(true);
// Name a card, then target player puts the top card of his or her library into his or her graveyard. If that card is the named card, you draw two cards. Otherwise, you draw a card.
this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.ALL));
this.getSpellAbility().addEffect(new PredictEffect());
this.getSpellAbility().addTarget(new TargetPlayer());
}
@ -74,7 +76,7 @@ class PredictEffect extends OneShotEffect {
public PredictEffect() {
super(Outcome.DrawCard);
this.staticText = "Name a card, then target player puts the top card of his or her library into his or her graveyard. "
this.staticText = ", then target player puts the top card of his or her library into his or her graveyard. "
+ "If that card is the named card, you draw two cards. Otherwise, you draw a card.";
}
@ -90,24 +92,13 @@ class PredictEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player target = game.getPlayer(source.getFirstTarget());
if (controller != null && target != null) {
Choice cardChoice = new ChoiceImpl();
cardChoice.setChoices(CardRepository.instance.getNames());
cardChoice.clearChoice();
while (!controller.choose(Outcome.Detriment, cardChoice, game)) {
if (!controller.isInGame()) {
return false;
}
}
String cardName = cardChoice.getChoice();
game.informPlayers("Predict, named card: [" + cardName + "]");
int amount = 1;
Card card = target.getLibrary().removeFromTop(game);
Player targetPlayer = game.getPlayer(source.getFirstTarget());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) {
int amount = 1;
Card card = targetPlayer.getLibrary().getFromTop(game);
if (card != null) {
if (target.moveCardToGraveyardWithInfo(card, source.getSourceId(), game, Zone.LIBRARY)) {
if (targetPlayer.moveCardToGraveyardWithInfo(card, source.getSourceId(), game, Zone.LIBRARY)) {
if (card.getName().equals(cardName)) {
amount = 2;
}

View file

@ -33,11 +33,8 @@ import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.NameACardEffect;
import mage.cards.CardImpl;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.AbilityType;
import mage.constants.CardType;
import mage.constants.Duration;
@ -46,7 +43,6 @@ import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
/**
*
@ -59,7 +55,7 @@ public class PithingNeedle extends CardImpl {
this.expansionSetCode = "SOK";
// As Pithing Needle enters the battlefield, name a card.
this.addAbility(new AsEntersBattlefieldAbility(new NameCard()));
this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.ALL)));
// Activated abilities of sources with the chosen name can't be activated unless they're mana abilities.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PithingNeedleEffect()));
@ -75,43 +71,6 @@ public class PithingNeedle extends CardImpl {
}
}
class NameCard extends OneShotEffect {
public NameCard() {
super(Outcome.Detriment);
staticText = "name a card";
}
public NameCard(final NameCard effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Choice cardChoice = new ChoiceImpl();
cardChoice.setChoices(CardRepository.instance.getNames());
cardChoice.clearChoice();
while (!controller.choose(Outcome.Detriment, cardChoice, game)) {
if (!controller.isInGame()) {
return false;
}
}
String cardName = cardChoice.getChoice();
game.informPlayers("Pithing Needle, named card: [" + cardName + "]");
game.getState().setValue(source.getSourceId().toString(), cardName);
}
return false;
}
@Override
public NameCard copy() {
return new NameCard(this);
}
}
class PithingNeedleEffect extends ContinuousRuleModifiyingEffectImpl {
public PithingNeedleEffect() {
@ -140,7 +99,7 @@ class PithingNeedleEffect extends ContinuousRuleModifiyingEffectImpl {
Ability ability = game.getAbility(event.getTargetId(), event.getSourceId());
if (ability != null && object != null) {
if (ability.getAbilityType() != AbilityType.MANA &&
object.getName().equals(game.getState().getValue(source.getSourceId().toString()))) {
object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) {
return true;
}
}

View file

@ -28,38 +28,32 @@
package mage.sets.shadowmoor;
import java.util.UUID;
import mage.MageObject;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.abilities.Ability;
import mage.abilities.StaticAbility;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.NameACardEffect;
import mage.abilities.effects.common.continious.GainAbilityControllerEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.Filter;
import mage.filter.FilterCard;
import mage.filter.FilterObject;
import mage.filter.FilterPermanent;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
/**
* 5/1/2008: Runed Halo gives you protection from each object with the chosen name, whether it's a card, a token, or a copy of a spell. It doesn't matter what game zone that object is in.
* 5/1/2008: You can still be attacked by creatures with the chosen name.
* 5/1/2008: You'll have protection from the name, not from the word. For example, if you choose the name Forest, you'll have protection from anything named "Forest" -- but you won't have protection from Forests. An animated Sapseep Forest, for example, could deal damage to you even though its subtype is Forest.
* 5/1/2008: You can name either half of a split card, but not both. You'll have protection from the half you named (and from a fused split spell with that name), but not the other half.
* 5/1/2008: You can't choose [nothing] as a name. Face-down creatures have no name, so Runed Halo can't give you protection from them.
* 5/1/2008: You must choose the name of a card, not the name of a token. For example, you can't choose "Saproling" or "Voja." However, if a token happens to have the same name as a card (such as "Shapeshifter" or "Goldmeadow Harrier"), you can choose it.
* 5/1/2008: You may choose either one of a flip card's names. You'll have protection only from the appropriate version. For example, if you choose Nighteyes the Desecrator, you won't have protection from Nezumi Graverobber.
*
* @author LevelX2
*/
@ -72,20 +66,10 @@ public class RunedHalo extends CardImpl {
this.color.setWhite(true);
// As Runed Halo enters the battlefield, name a card.
this.addAbility(new AsEntersBattlefieldAbility(new NameCard()));
/**
* 5/1/2008: Runed Halo gives you protection from each object with the chosen name, whether it's a card, a token, or a copy of a spell. It doesn't matter what game zone that object is in.
* 5/1/2008: You can still be attacked by creatures with the chosen name.
* 5/1/2008: You'll have protection from the name, not from the word. For example, if you choose the name Forest, you'll have protection from anything named "Forest" -- but you won't have protection from Forests. An animated Sapseep Forest, for example, could deal damage to you even though its subtype is Forest.
* 5/1/2008: You can name either half of a split card, but not both. You'll have protection from the half you named (and from a fused split spell with that name), but not the other half.
* 5/1/2008: You can't choose [nothing] as a name. Face-down creatures have no name, so Runed Halo can't give you protection from them.
* 5/1/2008: You must choose the name of a card, not the name of a token. For example, you can't choose "Saproling" or "Voja." However, if a token happens to have the same name as a card (such as "Shapeshifter" or "Goldmeadow Harrier"), you can choose it.
* 5/1/2008: You may choose either one of a flip card's names. You'll have protection only from the appropriate version. For example, if you choose Nighteyes the Desecrator, you won't have protection from Nezumi Graverobber.
*/
Ability ability = new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.ALL));
// You have protection from the chosen name.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RunedHaloRuleTextEffect()));
ability.addEffect(new RunedHaloSetProtectionEffect());
this.addAbility(ability);
}
public RunedHalo(final RunedHalo card) {
@ -98,34 +82,22 @@ public class RunedHalo extends CardImpl {
}
}
class NameCard extends OneShotEffect {
class RunedHaloSetProtectionEffect extends OneShotEffect {
public NameCard() {
super(Outcome.Detriment);
staticText = "name a card";
public RunedHaloSetProtectionEffect() {
super(Outcome.Protect);
staticText = "<br/><br/>You have protection from the chosen name <i>(You can't be targeted, dealt damage, or enchanted by anything with that name.)<i/>";
}
public NameCard(final NameCard effect) {
public RunedHaloSetProtectionEffect(final RunedHaloSetProtectionEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (controller != null && sourcePermanent != null) {
Choice cardChoice = new ChoiceImpl();
cardChoice.setChoices(CardRepository.instance.getNames());
cardChoice.clearChoice();
while (!controller.choose(Outcome.Detriment, cardChoice, game)) {
if (!controller.isInGame()) {
return false;
}
}
String cardName = cardChoice.getChoice();
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(", named card: [").append(cardName).append("]").toString());
sourcePermanent.addInfo("Named card", new StringBuilder("[Named card: ").append(cardName).append("]").toString());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
if (controller != null && cardName != null && !cardName.isEmpty()) {
FilterObject filter = new FilterObject("the name [" + cardName + "]");
filter.add(new NamePredicate(cardName));
ContinuousEffect effect = new GainAbilityControllerEffect(new ProtectionAbility(filter), Duration.Custom);
@ -136,30 +108,8 @@ class NameCard extends OneShotEffect {
}
@Override
public NameCard copy() {
return new NameCard(this);
public RunedHaloSetProtectionEffect copy() {
return new RunedHaloSetProtectionEffect(this);
}
}
class RunedHaloRuleTextEffect extends OneShotEffect {
public RunedHaloRuleTextEffect() {
super(Outcome.Benefit);
this.staticText = "You have protection from the chosen name <i>(You can't be targeted, dealt damage, or enchanted by anything with that name.)<i/>";
}
public RunedHaloRuleTextEffect(final RunedHaloRuleTextEffect effect) {
super(effect);
}
@Override
public RunedHaloRuleTextEffect copy() {
return new RunedHaloRuleTextEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
}

View file

@ -28,6 +28,7 @@
package mage.sets.tempest;
import java.util.UUID;
import mage.MageObject;
import mage.constants.CardType;
import mage.constants.Rarity;
@ -36,13 +37,11 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.NameACardEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
@ -62,7 +61,8 @@ public class CursedScroll extends CardImpl {
this.expansionSetCode = "TMP";
// {3}, {tap}: Name a card. Reveal a card at random from your hand. If it's the named card, Cursed Scroll deals 2 damage to target creature or player.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CursedScrollEffect(), new ManaCostsImpl("{3}"));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new NameACardEffect(NameACardEffect.TypeOfName.ALL), new ManaCostsImpl("{3}"));
ability.addEffect(new CursedScrollEffect());
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability);
@ -82,7 +82,7 @@ class CursedScrollEffect extends OneShotEffect {
public CursedScrollEffect() {
super(Outcome.Neutral);
staticText = "Name a card. Reveal a card at random from your hand. If it's the named card, {this} deals 2 damage to target creature or player";
staticText = "Reveal a card at random from your hand. If it's the named card, {this} deals 2 damage to target creature or player";
}
public CursedScrollEffect(final CursedScrollEffect effect) {
@ -92,22 +92,14 @@ class CursedScrollEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player you = game.getPlayer(source.getControllerId());
if (you != null) {
Choice cardChoice = new ChoiceImpl();
cardChoice.setChoices(CardRepository.instance.getNames());
cardChoice.clearChoice();
while (!you.choose(Outcome.Damage, cardChoice, game)) {
if (!you.isInGame()) {
return false;
}
}
String cardName = cardChoice.getChoice();
game.informPlayers("Cursed Scroll, named card: [" + cardName + "]");
MageObject sourceObject = game.getObject(source.getSourceId());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
if (sourceObject != null && you != null && cardName != null && !cardName.isEmpty()) {
if (you.getHand().size() > 0) {
Cards revealed = new CardsImpl();
Card card = you.getHand().getRandom(game);
revealed.add(card);
you.revealCards("Cursed Scroll", revealed, game);
you.revealCards(sourceObject.getLogName(), revealed, game);
if (card.getName().equals(cardName)) {
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
if (creature != null) {

View file

@ -0,0 +1,63 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.protection.gain;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class RunedHaloTest extends CardTestPlayerBase {
// As Runed Halo enters the battlefield, name a card.
// You have protection from the chosen name.
@Test
public void testGainProtectionFromAttackingCreature() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.HAND, playerA, "Runed Halo");
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Runed Halo");
setChoice(playerA, "Silvercoat Lion");
attack(2, playerB, "Silvercoat Lion");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20); // because he has protecion from Silvercoat Lion
}
}

View file

@ -50,6 +50,19 @@ public class AsEntersBattlefieldAbility extends StaticAbility {
super(ability);
}
@Override
public void addEffect(Effect effect) {
if (!getEffects().isEmpty()) {
Effect entersEffect = this.getEffects().get(0);
if (entersEffect instanceof EntersBattlefieldEffect) {
((EntersBattlefieldEffect) entersEffect).addEffect(effect);
return;
}
}
super.addEffect(effect);
}
@Override
public AsEntersBattlefieldAbility copy() {
return new AsEntersBattlefieldAbility(this);

View file

@ -0,0 +1,123 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
* @author LevelX2
*/
public class NameACardEffect extends OneShotEffect {
public static String INFO_KEY = "NAMED_CARD";
public enum TypeOfName {
ALL,
NON_LAND_NAME,
NON_LAND_AND_NON_CREATURE_NAME
}
private final TypeOfName typeOfName;
public NameACardEffect(TypeOfName typeOfName) {
super(Outcome.Detriment);
this.typeOfName = typeOfName;
staticText = setText();
}
public NameACardEffect(final NameACardEffect effect) {
super(effect);
this.typeOfName = effect.typeOfName;
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller != null && sourceObject != null) {
Choice cardChoice = new ChoiceImpl();
switch(typeOfName) {
case ALL:
cardChoice.setChoices(CardRepository.instance.getNames());
break;
case NON_LAND_AND_NON_CREATURE_NAME:
cardChoice.setChoices(CardRepository.instance.getNonLandAndNonCreatureNames());
break;
case NON_LAND_NAME:
cardChoice.setChoices(CardRepository.instance.getNonLandNames());
break;
}
cardChoice.clearChoice();
while (!controller.choose(Outcome.Detriment, cardChoice, game)) {
if (!controller.isInGame()) {
return false;
}
}
String cardName = cardChoice.getChoice();
game.informPlayers(sourceObject.getLogName() + ", named card: [" + cardName + "]");
game.getState().setValue(source.getSourceId().toString() + INFO_KEY, cardName);
if (sourceObject instanceof Permanent) {
((Permanent)sourceObject).addInfo(INFO_KEY, CardUtil.addToolTipMarkTags("Named card: " + cardName));
}
return true;
}
return false;
}
@Override
public NameACardEffect copy() {
return new NameACardEffect(this);
}
private String setText() {
StringBuilder sb = new StringBuilder("name a ");
switch(typeOfName) {
case ALL:
sb.append("card");
break;
case NON_LAND_AND_NON_CREATURE_NAME:
sb.append("card other than a creature or a land card");
break;
case NON_LAND_NAME:
sb.append("nonland card");
break;
}
return sb.toString();
}
}