[VIS] Implement Matopi Golem (#11323)

fix Skeleton Scavengers & Soldevi Sentry, and refactor a common effect for all 3.
This commit is contained in:
Susucre 2023-10-21 15:28:03 +02:00 committed by GitHub
parent a37fc0589a
commit 5b58ff242b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 200 additions and 78 deletions

View file

@ -0,0 +1,47 @@
package mage.cards.m;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.RegenerateSourceWithReflexiveEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import java.util.UUID;
/**
* @author Susucr
*/
public final class MatopiGolem extends CardImpl {
public MatopiGolem(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}");
this.subtype.add(SubType.GOLEM);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// {1}: Regenerate Matopi Golem. When it regenerates this way, put a -1/-1 counter on it.
this.addAbility(new SimpleActivatedAbility(
new RegenerateSourceWithReflexiveEffect(new ReflexiveTriggeredAbility(
new AddCountersSourceEffect(CounterType.M1M1.createInstance()),
false
), false),
new GenericManaCost(1)
));
}
private MatopiGolem(final MatopiGolem card) {
super(card);
}
@Override
public MatopiGolem copy() {
return new MatopiGolem(this);
}
}

View file

@ -4,21 +4,19 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.RegenerateSourceEffect;
import mage.abilities.effects.common.RegenerateSourceWithReflexiveEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.ManaUtil;
@ -40,7 +38,13 @@ public final class SkeletonScavengers extends CardImpl {
this.addAbility(new AsEntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())));
// Pay {1} for each +1/+1 counter on Skeleton Scavengers: Regenerate Skeleton Scavengers. When it regenerates this way, put a +1/+1 counter on it.
this.addAbility(new SimpleActivatedAbility(new SkeletonScavengersEffect(), new DynamicValueGenericManaCost(new CountersSourceCount(CounterType.P1P1))));
this.addAbility(new SimpleActivatedAbility(
new RegenerateSourceWithReflexiveEffect(new ReflexiveTriggeredAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance()),
false
), false),
new DynamicValueGenericManaCost(new CountersSourceCount(CounterType.P1P1))
));
}
@ -100,31 +104,3 @@ class DynamicValueGenericManaCost extends CostImpl {
text = ("Pay {1} for each +1/+1 counter on {this}");
}
}
class SkeletonScavengersEffect extends OneShotEffect {
SkeletonScavengersEffect() {
super(Outcome.Benefit);
this.staticText = "Regenerate {this}. When it regenerates this way, put a +1/+1 counter on it";
}
private SkeletonScavengersEffect(final SkeletonScavengersEffect effect) {
super(effect);
}
@Override
public SkeletonScavengersEffect copy() {
return new SkeletonScavengersEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent skeletonScavengers = game.getPermanent(source.getSourceId());
if (skeletonScavengers != null) {
if (new RegenerateSourceEffect().apply(game, source)) {
return new AddCountersSourceEffect(CounterType.P1P1.createInstance()).apply(game, source);
}
}
return false;
}
}

View file

@ -3,16 +3,14 @@ package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.RegenerateSourceEffect;
import mage.abilities.effects.common.DrawCardTargetEffect;
import mage.abilities.effects.common.RegenerateSourceWithReflexiveEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
import java.util.UUID;
@ -28,9 +26,16 @@ public final class SoldeviSentry extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// 1: Choose target opponent. Regenerate Soldevi Sentry. When it regenerates
// this way, that player may draw a card.
Ability ability = new SimpleActivatedAbility(new SoldeviSentryEffect(), new GenericManaCost(1));
// {1}: Choose target opponent. Regenerate Soldevi Sentry. When it regenerates this way, that player may draw a card.
Ability ability = new SimpleActivatedAbility(
new RegenerateSourceWithReflexiveEffect(new ReflexiveTriggeredAbility(
new DrawCardTargetEffect(1, true),
false
), true)
.setText("Choose target opponent. Regenerate Soldevi Sentry. "
+ "When it regenerates this way, that player may draw a card"),
new GenericManaCost(1)
);
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
@ -44,38 +49,3 @@ public final class SoldeviSentry extends CardImpl {
return new SoldeviSentry(this);
}
}
class SoldeviSentryEffect extends RegenerateSourceEffect {
public SoldeviSentryEffect() {
super();
this.staticText = "Choose target opponent. Regenerate {this}. When it regenerates this way, that player may draw a card";
}
protected SoldeviSentryEffect(final SoldeviSentryEffect effect) {
super(effect);
}
@Override
public SoldeviSentryEffect copy() {
return new SoldeviSentryEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
//20110204 - 701.11
Player opponent = game.getPlayer(source.getFirstTarget());
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null && permanent.regenerate(source, game)) {
if (opponent != null) {
if (opponent.chooseUse(Outcome.DrawCard, "Draw a card?", source, game)) {
opponent.drawCards(1, source, game);
}
}
this.used = true;
return true;
}
return false;
}
}

