mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
[VIS] Implement Matopi Golem (#11323)
fix Skeleton Scavengers & Soldevi Sentry, and refactor a common effect for all 3.
This commit is contained in:
parent
a37fc0589a
commit
5b58ff242b
7 changed files with 200 additions and 78 deletions
47
Mage.Sets/src/mage/cards/m/MatopiGolem.java
Normal file
47
Mage.Sets/src/mage/cards/m/MatopiGolem.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,21 +4,19 @@ import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.CostImpl;
|
import mage.abilities.costs.CostImpl;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
import mage.abilities.dynamicvalue.common.CountersSourceCount;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.common.RegenerateSourceWithReflexiveEffect;
|
||||||
import mage.abilities.effects.common.RegenerateSourceEffect;
|
|
||||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.ManaUtil;
|
import mage.util.ManaUtil;
|
||||||
|
|
||||||
|
|
@ -40,7 +38,13 @@ public final class SkeletonScavengers extends CardImpl {
|
||||||
this.addAbility(new AsEntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())));
|
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.
|
// 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))
|
||||||
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,32 +103,4 @@ class DynamicValueGenericManaCost extends CostImpl {
|
||||||
private void setText() {
|
private void setText() {
|
||||||
text = ("Pay {1} for each +1/+1 counter on {this}");
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,16 +3,14 @@ package mage.cards.s;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
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.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.common.TargetOpponent;
|
import mage.target.common.TargetOpponent;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -28,9 +26,16 @@ public final class SoldeviSentry extends CardImpl {
|
||||||
this.power = new MageInt(1);
|
this.power = new MageInt(1);
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
// 1: Choose target opponent. Regenerate Soldevi Sentry. When it regenerates
|
// {1}: Choose target opponent. Regenerate Soldevi Sentry. When it regenerates this way, that player may draw a card.
|
||||||
// this way, that player may draw a card.
|
Ability ability = new SimpleActivatedAbility(
|
||||||
Ability ability = new SimpleActivatedAbility(new SoldeviSentryEffect(), new GenericManaCost(1));
|
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());
|
ability.addTarget(new TargetOpponent());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
@ -43,39 +48,4 @@ public final class SoldeviSentry extends CardImpl {
|
||||||
public SoldeviSentry copy() {
|
public SoldeviSentry copy() {
|
||||||
return new SoldeviSentry(this);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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("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("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("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("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("Mob Mentality", 88, Rarity.UNCOMMON, mage.cards.m.MobMentality.class));
|
||||||
cards.add(new SetCardInfo("Mortal Wound", 113, Rarity.COMMON, mage.cards.m.MortalWound.class));
|
cards.add(new SetCardInfo("Mortal Wound", 113, Rarity.COMMON, mage.cards.m.MortalWound.class));
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue