diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java index 018ef807a1..a546d9b698 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java @@ -1,4 +1,3 @@ - package mage.player.ai; import mage.MageObject; @@ -25,7 +24,6 @@ import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; /** - * * @author BetaSteward_at_googlemail.com */ public class SimulatedPlayer2 extends ComputerPlayer { @@ -173,6 +171,7 @@ public class SimulatedPlayer2 extends ComputerPlayer { // allActions.add(new SimulatedAction(sim, actions)); // } // } + /** * if suggested abilities exist, return only those from playables * @@ -191,11 +190,13 @@ public class SimulatedPlayer2 extends ComputerPlayer { List filtered = new ArrayList<>(); for (Ability ability : playables) { Card card = game.getCard(ability.getSourceId()); - for (String s : suggested) { - if (s.equals(card.getName())) { - logger.debug("matched: " + s); - forced = true; - filtered.add(ability); + if (card != null) { + for (String s : suggested) { + if (s.equals(card.getName())) { + logger.debug("matched: " + s); + forced = true; + filtered.add(ability); + } } } } @@ -216,26 +217,28 @@ public class SimulatedPlayer2 extends ComputerPlayer { for (Ability option : options) { if (!option.getTargets().isEmpty() && option.getTargets().get(0).getMaxNumberOfTargets() == 1) { Card card = game.getCard(ability.getSourceId()); - for (String s : suggested) { - String[] groups = s.split(";"); - logger.trace("s=" + s + ";groups=" + groups.length); - if (groups.length == 2) { - if (groups[0].equals(card.getName()) && groups[1].startsWith("name=")) { - // extract target and compare to suggested - String targetName = groups[1].split("=")[1]; - Player player = game.getPlayer(option.getFirstTarget()); - if (player != null && targetName.equals(player.getName())) { - System.out.println("matched(option): " + s); - filtered.add(option); - return filtered; - } else { - Card target = game.getCard(option.getFirstTarget()); - if (target != null && target.getName().equals(targetName)) { + if (card != null) { + for (String s : suggested) { + String[] groups = s.split(";"); + logger.trace("s=" + s + ";groups=" + groups.length); + if (groups.length == 2) { + if (groups[0].equals(card.getName()) && groups[1].startsWith("name=")) { + // extract target and compare to suggested + String targetName = groups[1].split("=")[1]; + Player player = game.getPlayer(option.getFirstTarget()); + if (player != null && targetName.equals(player.getName())) { System.out.println("matched(option): " + s); filtered.add(option); return filtered; + } else { + Card target = game.getCard(option.getFirstTarget()); + if (target != null && target.getName().equals(targetName)) { + System.out.println("matched(option): " + s); + filtered.add(option); + return filtered; + } + System.out.println("not equal UUID for target, player=" + player); } - System.out.println("not equal UUID for target, player=" + player); } } } diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java index 395becdf94..4d6f2cb51d 100644 --- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java @@ -1,19 +1,7 @@ package mage.server.util; -import java.io.File; -import java.lang.reflect.Constructor; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - import mage.abilities.Ability; import mage.cards.Card; -import mage.cards.Cards; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; @@ -25,6 +13,16 @@ import mage.game.Game; import mage.players.Player; import mage.util.RandomUtil; +import java.io.File; +import java.lang.reflect.Constructor; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + /** * @author JayDi85 */ @@ -111,6 +109,9 @@ public final class SystemUtil { for (UUID cardID : cardsList) { Card card = game.getCard(cardID); + if (card == null) { + continue; + } // basic info (card + set) String cardInfo = card.getName() + " - " + card.getExpansionSetCode(); @@ -225,7 +226,7 @@ public final class SystemUtil { *
* Implementation note:
* 1. Read init.txt line by line
- * 2. Parse line using for searching groups like: [group 1] + * 2. Parse line using for searching groups like: [group 1] * 3. Parse line using the following format: line ::= * :::
* 4. If zone equals to 'hand', add card to player's library
@@ -537,8 +538,8 @@ public final class SystemUtil { /** * Get a diff between two dates * - * @param date1 the oldest date - * @param date2 the newest date + * @param date1 the oldest date + * @param date2 the newest date * @param timeUnit the unit in which you want the diff * @return the diff value, in the provided unit */ diff --git a/Mage.Sets/src/mage/cards/c/ChromeMox.java b/Mage.Sets/src/mage/cards/c/ChromeMox.java index b3b414ee19..75fd118e48 100644 --- a/Mage.Sets/src/mage/cards/c/ChromeMox.java +++ b/Mage.Sets/src/mage/cards/c/ChromeMox.java @@ -1,8 +1,5 @@ package mage.cards.c; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.Mana; import mage.ObjectColor; @@ -30,8 +27,11 @@ import mage.target.TargetCard; import mage.util.CardUtil; import mage.util.GameLog; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author Plopman */ public final class ChromeMox extends CardImpl { @@ -141,7 +141,7 @@ class ChromeMoxManaEffect extends ManaEffect { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { List imprinted = permanent.getImprinted(); - if (!imprinted.isEmpty()) { + if (imprinted != null && !imprinted.isEmpty()) { Card imprintedCard = game.getCard(imprinted.get(0)); if (imprintedCard != null) { ObjectColor color = imprintedCard.getColor(game); @@ -172,7 +172,7 @@ class ChromeMoxManaEffect extends ManaEffect { Player player = game.getPlayer(source.getControllerId()); if (permanent != null && player != null) { List imprinted = permanent.getImprinted(); - if (!imprinted.isEmpty()) { + if (imprinted != null && !imprinted.isEmpty()) { Card imprintedCard = game.getCard(imprinted.get(0)); if (imprintedCard != null) { Choice choice = new ChoiceColor(true); diff --git a/Mage.Sets/src/mage/cards/c/CloneShell.java b/Mage.Sets/src/mage/cards/c/CloneShell.java index 47b9d5f20a..84171a085b 100644 --- a/Mage.Sets/src/mage/cards/c/CloneShell.java +++ b/Mage.Sets/src/mage/cards/c/CloneShell.java @@ -115,7 +115,7 @@ class CloneShellDiesEffect extends OneShotEffect { Permanent permanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); if (permanent != null) { List imprinted = permanent.getImprinted(); - if (!imprinted.isEmpty()) { + if (imprinted != null && !imprinted.isEmpty()) { Card imprintedCard = game.getCard(imprinted.get(0)); if (imprintedCard != null) { imprintedCard.setFaceDown(false, game); diff --git a/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java b/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java new file mode 100644 index 0000000000..56818fd890 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java @@ -0,0 +1,144 @@ +package mage.cards.d; + +import mage.MageObject; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.mana.BasicManaEffect; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.command.emblems.DomriChaosBringerEmblem; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.stack.Spell; +import mage.target.targetpointer.FixedTarget; +import mage.watchers.Watcher; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DomriChaosBringer extends CardImpl { + + public DomriChaosBringer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.DOMRI); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5)); + + // +1: Add {R} or {G}. If that mana is spent on a creature spell, it gains riot. + // TODO: make this into a single ability, also make this, Generator Servant and Hall of the Bandit Lord work without card scope watchers + Mana mana = Mana.RedMana(1); + mana.setFlag(true); + Ability ability = new LoyaltyAbility(new BasicManaEffect(mana).setText("Add {R}. If that mana is spent on a creature spell, it gains riot"), 1); + this.addAbility(ability, new HallOfTheBanditLordWatcher(ability)); + mana = Mana.GreenMana(1); + mana.setFlag(true); + ability = new LoyaltyAbility(new BasicManaEffect(mana).setText("Add {G}. If that mana is spent on a creature spell, it gains riot"), 1); + this.addAbility(ability, new HallOfTheBanditLordWatcher(ability)); + + // −3: Look at the top four cards of your library. You may reveal up to two creature cards from among them and put them into your hand. Put the rest on the bottom of your library in a random order. + this.addAbility(new LoyaltyAbility(new LookLibraryAndPickControllerEffect( + new StaticValue(4), false, new StaticValue(2), + StaticFilters.FILTER_CARD_CREATURE, Zone.LIBRARY, false, + true, false, Zone.HAND, false, false, false + ).setText( + "Look at the top four cards of your library. " + + "You may reveal up to two creature cards from among them " + + "and put them into your hand. Put the rest on the bottom of your library " + + "in a random order." + ), -3)); + + // −8: You get an emblem with "At the beginning of each end step, create a 4/4 red and green Beast creature token with trample." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new DomriChaosBringerEmblem()), -8)); + } + + private DomriChaosBringer(final DomriChaosBringer card) { + super(card); + } + + @Override + public DomriChaosBringer copy() { + return new DomriChaosBringer(this); + } +} + +class HallOfTheBanditLordWatcher extends Watcher { + + private final Ability source; + private final List creatures = new ArrayList<>(); + + HallOfTheBanditLordWatcher(Ability source) { + super(HallOfTheBanditLordWatcher.class.getSimpleName(), WatcherScope.CARD); + this.source = source; + } + + private HallOfTheBanditLordWatcher(final HallOfTheBanditLordWatcher watcher) { + super(watcher); + this.creatures.addAll(watcher.creatures); + this.source = watcher.source; + } + + @Override + public HallOfTheBanditLordWatcher copy() { + return new HallOfTheBanditLordWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.MANA_PAID) { + MageObject target = game.getObject(event.getTargetId()); + if (event.getSourceId() != null + && event.getSourceId().equals(this.getSourceId()) + && target != null && target.isCreature() + && event.getFlag()) { + if (target instanceof Spell) { + this.creatures.add(((Spell) target).getCard().getId()); + } + } + } + if (event.getType() == GameEvent.EventType.COUNTERED) { + if (creatures.contains(event.getTargetId())) { + creatures.remove(event.getSourceId()); + } + } + if (event.getType() == GameEvent.EventType.ZONE_CHANGE) { + if (creatures.contains(event.getSourceId())) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + // spell was e.g. exiled and goes again to stack, so previous cast has not resolved. + if (zEvent.getToZone() == Zone.STACK) { + creatures.remove(event.getSourceId()); + } + } + } + if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { + if (creatures.contains(event.getSourceId())) { + ContinuousEffect effect = new GainAbilityTargetEffect(new RiotAbility(), Duration.Custom); + effect.setTargetPointer(new FixedTarget(event.getSourceId())); + game.addEffect(effect, source); + creatures.remove(event.getSourceId()); + } + } + } + + @Override + public void reset() { + super.reset(); + creatures.clear(); + } + +} diff --git a/Mage.Sets/src/mage/cards/d/Duplicant.java b/Mage.Sets/src/mage/cards/d/Duplicant.java index 4abfea60c3..6cbb058cdf 100644 --- a/Mage.Sets/src/mage/cards/d/Duplicant.java +++ b/Mage.Sets/src/mage/cards/d/Duplicant.java @@ -1,8 +1,5 @@ - package mage.cards.d; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -22,8 +19,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import java.util.List; +import java.util.UUID; + /** - * * @author Plopman */ public final class Duplicant extends CardImpl { @@ -117,6 +116,9 @@ class DuplicantContinuousEffect extends ContinuousEffectImpl { if (permanent != null) { if (!permanent.getImprinted().isEmpty()) { List imprinted = permanent.getImprinted(); + if (imprinted == null || imprinted.isEmpty()) { + return false; + } Card card = game.getCard(imprinted.get(imprinted.size() - 1)); if (card != null && card.isCreature()) { switch (layer) { @@ -134,7 +136,6 @@ class DuplicantContinuousEffect extends ContinuousEffectImpl { } } return true; - } } diff --git a/Mage.Sets/src/mage/cards/g/GuardianProject.java b/Mage.Sets/src/mage/cards/g/GuardianProject.java new file mode 100644 index 0000000000..6deeddafcb --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GuardianProject.java @@ -0,0 +1,152 @@ +package mage.cards.g; + +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.other.OwnerIdPredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GuardianProject extends CardImpl { + + public GuardianProject(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + + // Whenever a nontoken creature enters the battlefield under your control, if that creature does not have the same name as another creature you control or a creature card in your graveyard, draw a card. + this.addAbility(new GuardianProjectTriggeredAbility()); + } + + private GuardianProject(final GuardianProject card) { + super(card); + } + + @Override + public GuardianProject copy() { + return new GuardianProject(this); + } +} + +class GuardianProjectTriggeredAbility extends EntersBattlefieldAllTriggeredAbility { + + public static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(Predicates.not(new TokenPredicate())); + } + + GuardianProjectTriggeredAbility() { + super(new GuardianProjectEffect(null), filter); + } + + private GuardianProjectTriggeredAbility(final GuardianProjectTriggeredAbility ability) { + super(ability); + } + + @Override + public GuardianProjectTriggeredAbility copy() { + return new GuardianProjectTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + if (!filter.match(permanent, sourceId, controllerId, game)) { + return false; + } + + if (checkCondition(permanent, controllerId, game)) { + this.getEffects().clear(); + this.addEffect(new GuardianProjectEffect(new MageObjectReference(permanent, game))); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever a nontoken creature enters the battlefield under your control, " + + "if that creature does not have the same name as another creature you control " + + "or a creature card in your graveyard, draw a card."; + } + + // This is needed as checkInterveningIfClause can't access trigger event information + static boolean checkCondition(Permanent permanent, UUID controllerId, Game game) { + Player player = game.getPlayer(controllerId); + if (player == null) { + return false; + } + if (!permanent.getName().equals("")) { + FilterCard filterCard = new FilterCard(); + filterCard.add(new NamePredicate(permanent.getName())); + filterCard.add(new OwnerIdPredicate(controllerId)); + if (player.getGraveyard().count(filterCard, game) > 0) { + return false; + } + } + FilterPermanent filterPermanent = new FilterCreaturePermanent(); + filterPermanent.add(new NamePredicate(permanent.getName())); + filterPermanent.add(Predicates.not(new CardIdPredicate(permanent.getId()))); + filterPermanent.add(new ControllerIdPredicate(controllerId)); + if (game.getBattlefield().getActivePermanents(filterPermanent, controllerId, game).size() > 0) { + return false; + } + return true; + } +} + +class GuardianProjectEffect extends OneShotEffect { + + private final MageObjectReference mor; + + GuardianProjectEffect(MageObjectReference mor) { + super(Outcome.Benefit); + this.mor = mor; + } + + private GuardianProjectEffect(final GuardianProjectEffect effect) { + super(effect); + this.mor = effect.mor; + } + + @Override + public GuardianProjectEffect copy() { + return new GuardianProjectEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + if (GuardianProjectTriggeredAbility.checkCondition( + mor.getPermanentOrLKIBattlefield(game), source.getControllerId(), game) + ) { + player.drawCards(1, game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HintOfInsanity.java b/Mage.Sets/src/mage/cards/h/HintOfInsanity.java index 461575814c..a8b3958af2 100644 --- a/Mage.Sets/src/mage/cards/h/HintOfInsanity.java +++ b/Mage.Sets/src/mage/cards/h/HintOfInsanity.java @@ -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; diff --git a/Mage.Sets/src/mage/cards/k/KayasWrath.java b/Mage.Sets/src/mage/cards/k/KayasWrath.java new file mode 100644 index 0000000000..b42c1212d4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KayasWrath.java @@ -0,0 +1,69 @@ +package mage.cards.k; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KayasWrath extends CardImpl { + + public KayasWrath(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}{W}{B}{B}"); + + // Destroy all creatures. You gain life equal to the number of creatures you controlled that were destroyed this way. + this.getSpellAbility().addEffect(new KayasWrathEffect()); + } + + private KayasWrath(final KayasWrath card) { + super(card); + } + + @Override + public KayasWrath copy() { + return new KayasWrath(this); + } +} + +class KayasWrathEffect extends OneShotEffect { + + KayasWrathEffect() { + super(Outcome.Benefit); + staticText = "Destroy all creatures. You gain life equal to the number of " + + "creatures you controlled that were destroyed this way."; + } + + private KayasWrathEffect(final KayasWrathEffect effect) { + super(effect); + } + + @Override + public KayasWrathEffect copy() { + return new KayasWrathEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int counter = 0; + for (Permanent permanent : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_PERMANENT_CREATURE, + source.getControllerId(), source.getSourceId(), game + )) { + boolean isMine = permanent != null && permanent.getControllerId().equals(source.getControllerId()); + if (permanent.destroy(source.getSourceId(), game, false) && isMine) { + counter++; + } + } + return new GainLifeEffect(counter).apply(game, source); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/NamelessRace.java b/Mage.Sets/src/mage/cards/n/NamelessRace.java index e561b06936..cebf34c2e3 100644 --- a/Mage.Sets/src/mage/cards/n/NamelessRace.java +++ b/Mage.Sets/src/mage/cards/n/NamelessRace.java @@ -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; diff --git a/Mage.Sets/src/mage/cards/n/Nightsnare.java b/Mage.Sets/src/mage/cards/n/Nightsnare.java index 7a4517db4a..c189b8eedc 100644 --- a/Mage.Sets/src/mage/cards/n/Nightsnare.java +++ b/Mage.Sets/src/mage/cards/n/Nightsnare.java @@ -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)) { diff --git a/Mage.Sets/src/mage/cards/n/NikyaOfTheOldWays.java b/Mage.Sets/src/mage/cards/n/NikyaOfTheOldWays.java new file mode 100644 index 0000000000..cdb990392d --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NikyaOfTheOldWays.java @@ -0,0 +1,88 @@ +package mage.cards.n; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.TapForManaAllTriggeredManaAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.mana.AddManaOfAnyTypeProducedEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NikyaOfTheOldWays extends CardImpl { + + public NikyaOfTheOldWays(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.CENTAUR); + this.subtype.add(SubType.DRUID); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // You can't cast noncreature spells. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, new NikyaOfTheOldWaysCantCastEffect() + )); + + // Whenever you tap a land for mana, add one mana of any type that land produced. + AddManaOfAnyTypeProducedEffect effect = new AddManaOfAnyTypeProducedEffect(); + effect.setText("add one mana of any type that land produced"); + this.addAbility(new TapForManaAllTriggeredManaAbility( + effect, + new FilterControlledLandPermanent("you tap a land"), + SetTargetPointer.PERMANENT) + ); + } + + private NikyaOfTheOldWays(final NikyaOfTheOldWays card) { + super(card); + } + + @Override + public NikyaOfTheOldWays copy() { + return new NikyaOfTheOldWays(this); + } +} + +class NikyaOfTheOldWaysCantCastEffect extends ContinuousRuleModifyingEffectImpl { + + NikyaOfTheOldWaysCantCastEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + staticText = "You can't cast noncreature spells"; + } + + private NikyaOfTheOldWaysCantCastEffect(final NikyaOfTheOldWaysCantCastEffect effect) { + super(effect); + } + + @Override + public NikyaOfTheOldWaysCantCastEffect copy() { + return new NikyaOfTheOldWaysCantCastEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getPlayerId().equals(source.getControllerId())) { + Card card = game.getCard(event.getSourceId()); + return card != null && !card.isCreature(); + } + return false; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/NoContest.java b/Mage.Sets/src/mage/cards/n/NoContest.java index 1298ece808..5a2f142127 100644 --- a/Mage.Sets/src/mage/cards/n/NoContest.java +++ b/Mage.Sets/src/mage/cards/n/NoContest.java @@ -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(); diff --git a/Mage.Sets/src/mage/cards/p/PastInFlames.java b/Mage.Sets/src/mage/cards/p/PastInFlames.java index 77ac3bb1d2..627aa8791b 100644 --- a/Mage.Sets/src/mage/cards/p/PastInFlames.java +++ b/Mage.Sets/src/mage/cards/p/PastInFlames.java @@ -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; diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianProcessor.java b/Mage.Sets/src/mage/cards/p/PhyrexianProcessor.java index dc33388f9a..20b78322d0 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianProcessor.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianProcessor.java @@ -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); diff --git a/Mage.Sets/src/mage/cards/p/PlagueOfVermin.java b/Mage.Sets/src/mage/cards/p/PlagueOfVermin.java index 05652917b5..0a5dd16f1e 100644 --- a/Mage.Sets/src/mage/cards/p/PlagueOfVermin.java +++ b/Mage.Sets/src/mage/cards/p/PlagueOfVermin.java @@ -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 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; diff --git a/Mage.Sets/src/mage/cards/p/PostmortemLunge.java b/Mage.Sets/src/mage/cards/p/PostmortemLunge.java index 65a32494f1..6372d91cf1 100644 --- a/Mage.Sets/src/mage/cards/p/PostmortemLunge.java +++ b/Mage.Sets/src/mage/cards/p/PostmortemLunge.java @@ -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; } } diff --git a/Mage.Sets/src/mage/cards/p/PutAway.java b/Mage.Sets/src/mage/cards/p/PutAway.java index b67ccad8ac..0f4c6da129 100644 --- a/Mage.Sets/src/mage/cards/p/PutAway.java +++ b/Mage.Sets/src/mage/cards/p/PutAway.java @@ -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); diff --git a/Mage.Sets/src/mage/cards/r/RakdosAugermage.java b/Mage.Sets/src/mage/cards/r/RakdosAugermage.java index 422d4c3291..3fa747f9f5 100644 --- a/Mage.Sets/src/mage/cards/r/RakdosAugermage.java +++ b/Mage.Sets/src/mage/cards/r/RakdosAugermage.java @@ -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); } } } diff --git a/Mage.Sets/src/mage/cards/r/RenownedWeaponsmith.java b/Mage.Sets/src/mage/cards/r/RenownedWeaponsmith.java index ed31ed8cc0..8898379400 100644 --- a/Mage.Sets/src/mage/cards/r/RenownedWeaponsmith.java +++ b/Mage.Sets/src/mage/cards/r/RenownedWeaponsmith.java @@ -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); diff --git a/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java b/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java index 4b6a0acc3f..dba8d34db8 100644 --- a/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java +++ b/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java @@ -1,8 +1,5 @@ - package mage.cards.s; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -21,6 +18,9 @@ import mage.players.Player; import mage.target.TargetCard; import mage.util.CardUtil; +import java.util.List; +import java.util.UUID; + /** * @author nantuko */ @@ -113,11 +113,9 @@ class SemblanceAnvilCostReductionEffect extends CostModificationEffectImpl { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { List imprinted = permanent.getImprinted(); - if (!imprinted.isEmpty()) { + if (imprinted != null && !imprinted.isEmpty()) { Card imprintedCard = game.getCard(imprinted.get(0)); - if (imprintedCard != null && imprintedCard.shareTypes(sourceCard)) { - return true; - } + return imprintedCard != null && imprintedCard.shareTypes(sourceCard); } } } diff --git a/Mage.Sets/src/mage/cards/s/SereneRemembrance.java b/Mage.Sets/src/mage/cards/s/SereneRemembrance.java index 15c9014ab8..b805b2f3b5 100644 --- a/Mage.Sets/src/mage/cards/s/SereneRemembrance.java +++ b/Mage.Sets/src/mage/cards/s/SereneRemembrance.java @@ -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; } } diff --git a/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java b/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java index 6e0d7d255f..5af0b2937e 100644 --- a/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java +++ b/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java @@ -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 diff --git a/Mage.Sets/src/mage/cards/s/ShroudedLore.java b/Mage.Sets/src/mage/cards/s/ShroudedLore.java index 16abab99ed..b4042febd6 100644 --- a/Mage.Sets/src/mage/cards/s/ShroudedLore.java +++ b/Mage.Sets/src/mage/cards/s/ShroudedLore.java @@ -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); diff --git a/Mage.Sets/src/mage/cards/s/SistersOfStoneDeath.java b/Mage.Sets/src/mage/cards/s/SistersOfStoneDeath.java index c32c0bcd37..ab178a600c 100644 --- a/Mage.Sets/src/mage/cards/s/SistersOfStoneDeath.java +++ b/Mage.Sets/src/mage/cards/s/SistersOfStoneDeath.java @@ -1,8 +1,5 @@ - package mage.cards.s; -import java.util.LinkedList; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -14,11 +11,7 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.CardsImpl; -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.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; @@ -30,8 +23,10 @@ import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetCreaturePermanent; +import java.util.LinkedList; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class SistersOfStoneDeath extends CardImpl { @@ -39,7 +34,7 @@ public final class SistersOfStoneDeath extends CardImpl { private UUID exileId = UUID.randomUUID(); public SistersOfStoneDeath(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}{G}{G}"); this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.GORGON); @@ -100,7 +95,9 @@ class SistersOfStoneDeathEffect extends OneShotEffect { LinkedList cards = new LinkedList<>(exile); for (UUID cardId : cards) { Card card = game.getCard(cardId); - cardsInExile.add(card); + if (card != null) { + cardsInExile.add(card); + } } if (controller.choose(Outcome.PutCreatureInPlay, cardsInExile, target, game)) { Card chosenCard = game.getCard(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java b/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java new file mode 100644 index 0000000000..690a8c7f3b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java @@ -0,0 +1,97 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SphinxOfNewPrahv extends CardImpl { + + public SphinxOfNewPrahv(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}{U}{U}"); + + this.subtype.add(SubType.SPHINX); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Spells your opponents cast that target Sphinx of New Prahv cost {2} more to cast. + this.addAbility(new SimpleStaticAbility(new SphinxOfNewPrahvCostIncreaseEffect())); + } + + private SphinxOfNewPrahv(final SphinxOfNewPrahv card) { + super(card); + } + + @Override + public SphinxOfNewPrahv copy() { + return new SphinxOfNewPrahv(this); + } +} + +class SphinxOfNewPrahvCostIncreaseEffect extends CostModificationEffectImpl { + + SphinxOfNewPrahvCostIncreaseEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); + staticText = "Spells your opponents cast that target {this} cost {2} more to cast"; + } + + private SphinxOfNewPrahvCostIncreaseEffect(SphinxOfNewPrahvCostIncreaseEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + SpellAbility spellAbility = (SpellAbility) abilityToModify; + CardUtil.adjustCost(spellAbility, -2); + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null + || !(abilityToModify instanceof SpellAbility) + || !controller.hasOpponent(abilityToModify.getControllerId(), game)) { + return false; + } + for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { + Mode mode = abilityToModify.getModes().get(modeId); + for (Target target : mode.getTargets()) { + for (UUID targetUUID : target.getTargets()) { + if (targetUUID.equals(source.getSourceId())) { + return true; + } + } + } + } + return false; + } + + @Override + public SphinxOfNewPrahvCostIncreaseEffect copy() { + return new SphinxOfNewPrahvCostIncreaseEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfTheChimes.java b/Mage.Sets/src/mage/cards/s/SphinxOfTheChimes.java index 5d81e77616..07a1884826 100644 --- a/Mage.Sets/src/mage/cards/s/SphinxOfTheChimes.java +++ b/Mage.Sets/src/mage/cards/s/SphinxOfTheChimes.java @@ -1,22 +1,12 @@ - package mage.cards.s; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.FlyingAbility; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; -import mage.cards.SplitCard; +import mage.cards.*; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; @@ -27,8 +17,12 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInHand; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SphinxOfTheChimes extends CardImpl { @@ -91,7 +85,7 @@ class TargetTwoNonLandCardsWithSameNameInHand extends TargetCardInHand { Set newPossibleTargets = new HashSet<>(); Set possibleTargets = new HashSet<>(); Player player = game.getPlayer(sourceControllerId); - if(player == null){ + if (player == null) { return newPossibleTargets; } for (Card card : player.getHand().getCards(filter, game)) { @@ -116,9 +110,11 @@ class TargetTwoNonLandCardsWithSameNameInHand extends TargetCardInHand { for (UUID cardToCheck : cardsToCheck) { FilterCard nameFilter = new FilterCard(); Card card = game.getCard(cardToCheck); - nameFilter.add(new NamePredicate(card.isSplitCard() ? ((SplitCard) card).getLeftHalfCard().getName() : card.getName())); - if (cardsToCheck.count(nameFilter, game) > 1) { - newPossibleTargets.add(cardToCheck); + if (card != null) { + nameFilter.add(new NamePredicate(card.isSplitCard() ? ((SplitCard) card).getLeftHalfCard().getName() : card.getName())); + if (cardsToCheck.count(nameFilter, game) > 1) { + newPossibleTargets.add(cardToCheck); + } } } } @@ -129,7 +125,7 @@ class TargetTwoNonLandCardsWithSameNameInHand extends TargetCardInHand { public boolean canChoose(UUID sourceControllerId, Game game) { Cards cardsToCheck = new CardsImpl(); Player player = game.getPlayer(sourceControllerId); - if(player == null){ + if (player == null) { return false; } for (Card card : player.getHand().getCards(filter, game)) { @@ -153,16 +149,12 @@ class TargetTwoNonLandCardsWithSameNameInHand extends TargetCardInHand { if (card != null) { if (targets.size() == 1) { Card card2 = game.getCard(targets.entrySet().iterator().next().getKey()); - if (card2 != null && card2.getName().equals(card.getName())) { - return true; - } + return card2 != null && card2.getName().equals(card.getName()); } else { FilterCard nameFilter = new FilterCard(); nameFilter.add(new NamePredicate(card.isSplitCard() ? ((SplitCard) card).getLeftHalfCard().getName() : card.getName())); Player player = game.getPlayer(card.getOwnerId()); - if (player != null && player.getHand().getCards(nameFilter, game).size() > 1) { - return true; - } + return player != null && player.getHand().getCards(nameFilter, game).size() > 1; } } } diff --git a/Mage.Sets/src/mage/cards/s/SteamVines.java b/Mage.Sets/src/mage/cards/s/SteamVines.java index 5861920b9b..317d2ba47b 100644 --- a/Mage.Sets/src/mage/cards/s/SteamVines.java +++ b/Mage.Sets/src/mage/cards/s/SteamVines.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BecomesTappedAttachedTriggeredAbility; import mage.abilities.effects.Effect; @@ -24,8 +22,9 @@ import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author jeffwadsworth & L_J */ public final class SteamVines extends CardImpl { @@ -76,7 +75,6 @@ class SteamVinesEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent steamVines = game.getPermanentOrLKIBattlefield(source.getSourceId()); - Card steamVinesCard = game.getCard(source.getSourceId()); if (steamVines != null) { Permanent enchantedLand = game.getPermanentOrLKIBattlefield(steamVines.getAttachedTo()); Player controller = game.getPlayer(source.getControllerId()); @@ -85,15 +83,15 @@ class SteamVinesEffect extends OneShotEffect { Player landsController = game.getPlayer(enchantedLand.getControllerId()); if (game.getState().getZone(enchantedLand.getId()) == Zone.BATTLEFIELD) { // if 2 or more Steam Vines were on a land enchantedLand.destroy(source.getId(), game, false); - if(landsController != null) { + if (landsController != null) { landsController.damage(1, source.getSourceId(), game, false, true); } } if (!game.getBattlefield().getAllActivePermanents(CardType.LAND).isEmpty()) { //lands are available on the battlefield Target target = new TargetLandPermanent(); target.setNotTarget(true); //not a target, it is chosen - if (steamVinesCard != null - && landsController != null) { + Card steamVinesCard = game.getCard(source.getSourceId()); + if (steamVinesCard != null && landsController != null) { if (landsController.choose(Outcome.DestroyPermanent, target, source.getId(), game)) { if (target.getFirstTarget() != null) { Permanent landChosen = game.getPermanent(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java b/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java index 723ea2cc6e..e1f0e8ff73 100644 --- a/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java +++ b/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java @@ -1,11 +1,11 @@ - package mage.cards.s; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.*; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SuperType; @@ -21,8 +21,10 @@ import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInLibrary; +import java.util.List; +import java.util.UUID; + /** - * * @author North */ public final class SurgicalExtraction extends CardImpl { @@ -71,12 +73,12 @@ class SurgicalExtractionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Card chosenCard = game.getCard(source.getFirstTarget()); - Player controller = game.getPlayer(source.getControllerId()); - // 6/1/2011 "Any number of cards" means just that. If you wish, you can choose to // leave some or all of the cards with the same name as the targeted card, // including that card, in the zone they're in. + + Card chosenCard = game.getCard(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); if (chosenCard != null && controller != null) { Player owner = game.getPlayer(chosenCard.getOwnerId()); if (owner != null) { diff --git a/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java b/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java index be586c41a5..a43e9d15c3 100644 --- a/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java +++ b/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -17,14 +15,15 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class TeferiMageOfZhalfir extends CardImpl { public TeferiMageOfZhalfir(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}{U}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -76,14 +75,14 @@ class TeferiMageOfZhalfirAddFlashEffect extends ContinuousEffectImpl { // in graveyard for (UUID cardId : controller.getGraveyard()) { Card card = game.getCard(cardId); - if (card.isCreature()) { + if (card != null && card.isCreature()) { game.getState().addOtherAbility(card, FlashAbility.getInstance()); } } // on Hand for (UUID cardId : controller.getHand()) { Card card = game.getCard(cardId); - if (card.isCreature()) { + if (card != null && card.isCreature()) { game.getState().addOtherAbility(card, FlashAbility.getInstance()); } } @@ -103,7 +102,7 @@ class TeferiMageOfZhalfirAddFlashEffect extends ContinuousEffectImpl { for (UUID commanderId : controller.getCommandersIds()) { if (game.getState().getZone(commanderId) == Zone.COMMAND) { Card card = game.getCard(commanderId); - if (card.isCreature()) { + if (card != null && card.isCreature()) { game.getState().addOtherAbility(card, FlashAbility.getInstance()); } } diff --git a/Mage.Sets/src/mage/cards/t/TravelingPlague.java b/Mage.Sets/src/mage/cards/t/TravelingPlague.java index d079c2c44b..fdc09f1d2c 100644 --- a/Mage.Sets/src/mage/cards/t/TravelingPlague.java +++ b/Mage.Sets/src/mage/cards/t/TravelingPlague.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -18,12 +16,7 @@ import mage.abilities.keyword.EnchantAbility; 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.SubType; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; @@ -34,8 +27,9 @@ import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class TravelingPlague extends CardImpl { @@ -130,10 +124,10 @@ class TravelingPlagueEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Card travelingPlague = game.getCard(source.getSourceId()); Permanent enchantedCreature = (Permanent) game.getState().getValue("travelingPlague" + source.getSourceId()); if (enchantedCreature != null) { Player controllerOfEnchantedCreature = game.getPlayer(enchantedCreature.getControllerId()); + Card travelingPlague = game.getCard(source.getSourceId()); if (travelingPlague != null && game.getState().getZone(travelingPlague.getId()) == Zone.GRAVEYARD // aura must come from the graveyard && controllerOfEnchantedCreature != null) { diff --git a/Mage.Sets/src/mage/cards/t/TrenchGorger.java b/Mage.Sets/src/mage/cards/t/TrenchGorger.java index fd5692290f..6b2b53ec04 100644 --- a/Mage.Sets/src/mage/cards/t/TrenchGorger.java +++ b/Mage.Sets/src/mage/cards/t/TrenchGorger.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -11,25 +9,21 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterLandCard; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class TrenchGorger extends CardImpl { public TrenchGorger(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{U}{U}"); this.subtype.add(SubType.LEVIATHAN); this.power = new MageInt(6); @@ -77,8 +71,10 @@ class TrenchGorgerEffect extends OneShotEffect { int count = 0; for (UUID cardId : target.getTargets()) { Card card = game.getCard(cardId); - controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.LIBRARY, true); - count++; + if (card != null) { + controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.LIBRARY, true); + count++; + } } controller.shuffleLibrary(source, game); game.addEffect(new SetPowerToughnessSourceEffect(count, count, Duration.EndOfGame, SubLayer.SetPT_7b), source); diff --git a/Mage.Sets/src/mage/cards/v/VolrathsDungeon.java b/Mage.Sets/src/mage/cards/v/VolrathsDungeon.java index f3dbd4513a..c70ab8f159 100644 --- a/Mage.Sets/src/mage/cards/v/VolrathsDungeon.java +++ b/Mage.Sets/src/mage/cards/v/VolrathsDungeon.java @@ -1,6 +1,5 @@ package mage.cards.v; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; import mage.abilities.common.ActivateAsSorceryActivatedAbility; @@ -25,8 +24,9 @@ import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetCardInHand; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class VolrathsDungeon extends CardImpl { @@ -65,7 +65,7 @@ class PayLifeActivePlayerCost extends CostImpl { public PayLifeActivePlayerCost(int amount) { this.amount = new StaticValue(amount); - this.text = "Pay " + Integer.toString(amount) + " life"; + this.text = "Pay " + amount + " life"; } public PayLifeActivePlayerCost(DynamicValue amount, String text) { @@ -89,9 +89,9 @@ class PayLifeActivePlayerCost extends CostImpl { int lifeToPayAmount = amount.calculate(game, ability, null); Player activatingPlayer = game.getPlayer(game.getActivePlayerId()); if (activatingPlayer != null - && activatingPlayer.chooseUse(Outcome.LoseLife, "Do you wish to pay "+ lifeToPayAmount +" life?", ability, game)) { + && activatingPlayer.chooseUse(Outcome.LoseLife, "Do you wish to pay " + lifeToPayAmount + " life?", ability, game)) { Player player = game.getPlayer(game.getActivePlayerId()); - if(player != null) { + if (player != null) { this.paid = player.loseLife(lifeToPayAmount, game, false) == lifeToPayAmount; } } @@ -127,7 +127,7 @@ class VolrathsDungeonEffect extends OneShotEffect { TargetCardInHand target = new TargetCardInHand(); if (targetedPlayer.choose(Outcome.Detriment, targetedPlayer.getHand(), target, game)) { Card card = game.getCard(target.getFirstTarget()); - return targetedPlayer.putCardOnTopXOfLibrary(card, game, source, 0); + return card != null && targetedPlayer.putCardOnTopXOfLibrary(card, game, source, 0); } } return false; diff --git a/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java b/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java index a1d1d16c90..3670b8a32a 100644 --- a/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java +++ b/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java @@ -1,7 +1,5 @@ package mage.cards.y; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.LegendarySpellAbility; import mage.abilities.effects.OneShotEffect; @@ -9,7 +7,10 @@ import mage.abilities.effects.common.ExileSpellEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.Zone; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; import mage.filter.common.FilterPermanentCard; import mage.filter.predicate.Predicates; @@ -20,6 +21,8 @@ import mage.players.Player; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCreatureOrPlaneswalker; +import java.util.UUID; + /** * @author JRHerlehy Created on 4/8/18. */ @@ -78,7 +81,6 @@ class YawgmothsVileOfferingEffect extends OneShotEffect { } Card returnCard = game.getCard(source.getTargets().getFirstTarget()); - if (returnCard != null) { controller.moveCards(returnCard, Zone.BATTLEFIELD, source, game); } diff --git a/Mage.Sets/src/mage/sets/RavnicaAllegiance.java b/Mage.Sets/src/mage/sets/RavnicaAllegiance.java index 10eabc8225..1194aed485 100644 --- a/Mage.Sets/src/mage/sets/RavnicaAllegiance.java +++ b/Mage.Sets/src/mage/sets/RavnicaAllegiance.java @@ -56,6 +56,7 @@ public final class RavnicaAllegiance extends ExpansionSet { cards.add(new SetCardInfo("Cry of the Carnarium", 70, Rarity.UNCOMMON, mage.cards.c.CryOfTheCarnarium.class)); cards.add(new SetCardInfo("Depose // Deploy", 225, Rarity.UNCOMMON, mage.cards.d.DeposeDeploy.class)); cards.add(new SetCardInfo("Deputy of Detention", 165, Rarity.RARE, mage.cards.d.DeputyOfDetention.class)); + cards.add(new SetCardInfo("Domri, Chaos Bringer", 166, Rarity.MYTHIC, mage.cards.d.DomriChaosBringer.class)); cards.add(new SetCardInfo("Dovin, Grand Arbiter", 167, Rarity.MYTHIC, mage.cards.d.DovinGrandArbiter.class)); cards.add(new SetCardInfo("Drill Bit", 73, Rarity.UNCOMMON, mage.cards.d.DrillBit.class)); cards.add(new SetCardInfo("Electrodominance", 99, Rarity.RARE, mage.cards.e.Electrodominance.class)); @@ -73,6 +74,7 @@ public final class RavnicaAllegiance extends ExpansionSet { cards.add(new SetCardInfo("Gruul Guildgate", 250, Rarity.COMMON, mage.cards.g.GruulGuildgate.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Gruul Locket", 234, Rarity.COMMON, mage.cards.g.GruulLocket.class)); cards.add(new SetCardInfo("Gruul Spellbreaker", 179, Rarity.RARE, mage.cards.g.GruulSpellbreaker.class)); + cards.add(new SetCardInfo("Guardian Project", 130, Rarity.RARE, mage.cards.g.GuardianProject.class)); cards.add(new SetCardInfo("Gutterbones", 76, Rarity.RARE, mage.cards.g.Gutterbones.class)); cards.add(new SetCardInfo("Hackrobat", 181, Rarity.UNCOMMON, mage.cards.h.Hackrobat.class)); cards.add(new SetCardInfo("Hallowed Fountain", 251, Rarity.RARE, mage.cards.h.HallowedFountain.class)); @@ -82,6 +84,7 @@ public final class RavnicaAllegiance extends ExpansionSet { cards.add(new SetCardInfo("Imperious Oligarch", 184, Rarity.COMMON, mage.cards.i.ImperiousOligarch.class)); cards.add(new SetCardInfo("Incubation // Incongruity", 226, Rarity.UNCOMMON, mage.cards.i.IncubationIncongruity.class)); cards.add(new SetCardInfo("Judith, the Scourge Diva", 185, Rarity.RARE, mage.cards.j.JudithTheScourgeDiva.class)); + cards.add(new SetCardInfo("Kaya's Wrath", 187, Rarity.RARE, mage.cards.k.KayasWrath.class)); cards.add(new SetCardInfo("Kaya, Orzhov Usurper", 186, Rarity.MYTHIC, mage.cards.k.KayaOrzhovUsurper.class)); cards.add(new SetCardInfo("Lavinia, Azorius Renegade", 189, Rarity.RARE, mage.cards.l.LaviniaAzoriusRenegade.class)); cards.add(new SetCardInfo("Light Up the Stage", 107, Rarity.UNCOMMON, mage.cards.l.LightUpTheStage.class)); @@ -89,6 +92,7 @@ public final class RavnicaAllegiance extends ExpansionSet { cards.add(new SetCardInfo("Mesmerizing Benthid", 43, Rarity.MYTHIC, mage.cards.m.MesmerizingBenthid.class)); cards.add(new SetCardInfo("Ministrant of Obligation", 16, Rarity.UNCOMMON, mage.cards.m.MinistrantOfObligation.class)); cards.add(new SetCardInfo("Mortify", 192, Rarity.UNCOMMON, mage.cards.m.Mortify.class)); + cards.add(new SetCardInfo("Nikya of the Old Ways", 193, Rarity.RARE, mage.cards.n.NikyaOfTheOldWays.class)); cards.add(new SetCardInfo("Orzhov Guildgate", 252, Rarity.COMMON, mage.cards.o.OrzhovGuildgate.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Orzhov Guildgate", 253, Rarity.COMMON, mage.cards.o.OrzhovGuildgate.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Orzhov Locket", 236, Rarity.COMMON, mage.cards.o.OrzhovLocket.class)); @@ -123,6 +127,7 @@ public final class RavnicaAllegiance extends ExpansionSet { cards.add(new SetCardInfo("Smothering Tithe", 22, Rarity.RARE, mage.cards.s.SmotheringTithe.class)); cards.add(new SetCardInfo("Spawn of Mayhem", 85, Rarity.MYTHIC, mage.cards.s.SpawnOfMayhem.class)); cards.add(new SetCardInfo("Sphinx of Foresight", 55, Rarity.RARE, mage.cards.s.SphinxOfForesight.class)); + cards.add(new SetCardInfo("Sphinx of New Prahv", 208, Rarity.UNCOMMON, mage.cards.s.SphinxOfNewPrahv.class)); cards.add(new SetCardInfo("Sphinx's Insight", 209, Rarity.COMMON, mage.cards.s.SphinxsInsight.class)); cards.add(new SetCardInfo("Stomping Ground", 259, Rarity.RARE, mage.cards.s.StompingGround.class)); cards.add(new SetCardInfo("Syndicate Guildmage", 211, Rarity.UNCOMMON, mage.cards.s.SyndicateGuildmage.class)); diff --git a/Mage/src/main/java/mage/abilities/SpellAbility.java b/Mage/src/main/java/mage/abilities/SpellAbility.java index 201d2deb34..d96699bf3b 100644 --- a/Mage/src/main/java/mage/abilities/SpellAbility.java +++ b/Mage/src/main/java/mage/abilities/SpellAbility.java @@ -1,8 +1,5 @@ - package mage.abilities; -import java.util.Optional; -import java.util.UUID; import mage.MageObject; import mage.MageObjectReference; import mage.abilities.costs.Cost; @@ -12,17 +9,15 @@ import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.keyword.FlashAbility; import mage.cards.Card; import mage.cards.SplitCard; -import mage.constants.AbilityType; -import mage.constants.AsThoughEffectType; -import mage.constants.SpellAbilityCastMode; -import mage.constants.SpellAbilityType; -import mage.constants.TimingRule; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.players.Player; +import java.util.Optional; +import java.util.UUID; + /** * @author BetaSteward_at_googlemail.com */ @@ -224,12 +219,16 @@ public class SpellAbility extends ActivatedAbilityImpl { if (event.getType() != GameEvent.EventType.CAST_SPELL) { return null; } + Card card = game.getCard(event.getSourceId()); - Optional ability = card.getAbilities(game).get(event.getTargetId()); - if (ability.isPresent() && ability.get() instanceof SpellAbility) { - return (SpellAbility) ability.get(); + if (card != null) { + Optional ability = card.getAbilities(game).get(event.getTargetId()); + if (ability.isPresent() && ability.get() instanceof SpellAbility) { + return (SpellAbility) ability.get(); + } + return card.getSpellAbility(); } - return card.getSpellAbility(); + return null; } public void setId(UUID idToUse) { diff --git a/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java b/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java index 44fa2a8a5e..bd23597969 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java @@ -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; } diff --git a/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java b/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java index 6ce501563f..c6c26c43cd 100644 --- a/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java @@ -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." # - * + *

* 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). # - * + *

* 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; } } diff --git a/Mage/src/main/java/mage/game/command/emblems/DomriChaosBringerEmblem.java b/Mage/src/main/java/mage/game/command/emblems/DomriChaosBringerEmblem.java new file mode 100644 index 0000000000..416cae15e1 --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/DomriChaosBringerEmblem.java @@ -0,0 +1,23 @@ +package mage.game.command.emblems; + +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.constants.TargetController; +import mage.game.command.Emblem; +import mage.game.permanent.token.SoldierToken; + +/** + * @author TheElk801 + */ +public final class DomriChaosBringerEmblem extends Emblem { + + // -8: You get an emblem with "At the beginning of each end step, create a 4/4 red and green Beast creature token with trample." + public DomriChaosBringerEmblem() { + this.setName("Emblem Domri"); + this.setExpansionSetCodeForImage("RNA"); + this.getAbilities().add(new BeginningOfEndStepTriggeredAbility( + new CreateTokenEffect(new SoldierToken()), + TargetController.ANY, false + )); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/DomriChaosBringerToken.java b/Mage/src/main/java/mage/game/permanent/token/DomriChaosBringerToken.java new file mode 100644 index 0000000000..34bf7f690a --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/DomriChaosBringerToken.java @@ -0,0 +1,33 @@ + +package mage.game.permanent.token; + +import mage.MageInt; +import mage.abilities.keyword.TrampleAbility; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * @author TheElk801 + */ +public final class DomriChaosBringerToken extends TokenImpl { + + public DomriChaosBringerToken() { + super("Beast", "4/4 red and green Beast creature token with trample"); + cardType.add(CardType.CREATURE); + color.setRed(true); + color.setGreen(true); + subtype.add(SubType.BEAST); + power = new MageInt(4); + toughness = new MageInt(4); + + this.addAbility(TrampleAbility.getInstance()); + } + + private DomriChaosBringerToken(final DomriChaosBringerToken token) { + super(token); + } + + public DomriChaosBringerToken copy() { + return new DomriChaosBringerToken(this); + } +} diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 6a6eda0b92..6ff3332301 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -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());