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.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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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