consolidate "Sacrifice all [filter] you control"

This commit is contained in:
Susucre 2024-04-30 10:42:10 +02:00
parent 1b9335c788
commit 8a07ff30b9
9 changed files with 217 additions and 195 deletions

View file

@ -1,14 +1,12 @@
package mage.cards.d;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeAllControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -16,26 +14,32 @@ import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.DragonToken2;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class DayOfTheDragons extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent(SubType.DRAGON, "Dragons");
public DayOfTheDragons(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{U}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}{U}{U}");
// When Day of the Dragons enters the battlefield, exile all creatures you control. Then create that many 5/5 red Dragon creature tokens with flying.
this.addAbility(new EntersBattlefieldTriggeredAbility(new DayOfTheDragonsEntersEffect(), false));
// When Day of the Dragons leaves the battlefield, sacrifice all Dragons you control. Then return the exiled cards to the battlefield under your control.
this.addAbility(new LeavesBattlefieldTriggeredAbility(new DayOfTheDragonsLeavesEffect(), false));
Ability ability = new LeavesBattlefieldTriggeredAbility(new SacrificeAllControllerEffect(filter), false);
ability.addEffect(new DayOfTheDragonsLeavesEffect());
this.addAbility(ability);
}
private DayOfTheDragons(final DayOfTheDragons card) {
@ -92,16 +96,9 @@ class DayOfTheDragonsEntersEffect extends OneShotEffect {
class DayOfTheDragonsLeavesEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent("all Dragons you control");
static {
filter.add(TargetController.YOU.getControllerPredicate());
filter.add(SubType.DRAGON.getPredicate());
}
public DayOfTheDragonsLeavesEffect() {
super(Outcome.Neutral);
staticText = "sacrifice all Dragons you control. Then return the exiled cards to the battlefield under your control";
staticText = "Then return the exiled cards to the battlefield under your control";
}
private DayOfTheDragonsLeavesEffect(final DayOfTheDragonsLeavesEffect effect) {
@ -113,11 +110,6 @@ class DayOfTheDragonsLeavesEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null) {
for (Permanent dragon : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
if (dragon != null) {
dragon.sacrifice(source, game);
}
}
int zoneChangeCounter = source.getSourceObjectZoneChangeCounter();
if (zoneChangeCounter > 0 && !(sourceObject instanceof PermanentToken)) {
zoneChangeCounter--;

View file

@ -1,21 +1,19 @@
package mage.cards.d;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeAllControllerEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class DeathPitOffering extends CardImpl {
@ -24,7 +22,7 @@ public final class DeathPitOffering extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}");
// When Death Pit Offering enters the battlefield, sacrifice all creatures you control.
this.addAbility(new EntersBattlefieldTriggeredAbility(new DeathPitOfferingEffect()));
this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeAllControllerEffect(StaticFilters.FILTER_PERMANENT_CREATURES)));
// Creatures you control get +2/+2.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(2, 2, Duration.WhileOnBattlefield, StaticFilters.FILTER_CONTROLLED_CREATURES, false)));
}
@ -37,30 +35,4 @@ public final class DeathPitOffering extends CardImpl {
public DeathPitOffering copy() {
return new DeathPitOffering(this);
}
}
class DeathPitOfferingEffect extends OneShotEffect {
DeathPitOfferingEffect() {
super(Outcome.Sacrifice);
this.staticText = "sacrifice all creatures you control";
}
private DeathPitOfferingEffect(final DeathPitOfferingEffect effect) {
super(effect);
}
@Override
public DeathPitOfferingEffect copy() {
return new DeathPitOfferingEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game);
for (Permanent permanent : permanents) {
permanent.sacrifice(source, game);
}
return true;
}
}
}

View file

