Merge origin/master

This commit is contained in:
Styxo 2016-03-30 22:23:11 +02:00
commit 7ec91d55bb
26 changed files with 716 additions and 22 deletions

View file

@ -28,11 +28,16 @@
package mage.sets.shadowsoverinnistrad;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
@ -52,8 +57,14 @@ public class AshmouthBlade extends CardImpl {
// this card is the second face of double-faced card
this.nightCard = true;
// Equipped creature gets +3/+3.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 3)));
// Equipped creature gets +3/+3
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 3));
this.addAbility(ability);
// and has first strike.
Effect effect = new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT);
effect.setText("and has first strike");
ability.addEffect(effect);
// Equip {3}
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3)));

View file

@ -91,7 +91,7 @@ class BriarbridgePatrolCondition implements Condition {
PermanentsSacrificedWatcher watcher = (PermanentsSacrificedWatcher) game.getState().getWatchers().get(PermanentsSacrificedWatcher.class.getName());
if (watcher != null) {
List<Permanent> sacrificedPermanents = watcher.getThisTurnSacrificedPermanents(source.getControllerId());
if (!sacrificedPermanents.isEmpty()) {
if (sacrificedPermanents != null && !sacrificedPermanents.isEmpty()) {
int amountOfClues = 0;
for (Permanent permanent : sacrificedPermanents) {
if (permanent.getSubtype().contains("Clue")) {

View file

@ -60,7 +60,7 @@ public class ConfrontTheUnknown extends CardImpl {
Effect effect = new InvestigateEffect();
effect.setText("Investigate");
getSpellAbility().addEffect(effect);
effect = new BoostTargetEffect(new PermanentsOnBattlefieldCount(filter), new PermanentsOnBattlefieldCount(filter), Duration.EndOfTurn);
effect = new BoostTargetEffect(new PermanentsOnBattlefieldCount(filter), new PermanentsOnBattlefieldCount(filter), Duration.EndOfTurn, true);
effect.setText(", then target creature gets +1/+1 until end of turn for each Clue you control. <i>(To investigate, "
+ "put a colorless Clue artifact token onto the battlefield with \"{2}, Sacrifice this artifact: Draw a card.\")</i>");
getSpellAbility().addEffect(effect);

View file

@ -54,6 +54,7 @@ public class FlameheartWerewolf extends CardImpl {
this.subtype.add("Werewolf");
this.power = new MageInt(3);
this.toughness = new MageInt(2);
this.color.setRed(true);
// this card is the second face of double-faced card
this.nightCard = true;

View file

@ -29,16 +29,19 @@ package mage.sets.shadowsoverinnistrad;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SacrificeAllTriggeredAbility;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveTargetEffect;
import mage.abilities.effects.keyword.InvestigateEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.target.TargetPlayer;
/**
@ -61,7 +64,7 @@ public class FleetingMemories extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new InvestigateEffect(), false));
// Whenever you sacrifice a Clue, target player puts the top three cards of his or her graveyard into his or her graveyard.
Ability ability = new SacrificeAllTriggeredAbility(new PutTopCardOfLibraryIntoGraveTargetEffect(3), filter, TargetController.YOU, false);
Ability ability = new FleetingMemoriesTriggeredAbility();
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
@ -75,3 +78,36 @@ public class FleetingMemories extends CardImpl {
return new FleetingMemories(this);
}
}
class FleetingMemoriesTriggeredAbility extends TriggeredAbilityImpl {
public FleetingMemoriesTriggeredAbility() {
super(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveTargetEffect(3));
setLeavesTheBattlefieldTrigger(true);
}
public FleetingMemoriesTriggeredAbility(final FleetingMemoriesTriggeredAbility ability) {
super(ability);
}
@Override
public FleetingMemoriesTriggeredAbility copy() {
return new FleetingMemoriesTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.SACRIFICED_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getPlayerId().equals(this.getControllerId())
&& game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue");
}
@Override
public String getRule() {
return "Whenever you sacrifice a Clue, " + super.getRule();
}
}

View file

@ -54,6 +54,8 @@ public class GatstafRavagers extends CardImpl {
this.power = new MageInt(6);
this.toughness = new MageInt(5);
this.color.setRed(true);
this.canTransform = true;
this.nightCard = true;

View file

@ -0,0 +1,108 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.shadowsoverinnistrad;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author halljared
*/
public class HarvestHand extends CardImpl {
public HarvestHand(UUID ownerId) {
super(ownerId, 256, "Harvest Hand", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
this.expansionSetCode = "SOI";
this.subtype.add("Scarecrow");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.canTransform = true;
this.secondSideCard = new ScroungedScythe(ownerId);
// When Harvest Hand dies, return it to the battlefield transformed under your control.
this.addAbility(new TransformAbility());
this.addAbility(new DiesTriggeredAbility(new HarvestHandReturnTransformedEffect()));
}
public HarvestHand(final HarvestHand card) {
super(card);
}
@Override
public HarvestHand copy() {
return new HarvestHand(this);
}
}
class HarvestHandReturnTransformedEffect extends OneShotEffect {
public HarvestHandReturnTransformedEffect() {
super(Outcome.PutCardInPlay);
this.staticText = "Return {this} to the battlefield transformed under your control";
}
public HarvestHandReturnTransformedEffect(final HarvestHandReturnTransformedEffect effect) {
super(effect);
}
@Override
public HarvestHandReturnTransformedEffect copy() {
return new HarvestHandReturnTransformedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
if (game.getState().getZone(source.getSourceId()).equals(Zone.GRAVEYARD)) {
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
Card card = game.getCard(source.getSourceId());
if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
}
return true;
}
return false;
}
}

View file

@ -51,6 +51,7 @@ public class IncitedRabble extends CardImpl {
this.subtype.add("Human");
this.power = new MageInt(2);
this.toughness = new MageInt(3);
this.color.setRed(true);
// this card is the second face of double-faced card
this.nightCard = true;

View file

@ -56,6 +56,7 @@ public class LoneWolfOfTheNatterknolls extends CardImpl {
this.subtype.add("Werewolf");
this.power = new MageInt(3);
this.toughness = new MageInt(5);
this.color.setGreen(true);
this.nightCard = true;
this.canTransform = true;

View file

@ -36,7 +36,6 @@ import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.permanent.AnotherPredicate;
@ -50,8 +49,10 @@ public class MorkrutNecropod extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("another creature or land");
static {
filter.add(Predicates.or(Predicates.and(new AnotherPredicate(), new CardTypePredicate(CardType.CREATURE)),
filter.add(Predicates.or(
new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.LAND)));
filter.add(new AnotherPredicate());
}
public MorkrutNecropod(UUID ownerId) {
@ -66,7 +67,7 @@ public class MorkrutNecropod extends CardImpl {
this.addAbility(new MenaceAbility());
// Whenever Morkrut Necropod attacks or blocks, sacrifice another creature or land.
this.addAbility(new AttacksOrBlocksTriggeredAbility(new SacrificeControllerEffect(new FilterLandPermanent(), 1, ""), false));
this.addAbility(new AttacksOrBlocksTriggeredAbility(new SacrificeControllerEffect(filter, 1, ""), false));
}
public MorkrutNecropod(final MorkrutNecropod card) {

View file

@ -0,0 +1,116 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.shadowsoverinnistrad;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
*
* @author halljared
*/
public class NeglectedHeirloom extends CardImpl {
public NeglectedHeirloom(UUID ownerId) {
super(ownerId, 260, "Neglected Heirloom", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{1}");
this.expansionSetCode = "SOI";
this.subtype.add("Equipment");
this.canTransform = true;
this.secondSideCard = new AshmouthBlade(ownerId);
// Equipped creature gets +1/+1.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 1)));
// Equip {1}
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1)));
// When equipped creature transforms, transform Neglected Heirloom.
this.addAbility(new TransformAbility());
this.addAbility(new NeglectedHeirloomTriggeredAbility());
}
public NeglectedHeirloom(final NeglectedHeirloom card) {
super(card);
}
@Override
public NeglectedHeirloom copy() {
return new NeglectedHeirloom(this);
}
}
class NeglectedHeirloomTriggeredAbility extends TriggeredAbilityImpl {
public NeglectedHeirloomTriggeredAbility() {
super(Zone.BATTLEFIELD, new TransformSourceEffect(true), false);
}
public NeglectedHeirloomTriggeredAbility(final NeglectedHeirloomTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.TRANSFORMED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.TRANSFORMED) {
if (game.getPermanent(event.getTargetId()).getAttachments().contains(this.getSourceId())) {
return true;
}
}
return false;
}
@Override
public NeglectedHeirloomTriggeredAbility copy() {
return new NeglectedHeirloomTriggeredAbility(this);
}
@Override
public String getRule() {
return "When equipped creature transforms, transform Neglected Heirloom.";
}
}

View file

@ -52,6 +52,7 @@ public class OneOfThePack extends CardImpl {
this.subtype.add("Werewolf");
this.power = new MageInt(5);
this.toughness = new MageInt(6);
this.color.setGreen(true);
this.nightCard = true;
this.canTransform = true;

View file

@ -48,6 +48,7 @@ public class PersistentNightmare extends CardImpl {
this.subtype.add("Nightmare");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
this.color.setBlue(true);
// this card is the second face of double-faced card
this.nightCard = true;

View file

@ -37,9 +37,11 @@ import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffec
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent;
@ -50,6 +52,11 @@ import mage.game.events.GameEvent;
*/
public class PrizedAmalgam extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature");
static {
filter.add(new ControllerPredicate(TargetController.YOU));
}
public PrizedAmalgam(UUID ownerId) {
super(ownerId, 249, "Prized Amalgam", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}{B}");
this.expansionSetCode = "SOI";
@ -59,7 +66,7 @@ public class PrizedAmalgam extends CardImpl {
// Whenever a creature enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, return Prized Amalgam from your graveyard to the battlefield tapped at the beginning of the next end step.
this.addAbility(new PrizedAmalgamTriggerdAbility(new CreateDelayedTriggeredAbilityEffect(
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect(true))), new FilterCreaturePermanent()));
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect(true))), filter));
}
public PrizedAmalgam(final PrizedAmalgam card) {

View file

@ -46,6 +46,7 @@ import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.Filter;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.AnotherCardPredicate;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
@ -105,13 +106,14 @@ class RelentlessDeadEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
if (controller.chooseUse(Outcome.BoostCreature, "Do you want to to pay {X}?", source, game)) {
if (controller.chooseUse(Outcome.BoostCreature, "Do you want to pay {X}?", source, game)) {
int costX = controller.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
Cost cost = new GenericManaCost(costX);
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) {
FilterCard filter = new FilterCard("Zombie card with converted mana cost " + costX);
FilterCard filter = new FilterCard("Another target Zombie card with converted mana cost " + costX);
filter.add(new SubtypePredicate("Zombie"));
filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, costX));
filter.add(new AnotherCardPredicate());
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter);
if (controller.chooseTarget(outcome, target, source, game)) {
Card card = game.getCard(target.getFirstTarget());

View file

@ -1,3 +1,4 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
@ -56,6 +57,8 @@ public class ScroungedScythe extends CardImpl {
this.expansionSetCode = "SOI";
this.subtype.add("Equipment");
this.nightCard = true;
// Equipped creature gets +1/+1.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 1)));

View file

@ -29,19 +29,21 @@ package mage.sets.shadowsoverinnistrad;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.common.SacrificeAllTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.keyword.InvestigateEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
/**
*
@ -67,7 +69,7 @@ public class TirelessTracker extends CardImpl {
this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new InvestigateEffect(), new FilterControlledLandPermanent("a land"), false, null, true));
// Whenever you sacrifice a Clue, put a +1/+1 counter on Tireless Tracker.
this.addAbility(new SacrificeAllTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter, TargetController.YOU, false));
this.addAbility(new TirelessTrackerTriggeredAbility());
}
public TirelessTracker(final TirelessTracker card) {
@ -79,3 +81,36 @@ public class TirelessTracker extends CardImpl {
return new TirelessTracker(this);
}
}
class TirelessTrackerTriggeredAbility extends TriggeredAbilityImpl {
public TirelessTrackerTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
setLeavesTheBattlefieldTrigger(true);
}
public TirelessTrackerTriggeredAbility(final TirelessTrackerTriggeredAbility ability) {
super(ability);
}
@Override
public TirelessTrackerTriggeredAbility copy() {
return new TirelessTrackerTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.SACRIFICED_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getPlayerId().equals(this.getControllerId())
&& game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue");
}
@Override
public String getRule() {
return "Whenever you sacrifice a Clue, " + super.getRule();
}
}

View file

@ -28,20 +28,24 @@
package mage.sets.shadowsoverinnistrad;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.common.SacrificeAllTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.keyword.InvestigateEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
/**
*
@ -66,7 +70,7 @@ public class UlvenwaldMysteries extends CardImpl {
this.addAbility(new DiesCreatureTriggeredAbility(new InvestigateEffect(), false, filter));
// Whenever you sacrifice a Clue, put a 1/1 white Human Soldier creature token onto the battlefield.
this.addAbility(new SacrificeAllTriggeredAbility(new CreateTokenEffect(new HumanSoldierToken()), filterClue, TargetController.YOU, false));
this.addAbility(new UlvenwaldMysteriesTriggeredAbility());
}
public UlvenwaldMysteries(final UlvenwaldMysteries card) {
@ -78,3 +82,36 @@ public class UlvenwaldMysteries extends CardImpl {
return new UlvenwaldMysteries(this);
}
}
class UlvenwaldMysteriesTriggeredAbility extends TriggeredAbilityImpl {
public UlvenwaldMysteriesTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new HumanSoldierToken()));
setLeavesTheBattlefieldTrigger(true);
}
public UlvenwaldMysteriesTriggeredAbility(final UlvenwaldMysteriesTriggeredAbility ability) {
super(ability);
}
@Override
public UlvenwaldMysteriesTriggeredAbility copy() {
return new UlvenwaldMysteriesTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.SACRIFICED_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getPlayerId().equals(this.getControllerId())
&& game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue");
}
@Override
public String getRule() {
return "Whenever you sacrifice a Clue, " + super.getRule();
}
}

View file

@ -62,6 +62,7 @@ public class VildinPackAlpha extends CardImpl {
this.subtype.add("Werewolf");
this.power = new MageInt(4);
this.toughness = new MageInt(3);
this.color.setRed(true);
this.canTransform = true;
this.nightCard = true;

View file

@ -96,7 +96,7 @@ class WelcomeToTheFoldEffect extends GainControlTargetEffect {
maxToughness = source.getManaCostsToPay().getX();
}
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null && permanent.getToughness().getValue() <= maxToughness) {
if (permanent != null && permanent.getToughness().getValue() > maxToughness) {
this.discard();
return;
}

View file

@ -0,0 +1,49 @@
package org.mage.test.cards.control;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* 2UU
Sorcery
Madness XUU (If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.)
Gain control of target creature if its toughness is 2 or less.
* If Welcome to the Fold's madness cost was paid, instead gain control of that creature if its toughness is X or less.
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public class WelcomeToTheFoldTest extends CardTestPlayerBase {
/**
* Paid with regular cost, gain control of creatures with toughness <= 2
*/
@Test
public void regularCostVariousCreatures() {
addCard(Zone.HAND, playerA, "Welcome to the Fold", 3);
addCard(Zone.BATTLEFIELD, playerA, "Island", 12);
addCard(Zone.BATTLEFIELD, playerB, "Arashin Cleric", 1); // 1/3
addCard(Zone.BATTLEFIELD, playerB, "Jace, Vryn's Prodigy", 1); // 0/2
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard", 1); // 2/1
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Welcome to the Fold");
addTarget(playerA, "Arashin Cleric"); // does not gain control
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Welcome to the Fold");
addTarget(playerA, "Jace, Vryn's Prodigy"); // gains control
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Welcome to the Fold");
addTarget(playerA, "Elite Vanguard"); // gains control
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, "Welcome to the Fold", 3);
assertPermanentCount(playerA, "Arashin Cleric", 0); // should not gain control
assertPermanentCount(playerA, "Jace, Vryn's Prodigy", 1); // should gain control
assertPermanentCount(playerA, "Elite Vanguard", 1);
}
// TODO: add a madness cost test
}

View file

@ -0,0 +1,38 @@
package org.mage.test.cards.single.soi;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* 3G
Creature - Human Warrior
Whenever Briarbridge Patrol deals damage to one or more creatures, investigate. (Put a colorless Clue artifact token onto the battlefield with "2, Sacrifice this artifact: Draw a card.")
At the beginning of each end step, if you sacrificed three or more clues this turn, you may put a creature card from your hand onto the battlefield.
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public class BriarbridgePatrolTest extends CardTestPlayerBase {
/**
* Deals damage to creature test.
*/
@Test
public void dealtDamageToCreatureInvestigate() {
addCard(Zone.BATTLEFIELD, playerA, "Briarbridge Patrol", 1);
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard", 1);
attack(1, playerA, "Briarbridge Patrol");
block(1, playerB, "Elite Vanguard", "Briarbridge Patrol");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerA, "Clue", 1);
assertPermanentCount(playerA, "Briarbridge Patrol", 1);
assertPermanentCount(playerB, "Elite Vanguard", 0);
assertGraveyardCount(playerB, "Elite Vanguard", 1);
}
}

View file

@ -0,0 +1,103 @@
package org.mage.test.cards.single.soi;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*1UB
* Creature - Zombie
* Whenever a creature enters the battlefield, if it entered from your graveyard or you cast it from your graveyard,
* return Prized Amalgam from your graveyard to the battlefield tapped at the beginning of the next end step.
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public class PrizedAmalgamTest extends CardTestPlayerBase {
/**
* Reanimated creature recurs Prized Amalgam
*/
@Test
public void testReanimation() {
addCard(Zone.HAND, playerA, "Reanimate", 1); // {B} Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost.
addCard(Zone.GRAVEYARD, playerA, "Bronze Sable", 1); // (2) 2/1
addCard(Zone.GRAVEYARD, playerA, "Prized Amalgam", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate");
addTarget(playerA, "Bronze Sable");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerA, 18); // loss of 2 from reanimate
assertGraveyardCount(playerA, "Reanimate", 1);
assertPermanentCount(playerA, "Bronze Sable", 1);
assertPermanentCount(playerA, "Prized Amalgam", 1);
assertTapped("Prized Amalgam", true);
}
/**
* Reported bug - Gravecrawler cast from grave does not trigger Prized Amalgam.
*/
@Test
public void testGravecrawlerCastFromGrave() {
addCard(Zone.GRAVEYARD, playerA, "Gravecrawler", 1);
addCard(Zone.GRAVEYARD, playerA, "Prized Amalgam", 1);
addCard(Zone.BATTLEFIELD, playerA, "Gnawing Zombie", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gravecrawler");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Gravecrawler", 1);
assertPermanentCount(playerA, "Prized Amalgam", 1);
assertTapped("Prized Amalgam", true);
}
/**
* Reported bug - creature returned from opponent's graveyard to battlefield by Ojutai's Command incorrectly triggers Prized Amalgam
*/
@Test
public void testOpponentReturnsCreatureFromGrave() {
addCard(Zone.HAND, playerA, "Reanimate", 1);
addCard(Zone.GRAVEYARD, playerA, "Hill Giant", 1); // {3}{R} 3/3
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate");
addTarget(playerA, "Hill Giant");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerA, 16); // lose 4 life from reanimate 4 CMC
assertPermanentCount(playerA, "Hill Giant", 1);
assertPermanentCount(playerB, "Prized Amalgam", 0); // should not recur
assertGraveyardCount(playerB, "Prized Amalgam", 1); // stays in grave
}
/*
* Test opponent returning a card from your graveyard to battlefield.
*/
@Test
public void testOpponentReturnsCreatureFromYourGrave() {
addCard(Zone.HAND, playerA, "Necromantic Summons", 1); // Put target creature card from a graveyard onto the battlefield under your control.
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
addCard(Zone.GRAVEYARD, playerB, "Merfolk Looter", 1); // {U} 1/1
addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Necromantic Summons");
addTarget(playerA, "Merfolk Looter");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Merfolk Looter", 1);
assertPermanentCount(playerB, "Prized Amalgam", 0); // should not recur
assertGraveyardCount(playerB, "Prized Amalgam", 1); // stays in grave
}
}

View file

@ -0,0 +1,40 @@
package org.mage.test.cards.single.soi;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* 2G
Creature - Human Scout
Whenever a land enters the battlefield under your control, investigate.
Whenever you sacrifice a Clue, put a +1/+1 counter on Tireless Tracker.
*
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public class TirelessTrackerTest extends CardTestPlayerBase {
/**
* Only landfall under your control triggers first ability
*/
@Test
public void landfallUnderOwnControlTriggers() {
addCard(Zone.BATTLEFIELD, playerA, "Tireless Tracker", 1);
addCard(Zone.HAND, playerA, "Forest", 3);
addCard(Zone.HAND, playerB, "Wastes", 3);
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest");
playLand(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Wastes");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerA, "Forest", 1);
assertPermanentCount(playerB, "Wastes", 1);
assertPermanentCount(playerA, "Clue", 1);
}
// TODO: add tests for 2nd ability
}

View file

@ -0,0 +1,61 @@
package org.mage.test.cards.single.soi;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* 3RR
Creature - Elemental Wolf
*Whenever Wolf of Devil's Breach attacks, you may pay 1R and discard a card.
* If you do, Wolf of Devil's Breach deals damage to target creature or planeswalker equal to the discarded card's converted mana cost.
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public class WolfOfDevilsBreachTest extends CardTestPlayerBase {
/**
*
*/
@Test
public void attackChooseToPay() {
addCard(Zone.BATTLEFIELD, playerA, "Wolf of Devil's Breach", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.HAND, playerA, "Bronze Sable", 1); // (2) 2/1
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1); // 2/2
attack(1, playerA, "Wolf of Devil's Breach");
setChoice(playerA, "Yes");
setChoice(playerA, "Bronze Sable");
addTarget(playerA, "Grizzly Bears");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertGraveyardCount(playerA, "Bronze Sable", 1);
assertGraveyardCount(playerB, "Grizzly Bears", 1);
}
/**
*
*/
@Test
public void attackDoNotPay() {
addCard(Zone.BATTLEFIELD, playerA, "Wolf of Devil's Breach", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.HAND, playerA, "Bronze Sable", 1); // (2) 2/1
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1); // 2/2
attack(1, playerA, "Wolf of Devil's Breach");
setChoice(playerA, "No");
setChoice(playerA, "Bronze Sable");
addTarget(playerA, "Grizzly Bears");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertHandCount(playerA, "Bronze Sable", 1); // never discarded
assertGraveyardCount(playerA, "Bronze Sable", 0);
assertGraveyardCount(playerB, "Grizzly Bears", 0);
}
}

View file

@ -0,0 +1,39 @@
package org.mage.test.cards.triggers;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* When Silkwrap enters the battlefield, exile target creature with converted mana cost 3 or less an opponent controls until Silkwrap leaves the battlefield.
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public class SilkwrapTest extends CardTestPlayerBase {
/*
* Reported bug - Silkwrap does not exile Hangarback.
Cards with X CMC are considered 0 CMC on the battlefield.
*/
@Test
public void testHangarback() {
addCard(Zone.HAND, playerA, "Hangarback Walker", 1);
addCard(Zone.BATTLEFIELD, playerA, "Wastes", 8);
addCard(Zone.HAND, playerB, "Silkwrap", 1);
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hangarback Walker");
setChoice(playerA, "X=4");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Silkwrap");
addTarget(playerB, "Hangarback Walker");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerB, "Silkwrap", 1);
assertPermanentCount(playerA, "Hangarback Walker", 0);
assertExileCount("Hangarback Walker", 1);
}
}