Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CLU] Implement Amzu, Swarm's Hunger and batches for zone change events #12686

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
117 changes: 117 additions & 0 deletions Mage.Sets/src/mage/cards/a/AmzuSwarmsHunger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package mage.cards.a;

import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.CardsLeaveGraveyardTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.cards.Card;
import mage.constants.*;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.MenaceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.IzoniInsectToken;

/**
*
* @author jimga150
*/
public final class AmzuSwarmsHunger extends CardImpl {

private static final FilterPermanent filter = new FilterPermanent(SubType.INSECT, "Insects");

public AmzuSwarmsHunger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{G}");

this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.INSECT);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

// Flying
this.addAbility(FlyingAbility.getInstance());

// Menace
this.addAbility(new MenaceAbility());

// Other Insects you control have menace.
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
new MenaceAbility(false), Duration.WhileOnBattlefield,
filter, true
)));

// Whenever one or more cards leave your graveyard, you may create a 1/1 black and green Insect creature token,
// then put a number of +1/+1 counters on it equal to the greatest mana value among those cards.
// Do this only once each turn.
this.addAbility(new CardsLeaveGraveyardTriggeredAbility(new AmzuSwarmsHungerEffect(), true).setDoOnlyOnceEachTurn(true));
xenohedron marked this conversation as resolved.
Show resolved Hide resolved
}

private AmzuSwarmsHunger(final AmzuSwarmsHunger card) {
super(card);
}

@Override
public AmzuSwarmsHunger copy() {
return new AmzuSwarmsHunger(this);
}
}

// Based on OutlawStitcherEffect
class AmzuSwarmsHungerEffect extends OneShotEffect {

AmzuSwarmsHungerEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "create a 1/1 black and green Insect creature token, " +
"then put a number of +1/+1 counters on it equal to the greatest mana value among those cards.";
}

private AmzuSwarmsHungerEffect(final AmzuSwarmsHungerEffect effect) {
super(effect);
}

@Override
public AmzuSwarmsHungerEffect copy() {
return new AmzuSwarmsHungerEffect(this);
}