@ -1,10 +1,11 @@
package mage.cards.h;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeAllControllerEffect;
import mage.abilities.effects.common.discard.DiscardHandControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -12,9 +13,10 @@ import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
@ -25,6 +27,12 @@ import java.util.UUID;
*/
public final class HellcarverDemon extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("other permanents");
static {
filter.add(AnotherPredicate.instance);
}
public HellcarverDemon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}{B}");
this.subtype.add(SubType.DEMON);
@ -34,10 +42,11 @@ public final class HellcarverDemon extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever Hellcarver Demon deals combat damage to a player, sacrifice all other permanents you
// control and discard your hand. Exile the top six cards of your library. You may cast any number
// of nonland cards exiled this way without paying their mana costs.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new HellcarverDemonEffect(), false));
// Whenever Hellcarver Demon deals combat damage to a player, sacrifice all other permanents you control and discard your hand. Exile the top six cards of your library. You may cast any number of nonland cards exiled this way without paying their mana costs.
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new SacrificeAllControllerEffect(filter), false);
ability.addEffect(new DiscardHandControllerEffect().concatBy("and"));
ability.addEffect(new HellcarverDemonEffect());
this.addAbility(ability);
}
private HellcarverDemon(final HellcarverDemon card) {
@ -54,8 +63,7 @@ class HellcarverDemonEffect extends OneShotEffect {
HellcarverDemonEffect() {
super(Outcome.PlayForFree);
staticText = "sacrifice all other permanents you control and discard your hand. "
+ "Exile the top six cards of your library. You may cast any number of "
staticText = "Exile the top six cards of your library. You may cast any number of "
+ "spells from among cards exiled this way without paying their mana costs";
}
@ -69,16 +77,6 @@ class HellcarverDemonEffect extends OneShotEffect {
if (controller == null) {
return false;
}
MageObjectReference sourceMor = new MageObjectReference(source);
for (Permanent permanent : game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_CONTROLLED_PERMANENT,
source.getControllerId(), source, game
)) {
if (!sourceMor.refersTo(permanent, game)) {
permanent.sacrifice(source, game);
}
}
controller.discard(controller.getHand(), false, source, game);
CardUtil.castMultipleWithAttributeForFree(
controller, source, game, new CardsImpl(
controller.getLibrary().getTopCards(game, 6)

View file

@ -1,10 +1,9 @@
package mage.cards.o;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeAllControllerEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.abilities.mana.SimpleManaAbility;
@ -12,12 +11,8 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
@ -30,7 +25,7 @@ public final class OverlaidTerrain extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{G}");
// As Overlaid Terrain enters the battlefield, sacrifice all lands you control.
this.addAbility(new AsEntersBattlefieldAbility(new SacrificeAllLandEffect()));
this.addAbility(new AsEntersBattlefieldAbility(new SacrificeAllControllerEffect(StaticFilters.FILTER_LANDS)));
// Lands you control have "{T}: Add two mana of any one color."
SimpleManaAbility manaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(2), new TapSourceCost());
@ -45,33 +40,4 @@ public final class OverlaidTerrain extends CardImpl {
public OverlaidTerrain copy() {
return new OverlaidTerrain(this);
}
}
class SacrificeAllLandEffect extends OneShotEffect {
SacrificeAllLandEffect() {
super(Outcome.Detriment);
staticText = "sacrifice all lands you control";
}
private SacrificeAllLandEffect(final SacrificeAllLandEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS, source.getControllerId(), game)) {
permanent.sacrifice(source, game);
}
return true;
}
return false;
}
@Override
public SacrificeAllLandEffect copy() {
return new SacrificeAllLandEffect(this);
}
}
}

View file

@ -1,15 +1,14 @@
package mage.cards.t;
import mage.abilities.Ability;
import mage.abilities.common.SagaAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
import mage.abilities.effects.common.SacrificeAllControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SagaChapter;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.ObjectSourcePlayer;
@ -20,7 +19,6 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.List;
import java.util.UUID;
/**
@ -36,6 +34,9 @@ public final class TheApprenticesFolly extends CardImpl {
filter.add(TheApprenticesFollyPredicate.instance);
}
private static final FilterPermanent filterReflection =
new FilterPermanent(SubType.REFLECTION, "Reflections");
public TheApprenticesFolly(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{R}");
@ -56,9 +57,7 @@ public final class TheApprenticesFolly extends CardImpl {
);
// III -- Sacrifice all Reflections you control.
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III,
new TheApprenticesFollySacrificeAllEffect()
);
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new SacrificeAllControllerEffect(filterReflection));
this.addAbility(sagaAbility);
}
@ -89,35 +88,4 @@ enum TheApprenticesFollyPredicate implements ObjectSourcePlayerPredicate<Permane
// This works due to the non-token clause on the target. There should be no controlled token with that name.
return game.getBattlefield().count(filter, input.getPlayerId(), input.getSource(), game) == 0;
}
}
class TheApprenticesFollySacrificeAllEffect extends OneShotEffect {
private static final FilterControlledPermanent filterReflection =
new FilterControlledPermanent(SubType.REFLECTION, "Reflections you control");
TheApprenticesFollySacrificeAllEffect() {
super(Outcome.Sacrifice);
staticText = "sacrifice all Reflections you control";
}
private TheApprenticesFollySacrificeAllEffect(final TheApprenticesFollySacrificeAllEffect effect) {
super(effect);
}
@Override
public TheApprenticesFollySacrificeAllEffect copy() {
return new TheApprenticesFollySacrificeAllEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = game.getBattlefield()
.getAllActivePermanents(filterReflection, source.getControllerId(), game);
for (Permanent permanent : permanents) {
permanent.sacrifice(source, game);
}
return true;
}
}
}

View file

@ -1,37 +1,32 @@
package mage.cards.y;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeAllControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class YukoraThePrisoner extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("non-Ogre creatures");
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Ogre creatures");
static {
filter.add(Predicates.not(SubType.OGRE.getPredicate()));
}
public YukoraThePrisoner(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.DEMON);
this.subtype.add(SubType.SPIRIT);
@ -40,7 +35,7 @@ public final class YukoraThePrisoner extends CardImpl {
this.toughness = new MageInt(5);
// When Yukora, the Prisoner leaves the battlefield, sacrifice all non-Ogre creatures you control.
this.addAbility(new LeavesBattlefieldTriggeredAbility(new YukoraThePrisonerEffect(), false));
this.addAbility(new LeavesBattlefieldTriggeredAbility(new SacrificeAllControllerEffect(filter), false));
}
@ -52,36 +47,4 @@ public final class YukoraThePrisoner extends CardImpl {
public YukoraThePrisoner copy() {
return new YukoraThePrisoner(this);
}
}
class YukoraThePrisonerEffect extends OneShotEffect {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("non-Ogre creatures");
static {
filter.add(Predicates.not(SubType.OGRE.getPredicate()));
}
public YukoraThePrisonerEffect() {
super(Outcome.Sacrifice);
this.staticText = "sacrifice all non-Ogre creatures you control";
}
private YukoraThePrisonerEffect(final YukoraThePrisonerEffect effect) {
super(effect);
}
@Override
public YukoraThePrisonerEffect copy() {
return new YukoraThePrisonerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game);
for (Permanent permanent : permanents) {
permanent.sacrifice(source, game);
}
return true;
}
}
}

View file

@ -0,0 +1,44 @@
package org.mage.test.cards.single.nem;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class DeathPitOfferingTest extends CardTestPlayerBase {
/**
* {@link mage.cards.d.DeathPitOffering Death Pit Offering} {2}{B}{B}
* Enchantment
* When Death Pit Offering enters the battlefield, sacrifice all creatures you control.
* Creatures you control get +2/+2.
*/
private static final String offering = "Death Pit Offering";
@Test
public void test_Trigger() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, offering);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
// Will be sacrificed:
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 2);
// Will not be sacrificed:
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, offering);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, 4 + 1);
assertPermanentCount(playerA, "Grizzly Bears", 0);
assertGraveyardCount(playerA, "Grizzly Bears", 2);
assertPermanentCount(playerB, "Grizzly Bears", 2);
}
}

View file

@ -0,0 +1,63 @@
package org.mage.test.cards.single.nem;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class OverlaidTerrainTest extends CardTestPlayerBase {
/**
* {@link mage.cards.o.OverlaidTerrain Overlaid Terrain} {2}{G}{G}
* Enchantment
* As Overlaid Terrain enters the battlefield, sacrifice all lands you control.
* Lands you control have {T}: Add two mana of any one color.
*/
private static final String terrain = "Overlaid Terrain";
@Test
public void test_Trigger() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, terrain);
// Will be sacrificed:
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
// Will not be sacrificed:
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 2);
addCard(Zone.BATTLEFIELD, playerB, "Taiga", 2);
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, terrain);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, 1 + 2);
assertPermanentCount(playerA, "Forest", 0);
assertGraveyardCount(playerA, "Forest", 4);
assertPermanentCount(playerB, 4);
}
@Test
public void test_Mana() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, terrain);
addCard(Zone.HAND, playerA, "Swamp");
addCard(Zone.HAND, playerA, "Ajani's Sunstriker"); // {W}{W}
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Swamp");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ajani's Sunstriker");
setChoice(playerA, "White"); // choice for mana color
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Ajani's Sunstriker", 1);
}
}

View file

@ -0,0 +1,56 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
* The controlling player of the source ability has to sacrifice all permanents
* under their control that match the [filter].
*
* @author Susucr
*/
public class SacrificeAllControllerEffect extends OneShotEffect {
private final FilterPermanent filter;
/**
* sacrifice all [filter] you control
*/
public SacrificeAllControllerEffect(FilterPermanent filter) {
super(Outcome.Sacrifice);
this.filter = filter;
this.staticText = "sacrifice all " + filter.getMessage() + " you control";
}
private SacrificeAllControllerEffect(final SacrificeAllControllerEffect effect) {
super(effect);
this.filter = effect.filter;
}
@Override
public SacrificeAllControllerEffect copy() {
return new SacrificeAllControllerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
UUID playerId = source.getControllerId();
boolean result = false;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
if (!filter.match(permanent, playerId, source, game)) {
continue;
}
permanent.sacrifice(source, game);
result = true;
}
return result;
}
}