Fixed NPE errors for some cards (#5471)

This commit is contained in:
Oleg Agafonov 2019-01-08 07:00:14 +04:00
parent b73529fbc4
commit d0c8d6a707
17 changed files with 190 additions and 224 deletions

View file

@ -58,6 +58,7 @@ class HintOfInsanityEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
FilterCard filter = new FilterCard("card from your hand");
Player targetPlayer = game.getPlayer(source.getFirstTarget());
Card chosenCard;
if (targetPlayer != null) {
TargetCardInHand targetCard = new TargetCardInHand(filter);
targetCard.setNotTarget(true);
@ -66,12 +67,10 @@ class HintOfInsanityEffect extends OneShotEffect {
targetPlayer.revealCards("Hint of Insanity Reveal", cardsInHand, game);
if (!cardsInHand.isEmpty()
&& targetPlayer.choose(Outcome.Discard, targetCard, source.getSourceId(), game)) {
Card chosenCard = game.getCard(targetCard.getFirstTarget());
if (chosenCard != null) {
for (Card card : cardsInHand.getCards(game)) {
if (CardUtil.haveSameNames(card, chosenCard) && !card.isLand()) {
targetPlayer.discard(card, source, game);
}
chosenCard = game.getCard(targetCard.getFirstTarget());
for (Card card : cardsInHand.getCards(game)) {
if (CardUtil.haveSameNames(card, chosenCard) && !card.isLand()) {
targetPlayer.discard(card, source, game);
}
}
return true;

View file

@ -1,7 +1,5 @@
package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
@ -16,12 +14,7 @@ import mage.abilities.keyword.TrampleAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
@ -32,8 +25,9 @@ import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author L_J
*/
public final class NamelessRace extends CardImpl {
@ -48,7 +42,7 @@ public final class NamelessRace extends CardImpl {
// As Nameless Race enters the battlefield, pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards.
this.addAbility(new AsEntersBattlefieldAbility(new NamelessRaceEffect()));
// Nameless Race's power and toughness are each equal to the life paid as it entered the battlefield.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield")));
}
@ -64,10 +58,10 @@ public final class NamelessRace extends CardImpl {
}
class NamelessRaceEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent("white nontoken permanents your opponents control");
private static final FilterCard filter2 = new FilterCard("white cards in their graveyards");
static {
filter.add(new ColorPredicate(ObjectColor.WHITE));
filter.add(Predicates.not(new TokenPredicate()));
@ -94,13 +88,13 @@ class NamelessRaceEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card sourceCard = game.getCard(source.getSourceId());
int permanentsInPlay = new PermanentsOnBattlefieldCount(filter).calculate(game, source, null);
int cardsInGraveyards = new CardsInAllGraveyardsCount(filter2).calculate(game, source, null);
int maxAmount = Math.min(permanentsInPlay + cardsInGraveyards, controller.getLife());
int payAmount = controller.getAmount(0, maxAmount, "Pay up to " + maxAmount + " life", game);
controller.loseLife(payAmount, game, false);
game.informPlayers(sourceCard.getLogName() + ": " + controller.getLogName() +
Card sourceCard = game.getCard(source.getSourceId());
game.informPlayers((sourceCard != null ? sourceCard.getLogName() : "") + ": " + controller.getLogName() +
" pays " + payAmount + " life");
game.addEffect(new SetPowerToughnessSourceEffect(payAmount, payAmount, Duration.Custom, SubLayer.SetPT_7b), source);
return true;

View file

@ -1,14 +1,8 @@
package mage.cards.n;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@ -18,14 +12,15 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class Nightsnare extends CardImpl {
public Nightsnare(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}");
// Target opponent reveals their hand. You may choose a nonland card from it. If you do, that player discards that card. If you don't, that player discards two cards.
this.getSpellAbility().addTarget(new TargetOpponent());
@ -57,11 +52,11 @@ class NightsnareDiscardEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
Player controller = game.getPlayer(source.getControllerId());
Card sourceCard = game.getCard(source.getSourceId());
if (player != null && controller != null) {
if (!player.getHand().isEmpty()) {
Cards revealedCards = new CardsImpl();
revealedCards.addAll(player.getHand());
Card sourceCard = game.getCard(source.getSourceId());
player.revealCards(sourceCard != null ? sourceCard.getIdName() : "Discard", revealedCards, game);
// You may choose a nonland card from it.
if (controller.chooseUse(outcome, "Choose a a card to discard? (Otherwise " + player.getLogName() + " has to discard 2 cards).", source, game)) {

View file

@ -1,8 +1,5 @@
package mage.cards.n;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.common.FightTargetsEffect;
import mage.cards.Card;
@ -19,6 +16,9 @@ import mage.game.stack.Spell;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.Set;
import java.util.UUID;
/**
* @author Styxo
*/
@ -56,8 +56,11 @@ class TargetCreatureWithLessPowerPermanent extends TargetPermanent {
@Override
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
int maxPower = Integer.MIN_VALUE; // get the most poerful controlled creature that can be targeted
int maxPower = Integer.MIN_VALUE; // get the most powerful controlled creature that can be targeted
Card sourceCard = game.getCard(sourceId);
if (sourceCard == null) {
return false;
}
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, sourceControllerId, game)) {
if (permanent.getPower().getValue() > maxPower && permanent.canBeTargetedBy(sourceCard, sourceControllerId, game)) {
maxPower = permanent.getPower().getValue();

View file

@ -1,7 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -10,23 +8,19 @@ import mage.abilities.keyword.FlashbackAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.TimingRule;
import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author BetaSteward
*/
public final class PastInFlames extends CardImpl {
public PastInFlames(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}");
// Each instant and sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost.
@ -72,7 +66,7 @@ class PastInFlamesEffect extends ContinuousEffectImpl {
player.getGraveyard().stream().map((cardId) -> game.getCard(cardId)).filter((card) -> (card.isInstant() || card.isSorcery())).forEachOrdered((card) -> {
affectedObjectList.add(new MageObjectReference(card, game));
});
}
}
}
}
@ -82,17 +76,18 @@ class PastInFlamesEffect extends ContinuousEffectImpl {
if (player != null) {
player.getGraveyard().stream().filter((cardId) -> (affectedObjectList.contains(new MageObjectReference(cardId, game)))).forEachOrdered((cardId) -> {
Card card = game.getCard(cardId);
FlashbackAbility ability = null;
if (card.isInstant()) {
ability = new FlashbackAbility(card.getManaCost(), TimingRule.INSTANT);
}
else if (card.isSorcery()) {
ability = new FlashbackAbility(card.getManaCost(), TimingRule.SORCERY);
}
if (ability != null) {
ability.setSourceId(cardId);
ability.setControllerId(card.getOwnerId());
game.getState().addOtherAbility(card, ability);
if (card != null) {
FlashbackAbility ability = null;
if (card.isInstant()) {
ability = new FlashbackAbility(card.getManaCost(), TimingRule.INSTANT);
} else if (card.isSorcery()) {
ability = new FlashbackAbility(card.getManaCost(), TimingRule.SORCERY);
}
if (ability != null) {
ability.setSourceId(cardId);
ability.setControllerId(card.getOwnerId());
game.getState().addOtherAbility(card, ability);
}
}
});
return true;

View file

@ -1,7 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -19,14 +17,15 @@ import mage.game.permanent.token.MinionToken;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author FenrisulfrX
*/
public final class PhyrexianProcessor extends CardImpl {
public PhyrexianProcessor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// As {this} enters the battlefield, pay any amount of life.
this.addAbility(new EntersBattlefieldTriggeredAbility(new PhyrexianProcessorEffect()));
@ -65,11 +64,11 @@ class PhyrexianProcessorEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if(controller != null) {
Card sourceCard = game.getCard(source.getSourceId());
if (controller != null) {
int payAmount = controller.getAmount(0, controller.getLife(), staticText, game);
controller.loseLife(payAmount, game, false);
game.informPlayers(sourceCard.getName() + ": " + controller.getLogName() +
Card sourceCard = game.getCard(source.getSourceId());
game.informPlayers((sourceCard != null ? sourceCard.getName() : "") + ": " + controller.getLogName() +
" pays " + payAmount + " life.");
String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game);
game.getState().setValue(key, payAmount);
@ -80,7 +79,7 @@ class PhyrexianProcessorEffect extends OneShotEffect {
}
class PhyrexianProcessorCreateTokenEffect extends OneShotEffect {
public PhyrexianProcessorCreateTokenEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "Create an X/X black Minion creature token";
@ -89,7 +88,7 @@ class PhyrexianProcessorCreateTokenEffect extends OneShotEffect {
public PhyrexianProcessorCreateTokenEffect(PhyrexianProcessorCreateTokenEffect ability) {
super(ability);
}
@Override
public PhyrexianProcessorCreateTokenEffect copy() {
return new PhyrexianProcessorCreateTokenEffect(this);
@ -99,7 +98,7 @@ class PhyrexianProcessorCreateTokenEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game);
Object object = game.getState().getValue(key);
if(object instanceof Integer) {
if (object instanceof Integer) {
int lifePaid = (int) object;
MinionToken token = new MinionToken();
token.getPower().modifyBaseValue(lifePaid);

View file

@ -1,9 +1,5 @@
package mage.cards.p;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -16,14 +12,17 @@ import mage.game.permanent.token.RatToken;
import mage.players.Player;
import mage.players.PlayerList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class PlagueOfVermin extends CardImpl {
public PlagueOfVermin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{6}{B}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{B}");
// Starting with you, each player may pay any amount of life. Repeat this process until no one pays life. Each player creates a 1/1 black Rat creature token for each 1 life he or she paid this way.
@ -60,7 +59,6 @@ class PlagueOfVerminEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Card sourceCard = game.getCard(source.getSourceId());
Map<UUID, Integer> payLife = new HashMap<>();
int currentLifePaid;
int totalPaidLife;
@ -90,15 +88,16 @@ class PlagueOfVerminEffect extends OneShotEffect {
payLife.put(currentPlayer.getId(), currentLifePaid + totalPaidLife);
}
}
game.informPlayers(sourceCard.getName() + ": " + currentPlayer.getLogName() + " pays " + payLife.get(currentPlayer.getId()) + " life");
Card sourceCard = game.getCard(source.getSourceId());
game.informPlayers((sourceCard != null ? sourceCard.getName() : "") + ": " + currentPlayer.getLogName() + " pays " + payLife.get(currentPlayer.getId()) + " life");
firstInactivePlayer = null;
}
}
// get next player
playerList.getNext();
currentPlayer = game.getPlayer(playerList.get());
// if all player since this player didn't put permanent in play finish the process
if (currentPlayer.getId().equals(firstInactivePlayer)) {
break;

View file

@ -1,7 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
@ -23,6 +21,8 @@ import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
* @author North
*/
@ -76,13 +76,11 @@ class PostmortemLungeEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Card card = game.getCard(source.getFirstTarget());
if (card != null) {
Player cardOwner = game.getPlayer(card.getOwnerId());
if (cardOwner == null) {
return false;
}
if (cardOwner.moveCards(card, Zone.BATTLEFIELD, source, game)) {
Permanent permanent = game.getPermanent(card.getId());
if (permanent != null) {
@ -96,7 +94,6 @@ class PostmortemLungeEffect extends OneShotEffect {
}
return true;
}
return false;
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -17,15 +15,15 @@ import mage.players.Player;
import mage.target.TargetSpell;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*
*/
public final class PutAway extends CardImpl {
public PutAway(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
// Counter target spell. You may shuffle up to one target card from your graveyard into your library.
@ -46,7 +44,7 @@ public final class PutAway extends CardImpl {
}
class PutAwayEffect extends OneShotEffect {
boolean countered = false;
public PutAwayEffect() {
@ -66,15 +64,14 @@ class PutAwayEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(source.getFirstTarget());
Card card = game.getCard(source.getTargets().get(1).getFirstTarget());
Player you = game.getPlayer(source.getControllerId());
if (spell != null
&& game.getStack().counter(spell.getId(), source.getSourceId(), game)) {
if (spell != null && game.getStack().counter(spell.getId(), source.getSourceId(), game)) {
countered = true;
}
if (you != null) {
if (card != null
&& you.chooseUse(Outcome.Benefit, "Do you wish to shuffle up to one target card from your graveyard into your library?", source, game)
Card card = game.getCard(source.getTargets().get(1).getFirstTarget());
Player you = game.getPlayer(source.getControllerId());
if (you != null && card != null) {
if (you.chooseUse(Outcome.Benefit, "Do you wish to shuffle up to one target card from your graveyard into your library?", source, game)
&& game.getState().getZone(card.getId()).match(Zone.GRAVEYARD)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
you.shuffleLibrary(source, game);

View file

@ -5,8 +5,6 @@ import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.RevealHandSourceControllerEffect;
import mage.abilities.effects.common.RevealHandTargetEffect;
import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.*;
@ -23,14 +21,13 @@ import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
*
* @author noahg
*/
public final class RakdosAugermage extends CardImpl {
public RakdosAugermage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(3);
@ -71,16 +68,16 @@ class RakdosAugermageEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
Player controller = game.getPlayer(source.getControllerId());
Card sourceCard = game.getCard(source.getSourceId());
if (player != null && controller != null) {
Cards revealedCards = new CardsImpl();
revealedCards.addAll(controller.getHand());
player.revealCards((sourceCard != null ? sourceCard.getIdName() + " (" + sourceCard.getZoneChangeCounter(game) + ") (" : "Discard (")+controller.getName()+")", revealedCards, game);
Card sourceCard = game.getCard(source.getSourceId());
player.revealCards((sourceCard != null ? sourceCard.getIdName() + " (" + sourceCard.getZoneChangeCounter(game) + ") (" : "Discard (") + controller.getName() + ")", revealedCards, game);
TargetCard target = new TargetCard(Zone.HAND, new FilterCard());
if (player.choose(Outcome.Benefit, revealedCards, target, game)) {
Card card = revealedCards.get(target.getFirstTarget(), game);
if (card != null) {
return player.discard(card, source, game);
return player.discard(card, source, game);
}
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.r;
import java.util.UUID;
import mage.ConditionalMana;
import mage.MageInt;
import mage.MageObject;
@ -14,14 +12,10 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.mana.ConditionalColorlessManaAbility;
import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
@ -30,14 +24,15 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class RenownedWeaponsmith extends CardImpl {
public RenownedWeaponsmith(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ARTIFICER);
this.power = new MageInt(1);
@ -120,11 +115,14 @@ class RenownedWeaponsmithEffect extends OneShotEffect {
TargetCardInLibrary target = new TargetCardInLibrary(filter);
if (controller.searchLibrary(target, game)) {
if (!target.getTargets().isEmpty()) {
Card card = game.getCard(target.getFirstTarget());
Cards revealed = new CardsImpl();
revealed.add(card);
controller.revealCards(sourceObject.getIdName(), revealed, game);
controller.moveCards(revealed, Zone.HAND, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
revealed.add(card);
controller.revealCards(sourceObject.getIdName(), revealed, game);
controller.moveCards(revealed, Zone.HAND, source, game);
}
}
}
controller.shuffleLibrary(source, game);

View file

@ -1,7 +1,5 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -15,20 +13,21 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInASingleGraveyard;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class SereneRemembrance extends CardImpl {
public SereneRemembrance (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{G}");
public SereneRemembrance(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}");
// Shuffle Serene Remembrance and up to three target cards from a single graveyard into their owners' libraries.
this.getSpellAbility().addEffect(new SereneRemembranceEffect());
this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0,3,new FilterCard("up to three target cards from a single graveyard")));
this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("up to three target cards from a single graveyard")));
}
public SereneRemembrance(final SereneRemembrance card) {
@ -36,30 +35,32 @@ public final class SereneRemembrance extends CardImpl {
}
@Override
public SereneRemembrance copy() {
public SereneRemembrance copy() {
return new SereneRemembrance(this);
}
}
class SereneRemembranceEffect extends OneShotEffect {
public SereneRemembranceEffect() {
super(Outcome.Benefit);
this.staticText = "Shuffle Serene Remembrance and up to three target cards from a single graveyard into their owners' libraries";
}
public SereneRemembranceEffect(final SereneRemembranceEffect effect) {
super(effect);
}
@Override
public SereneRemembranceEffect copy() {
return new SereneRemembranceEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
boolean result = false;
// 3 cards to graveyard
Player graveyardPlayer = null;
for (UUID cardInGraveyard : targetPointer.getTargets(game, source)) {
Card card = game.getCard(cardInGraveyard);
@ -71,17 +72,22 @@ class SereneRemembranceEffect extends OneShotEffect {
result |= card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
}
}
}
}
// source card to graveyard
Card card = game.getCard(source.getSourceId());
result |= card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
Player player = game.getPlayer(card.getOwnerId());
if (player != null){
player.shuffleLibrary(source, game);
}
if (graveyardPlayer != null && !graveyardPlayer.equals(player)) {
graveyardPlayer.shuffleLibrary(source, game);
if (card != null) {
result |= card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
Player player = game.getPlayer(card.getOwnerId());
if (player != null) {
player.shuffleLibrary(source, game);
}
if (graveyardPlayer != null && !graveyardPlayer.equals(player)) {
graveyardPlayer.shuffleLibrary(source, game);
}
}
return result;
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
@ -13,11 +11,7 @@ import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEf
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
@ -25,8 +19,9 @@ import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class ShireiShizosCaretaker extends CardImpl {
@ -78,8 +73,8 @@ class ShireiShizosCaretakerTriggeredAbility extends TriggeredAbilityImpl {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
Permanent LKIpermanent = game.getPermanentOrLKIBattlefield(zEvent.getTargetId());
Card card = game.getCard(zEvent.getTargetId());
if (card != null && LKIpermanent != null
if (card != null
&& LKIpermanent != null
&& card.isOwnedBy(this.controllerId)
&& zEvent.getToZone() == Zone.GRAVEYARD
&& zEvent.getFromZone() == Zone.BATTLEFIELD

View file

@ -1,16 +1,10 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@ -23,14 +17,15 @@ import mage.players.Player;
import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public final class ShroudedLore extends CardImpl {
public ShroudedLore(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{B}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}");
// Target opponent chooses a card in your graveyard. You may pay {B}. If you do, repeat this process except that opponent can't choose a card already chosen for Shrouded Lore. Then put the last chosen card into your hand.
this.getSpellAbility().addEffect(new ShroudedLoreEffect());
@ -67,8 +62,7 @@ class ShroudedLoreEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player you = game.getPlayer(source.getControllerId());
Player opponent = game.getPlayer(targetPointer.getFirst(game, source));
if(you != null && opponent != null)
{
if (you != null && opponent != null) {
FilterCard filter = new FilterCard();
filter.add(new OwnerIdPredicate(you.getId()));
Cost cost = new ManaCostsImpl("{B}");
@ -78,31 +72,31 @@ class ShroudedLoreEffect extends OneShotEffect {
do {
chosenCard = new TargetCardInGraveyard(filter);
chosenCard.setNotTarget(true);
if(chosenCard.canChoose(opponent.getId(), game)) {
if (chosenCard.canChoose(opponent.getId(), game)) {
opponent.chooseTarget(Outcome.ReturnToHand, chosenCard, source, game);
card = game.getCard(chosenCard.getFirstTarget());
filter.add(Predicates.not(new CardIdPredicate(card.getId())));
game.informPlayers("Shrouded Lore: " + opponent.getLogName() + " has chosen " + card.getLogName());
}
else {
if (card != null) {
filter.add(Predicates.not(new CardIdPredicate(card.getId())));
game.informPlayers("Shrouded Lore: " + opponent.getLogName() + " has chosen " + card.getLogName());
}
} else {
done = true;
}
if(!done) {
if(cost.canPay(source, source.getSourceId(), you.getId(), game) && you.chooseUse(Outcome.Benefit, "Pay {B} to choose a different card ?", source, game)) {
if (!done) {
if (cost.canPay(source, source.getSourceId(), you.getId(), game) && you.chooseUse(Outcome.Benefit, "Pay {B} to choose a different card ?", source, game)) {
cost.clearPaid();
if(!cost.pay(source, game, source.getSourceId(), you.getId(), false, null)) {
if (!cost.pay(source, game, source.getSourceId(), you.getId(), false, null)) {
done = true;
}
}
else {
} else {
done = true;
}
}
} while(!done);
} while (!done);
if(card != null) {
if (card != null) {
Cards cardsToHand = new CardsImpl();
cardsToHand.add(card);
you.moveCards(cardsToHand, Zone.HAND, source, game);

View file

@ -5,7 +5,6 @@
*/
package mage.abilities.costs.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
@ -16,8 +15,9 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
@ -40,7 +40,7 @@ public class PutCardFromHandOnTopOfLibraryCost extends CostImpl {
if (targetCardInHand.canChoose(controllerId, game)
&& controller.choose(Outcome.PreventDamage, targetCardInHand, sourceId, game)) {
card = game.getCard(targetCardInHand.getFirstTarget());
paid = controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.HAND, true, true);
paid = card != null && controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.HAND, true, true);
}
return paid;
}

View file

@ -1,7 +1,5 @@
package mage.abilities.keyword;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
@ -19,18 +17,19 @@ import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* 702.46. Offering # 702.46a Offering is a static ability of a card that
* functions in any zone from which the card can be cast. "[Subtype] offering"
* means "You may cast this card any time you could cast an instant by
* sacrificing a [subtype] permanent. If you do, the total cost to cast this
* card is reduced by the sacrificed permanent's mana cost." #
*
* <p>
* 702.46b The permanent is sacrificed at the same time the spell is announced
* (see rule 601.2a). The total cost of the spell is reduced by the sacrificed
* permanent's mana cost (see rule 601.2e). #
*
* <p>
* 702.46c Generic mana in the sacrificed permanent's mana cost reduces generic
* mana in the total cost to cast the card with offering. Colored mana in the
* sacrificed permanent's mana cost reduces mana of the same color in the total
@ -39,7 +38,6 @@ import mage.util.CardUtil;
* cost of the card with offering, or is in excess of the card's colored mana
* cost, reduces that much generic mana in the total cost. #
*
*
* @author LevelX2
*/
public class OfferingAbility extends StaticAbility {
@ -47,7 +45,6 @@ public class OfferingAbility extends StaticAbility {
private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
/**
*
* @param subtype name of the subtype that can be offered
*/
public OfferingAbility(SubType subtype) {
@ -107,7 +104,7 @@ class OfferingAsThoughEffect extends AsThoughEffectImpl {
public boolean applies(UUID sourceId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
if (sourceId.equals(source.getSourceId())) {
Card card = game.getCard(sourceId);
if (!card.isOwnedBy(source.getControllerId())) {
if (card == null || !card.isOwnedBy(source.getControllerId())) {
return false;
}
// because can activate is always called twice, result from first call will be used
@ -129,6 +126,9 @@ class OfferingAsThoughEffect extends AsThoughEffectImpl {
}
FilterControlledCreaturePermanent filter = ((OfferingAbility) source).getFilter();
Card spellToCast = game.getCard(source.getSourceId());
if (spellToCast == null) {
return false;
}
Player player = game.getPlayer(source.getControllerId());
if (player != null && !CardUtil.isCheckPlayableMode(affectedAbility)
&& player.chooseUse(Outcome.Benefit, "Offer a " + filter.getMessage() + " to cast " + spellToCast.getName() + '?', source, game)) {
@ -146,7 +146,6 @@ class OfferingAsThoughEffect extends AsThoughEffectImpl {
game.getState().setValue("offering_ok_" + card.getId(), true);
game.getState().setValue("offering_Id_" + card.getId(), activationId);
return true;
}
} else {
game.getState().setValue("offering_" + card.getId(), true);
@ -201,7 +200,7 @@ class OfferingCostReductionEffect extends CostModificationEffectImpl {
Card card = game.getCard(source.getSourceId());
if (card != null) {
Object object = game.getState().getValue("offering_Id_" + card.getId());
if (object != null && ((UUID) object).equals(this.activationId) && offeredPermanent.getPermanent(game) != null) {
if (object != null && object.equals(this.activationId) && offeredPermanent.getPermanent(game) != null) {
return true;
}
}

View file

@ -619,9 +619,7 @@ public abstract class PlayerImpl implements Player, Serializable {
return false;
}
}
if (hasProtectionFrom(source, game)) {
return false;
}
return !hasProtectionFrom(source, game);
}
return true;
@ -1122,6 +1120,9 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public boolean playLand(Card card, Game game, boolean ignoreTiming) {
// Check for alternate casting possibilities: e.g. land with Morph
if (card == null) {
return false;
}
ActivatedAbility playLandAbility = null;
boolean found = false;
for (Ability ability : card.getAbilities()) {
@ -1342,7 +1343,7 @@ public abstract class PlayerImpl implements Player, Serializable {
switch (((SpellAbility) ability).getSpellAbilityType()) {
case SPLIT_FUSED:
if (zone == Zone.HAND) {
if (((SpellAbility) ability).canChooseTarget(game)) {
if (ability.canChooseTarget(game)) {
useable.put(ability.getId(), (SpellAbility) ability);
}
}
@ -1456,37 +1457,39 @@ public abstract class PlayerImpl implements Player, Serializable {
for (ActivatedAbility ability : otherAbilities) {
if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
Card card = game.getCard(ability.getSourceId());
if (card.isSplitCard() && ability instanceof FlashbackAbility) {
FlashbackAbility flashbackAbility;
// Left Half
if (card.isInstant()) {
flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.INSTANT);
} else {
flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.SORCERY);
}
flashbackAbility.setSourceId(card.getId());
flashbackAbility.setControllerId(card.getOwnerId());
flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_LEFT);
flashbackAbility.setAbilityName(((SplitCard) card).getLeftHalfCard().getName());
if (flashbackAbility.canActivate(playerId, game).canActivate()) {
useable.put(flashbackAbility.getId(), flashbackAbility);
}
// Right Half
if (card.isInstant()) {
flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.INSTANT);
} else {
flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.SORCERY);
}
flashbackAbility.setSourceId(card.getId());
flashbackAbility.setControllerId(card.getOwnerId());
flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_RIGHT);
flashbackAbility.setAbilityName(((SplitCard) card).getRightHalfCard().getName());
if (flashbackAbility.canActivate(playerId, game).canActivate()) {
useable.put(flashbackAbility.getId(), flashbackAbility);
}
if (card != null) {
if (card.isSplitCard() && ability instanceof FlashbackAbility) {
FlashbackAbility flashbackAbility;
// Left Half
if (card.isInstant()) {
flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.INSTANT);
} else {
flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.SORCERY);
}
flashbackAbility.setSourceId(card.getId());
flashbackAbility.setControllerId(card.getOwnerId());
flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_LEFT);
flashbackAbility.setAbilityName(((SplitCard) card).getLeftHalfCard().getName());
if (flashbackAbility.canActivate(playerId, game).canActivate()) {
useable.put(flashbackAbility.getId(), flashbackAbility);
}
// Right Half
if (card.isInstant()) {
flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.INSTANT);
} else {
flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.SORCERY);
}
flashbackAbility.setSourceId(card.getId());
flashbackAbility.setControllerId(card.getOwnerId());
flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_RIGHT);
flashbackAbility.setAbilityName(((SplitCard) card).getRightHalfCard().getName());
if (flashbackAbility.canActivate(playerId, game).canActivate()) {
useable.put(flashbackAbility.getId(), flashbackAbility);
}
} else {
useable.put(ability.getId(), ability);
} else {
useable.put(ability.getId(), ability);
}
}
}
}
@ -1690,9 +1693,7 @@ public abstract class PlayerImpl implements Player, Serializable {
leftForUntap = getPermanentsThatCanBeUntapped(game, canBeUntapped, handledEntry.getKey().getKey(), notMoreThanEffectsUsage);
// remove already selected permanents
for (Permanent permanent : selectedToUntap) {
if (leftForUntap.contains(permanent)) {
leftForUntap.remove(permanent);
}
leftForUntap.remove(permanent);
}
} else {
@ -1961,7 +1962,7 @@ public abstract class PlayerImpl implements Player, Serializable {
sourceControllerId = ((Card) source).getOwnerId();
} else if (source instanceof CommandObject) {
sourceControllerId = ((CommandObject) source).getControllerId();
sourceAbilities = ((CommandObject) source).getAbilities();
sourceAbilities = source.getAbilities();
}
} else {
sourceAbilities = ((Permanent) source).getAbilities(game);
@ -2847,9 +2848,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
}
}
if (canPlayCardByAlternateCost(card, available, ability, game)) {
return true;
}
return canPlayCardByAlternateCost(card, available, ability, game);
}
return false;
}
@ -3582,7 +3581,7 @@ public abstract class PlayerImpl implements Player, Serializable {
case OUTSIDE:
for (Card card : cards) {
if (card instanceof Permanent) {
game.getBattlefield().removePermanent(((Permanent) card).getId());
game.getBattlefield().removePermanent(card.getId());
ZoneChangeEvent event = new ZoneChangeEvent(card.getId(), (source == null ? null : source.getSourceId()),
byOwner ? card.getOwnerId() : getId(), Zone.BATTLEFIELD, Zone.OUTSIDE, appliedEffects);
game.fireEvent(event);
@ -3731,7 +3730,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
boolean result = false;
// Zone fromZone = game.getState().getZone(card.getId());
if (card.moveToZone(Zone.GRAVEYARD, sourceId, game, fromZone != null ? fromZone == Zone.BATTLEFIELD : false)) {
if (card.moveToZone(Zone.GRAVEYARD, sourceId, game, fromZone != null && fromZone == Zone.BATTLEFIELD)) {
if (!game.isSimulation()) {
if (card instanceof PermanentCard && game.getCard(card.getId()) != null) {
card = game.getCard(card.getId());