@Override
public boolean apply(Game game, Ability source) {
CreateTokenEffect effect = new CreateTokenEffect(new IzoniInsectToken());
boolean result = effect.apply(game, source);
xenohedron marked this conversation as resolved.
Show resolved Hide resolved

Object cardsLeavingGraveyardObj = this.getValue("cardsLeavingGraveyard");
if (!(cardsLeavingGraveyardObj instanceof Set)) {
return false;
}
Set<Card> cardsLeavingGraveyard = (Set<Card>) cardsLeavingGraveyardObj;
int xvalue = cardsLeavingGraveyard
.stream()
.mapToInt(MageObject::getManaValue)
.max()
.orElse(0);

if (xvalue <= 0 || !result) {
return result;
}
for (UUID id : effect.getLastAddedTokenIds()) {
Permanent token = game.getPermanent(id);
if (token == null) {
continue;
}
token.addCounters(CounterType.P1P1.createInstance(xvalue), source.getControllerId(), source, game);
}
return true;
}

}
1 change: 1 addition & 0 deletions Mage.Sets/src/mage/sets/RavnicaClueEdition.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ private RavnicaClueEdition() {
cards.add(new SetCardInfo("Affectionate Indrik", 155, Rarity.UNCOMMON, mage.cards.a.AffectionateIndrik.class));
cards.add(new SetCardInfo("Afterlife Insurance", 23, Rarity.UNCOMMON, mage.cards.a.AfterlifeInsurance.class));
cards.add(new SetCardInfo("Ajani's Pridemate", 52, Rarity.UNCOMMON, mage.cards.a.AjanisPridemate.class));
cards.add(new SetCardInfo("Amzu, Swarm's Hunger", 24, Rarity.RARE, mage.cards.a.AmzuSwarmsHunger.class));
cards.add(new SetCardInfo("Angel of Vitality", 53, Rarity.UNCOMMON, mage.cards.a.AngelOfVitality.class));
cards.add(new SetCardInfo("Apothecary White", 1, Rarity.RARE, mage.cards.a.ApothecaryWhite.class));
cards.add(new SetCardInfo("Azorius Arrester", 54, Rarity.COMMON, mage.cards.a.AzoriusArrester.class));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

package org.mage.test.cards.single.clu;

import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;

/**
* @author Susucr
*/
public class AmzuSwarmsHungerTest extends CardTestPlayerBase {

/**
* {@link mage.cards.a.AmzuSwarmsHunger Amzu, Swarm's Hunger} {3}{B}{G}
* Legendary Creature — Insect Shaman
* Flying, menace
* Other Insects you control have menace.
* Whenever one or more cards leave your graveyard, you may create a 1/1 black and green Insect creature token,
* then put a number of +1/+1 counters on it equal to the greatest mana value among those cards.
* Do this only once each turn.
* 3/3
*/
private static final String amzu = "Amzu, Swarm's Hunger";

@Test
public void testTwoCreatures() {

addCard(Zone.BATTLEFIELD, playerA, amzu);
addCard(Zone.BATTLEFIELD, playerA, "Zask, Skittering Swarmlord");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
addCard(Zone.GRAVEYARD, playerA, "Battlefly Swarm");
addCard(Zone.GRAVEYARD, playerA, "Saber Ants");

castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Saber Ants", true);
setChoice(playerA, "Yes");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Battlefly Swarm", true);

setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

assertPermanentCount(playerA, "Insect Token", 1);
assertCounterCount(playerA, "Insect Token", CounterType.P1P1, 4);
}

@Test
public void testGraveyardExile() {

addCard(Zone.BATTLEFIELD, playerA, amzu);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.GRAVEYARD, playerA, "Living Hive");
addCard(Zone.GRAVEYARD, playerA, "Saber Ants");
addCard(Zone.HAND, playerA, "Rakdos Charm");

castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rakdos Charm", true);
setModeChoice(playerA, "1"); // Exile target player’s graveyard.
addTarget(playerA, playerA);
setChoice(playerA, "Yes");

setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

assertPermanentCount(playerA, "Insect Token", 1);
assertCounterCount(playerA, "Insect Token", CounterType.P1P1, 8);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import mage.game.events.ZoneChangeGroupEvent;

import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author TheElk801
Expand All @@ -24,7 +26,15 @@ public CardsLeaveGraveyardTriggeredAbility(Effect effect) {
}

public CardsLeaveGraveyardTriggeredAbility(Effect effect, FilterCard filter) {
super(Zone.BATTLEFIELD, effect, false);
this(effect, filter, false);
}

public CardsLeaveGraveyardTriggeredAbility(Effect effect, boolean optional) {
this(effect, StaticFilters.FILTER_CARD_CARDS, false);
xenohedron marked this conversation as resolved.
Show resolved Hide resolved
}

public CardsLeaveGraveyardTriggeredAbility(Effect effect, FilterCard filter, boolean optional) {
super(Zone.BATTLEFIELD, effect, optional);
this.filter = filter;
setTriggerPhrase("Whenever one or more " + filter + " leave your graveyard, ");
}
Expand All @@ -42,16 +52,18 @@ public boolean checkEventType(GameEvent event, Game game) {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeGroupEvent zEvent = (ZoneChangeGroupEvent) event;
return zEvent != null
&& Zone.GRAVEYARD == zEvent.getFromZone()
&& Zone.GRAVEYARD != zEvent.getToZone()
&& zEvent.getCards() != null
&& zEvent.getCards()
if (zEvent == null || Zone.GRAVEYARD != zEvent.getFromZone()
|| Zone.GRAVEYARD == zEvent.getToZone() || zEvent.getCards() == null){
return false;
}
Set<Card> cards = zEvent.getCards()
.stream()
.filter(Objects::nonNull)
.filter(card -> filter.match(card, getControllerId(), this, game))
.map(Card::getOwnerId)
.anyMatch(this::isControlledBy);
.filter(card -> this.isControlledBy(card.getOwnerId()))
.collect(Collectors.toSet());
this.getAllEffects().setValue("cardsLeavingGraveyard", cards);
xenohedron marked this conversation as resolved.
Show resolved Hide resolved
return !cards.isEmpty();
}

@Override
Expand Down
Loading