View file

@ -107,6 +107,7 @@ public final class Visions extends ExpansionSet {
cards.add(new SetCardInfo("Longbow Archer", 12, Rarity.UNCOMMON, mage.cards.l.LongbowArcher.class));
cards.add(new SetCardInfo("Magma Mine", 149, Rarity.UNCOMMON, mage.cards.m.MagmaMine.class));
cards.add(new SetCardInfo("Man-o'-War", 37, Rarity.COMMON, mage.cards.m.ManOWar.class));
cards.add(new SetCardInfo("Matopi Golem", 150, Rarity.UNCOMMON, mage.cards.m.MatopiGolem.class));
cards.add(new SetCardInfo("Miraculous Recovery", 13, Rarity.UNCOMMON, mage.cards.m.MiraculousRecovery.class));
cards.add(new SetCardInfo("Mob Mentality", 88, Rarity.UNCOMMON, mage.cards.m.MobMentality.class));
cards.add(new SetCardInfo("Mortal Wound", 113, Rarity.COMMON, mage.cards.m.MortalWound.class));

View file

@ -0,0 +1,40 @@
package org.mage.test.cards.single.all;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class SoldeviSentryTest extends CardTestPlayerBase {
/**
* {@link mage.cards.s.SoldeviSentry} <br>
* Soldevi Sentry {1} <br>
* Artifact Creature Soldier <br>
* {1}: Choose target opponent. Regenerate Soldevi Sentry. When it regenerates this way, that player may draw a card. <br>
* 1/1
*/
private static final String sentry = "Soldevi Sentry";
@Test
public void test_ReflexiveOnRegenerate() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, sentry);
addCard(Zone.HAND, playerA, "Doom Blade");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
activateAbility(1, PhaseStep.UPKEEP, playerA, "{1}: Choose", playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Doom Blade", sentry);
setChoice(playerB, true); // yes to drawing a card in the reflexive trigger
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, sentry, 1);
assertTapped(sentry, true);
assertHandCount(playerB, 1);
}
}

View file

@ -0,0 +1,39 @@
package org.mage.test.cards.single.vis;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class MatopiGolemTest extends CardTestPlayerBase {
/**
* {@link mage.cards.m.MatopiGolem} <br>
* Matopi Golem {5} <br>
* Artifact Creature Golem <br>
* {1}: Regenerate Matopi Golem. When it regenerates this way, put a -1/-1 counter on it. <br>
* 3/3
*/
private static final String golem = "Matopi Golem";
@Test
public void test_ReflexiveOnRegenerate() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, golem);
addCard(Zone.HAND, playerA, "Doom Blade");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
activateAbility(1, PhaseStep.UPKEEP, playerA, "{1}: Regenerate");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Doom Blade", golem);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, golem, 1);
assertTapped(golem, true);
assertPowerToughness(playerA, golem, 3 - 1, 3 - 1);
}
}

View file

@ -0,0 +1,49 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.game.Game;
import mage.target.targetpointer.FixedTarget;
/**
* @author Susucr
*/
public class RegenerateSourceWithReflexiveEffect extends RegenerateSourceEffect {
private final ReflexiveTriggeredAbility reflexive;
private final boolean setReflexiveTarget;
public RegenerateSourceWithReflexiveEffect(ReflexiveTriggeredAbility reflexive, boolean setReflexiveTarget) {
super();
this.reflexive = reflexive;
this.reflexive.setTriggerPhrase("When it regenerates this way, ");
this.setReflexiveTarget = setReflexiveTarget;
this.staticText = "regenerate {this}. " + reflexive.getRule();
}
protected RegenerateSourceWithReflexiveEffect(final RegenerateSourceWithReflexiveEffect effect) {
super(effect);
this.reflexive = effect.reflexive.copy();
this.setReflexiveTarget = effect.setReflexiveTarget;
}
@Override
public RegenerateSourceWithReflexiveEffect copy() {
return new RegenerateSourceWithReflexiveEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (super.apply(game, source)) {
if (this.setReflexiveTarget) {
reflexive.getEffects().setTargetPointer(
new FixedTarget(targetPointer.getFirst(game, source), game)
);
}
game.fireReflexiveTriggeredAbility(reflexive, source);
return true;
}
return false;
}
}