forked from External/mage
[OTJ] Implement Kambal, Profiteering Mayor
This is slightly bugged due to effect creating different tokens creating them not at the same time. See Bestial Menace unit test & #10811 for more info
This commit is contained in:
parent
4de6b0b173
commit
39008586d0
3 changed files with 242 additions and 0 deletions
152
Mage.Sets/src/mage/cards/k/KambalProfiteeringMayor.java
Normal file
152
Mage.Sets/src/mage/cards/k/KambalProfiteeringMayor.java
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
package mage.cards.k;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.EntersBattlefieldOneOrMoreTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.permanent.TokenPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeBatchEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class KambalProfiteeringMayor extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("tokens");
|
||||
|
||||
static {
|
||||
filter.add(TokenPredicate.TRUE);
|
||||
}
|
||||
|
||||
public KambalProfiteeringMayor(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{B}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.ADVISOR);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Whenever one or more tokens enter the battlefield under your opponents' control, for each of them, create a tapped token that's a copy of it. This ability triggers only once each turn.
|
||||
this.addAbility(new KambalProfiteeringMayorTriggeredAbility());
|
||||
|
||||
// Whenever one or more tokens enter the battlefield under your control, each opponent loses 1 life and you gain 1 life.
|
||||
Ability ability = new EntersBattlefieldOneOrMoreTriggeredAbility(
|
||||
new LoseLifeOpponentsEffect(1), filter, TargetController.YOU
|
||||
);
|
||||
ability.addEffect(new GainLifeEffect(1).concatBy("and"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private KambalProfiteeringMayor(final KambalProfiteeringMayor card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KambalProfiteeringMayor copy() {
|
||||
return new KambalProfiteeringMayor(this);
|
||||
}
|
||||
}
|
||||
|
||||
class KambalProfiteeringMayorTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
KambalProfiteeringMayorTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, null);
|
||||
this.setTriggersOnceEachTurn(true);
|
||||
}
|
||||
|
||||
private KambalProfiteeringMayorTriggeredAbility(final KambalProfiteeringMayorTriggeredAbility effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KambalProfiteeringMayorTriggeredAbility copy() {
|
||||
return new KambalProfiteeringMayorTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
ZoneChangeBatchEvent zEvent = (ZoneChangeBatchEvent) event;
|
||||
Player controller = game.getPlayer(this.controllerId);
|
||||
List<UUID> tokensIds = zEvent.getEvents()
|
||||
.stream()
|
||||
.filter(zce -> zce.getToZone() == Zone.BATTLEFIELD // keep enter the battlefield
|
||||
&& controller.hasOpponent(zce.getPlayerId(), game)) // & under your opponent's control
|
||||
.map(ZoneChangeEvent::getTarget)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(p -> p instanceof PermanentToken) // collect only tokens
|
||||
.map(Permanent::getId)
|
||||
.collect(Collectors.toList());
|
||||
if (tokensIds.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().clear();
|
||||
this.addEffect(new KambalProfiteeringMayorEffect(tokensIds));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever one or more tokens enter the battlefield under your opponents' control, "
|
||||
+ "for each of them, create a tapped token that's a copy of it. "
|
||||
+ "This ability triggers only once each turn.";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class KambalProfiteeringMayorEffect extends OneShotEffect {
|
||||
|
||||
private final List<UUID> tokensIds;
|
||||
|
||||
KambalProfiteeringMayorEffect(List<UUID> tokensIds) {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
this.tokensIds = new ArrayList<>(tokensIds);
|
||||
}
|
||||
|
||||
private KambalProfiteeringMayorEffect(final KambalProfiteeringMayorEffect effect) {
|
||||
super(effect);
|
||||
this.tokensIds = new ArrayList<>(effect.tokensIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KambalProfiteeringMayorEffect copy() {
|
||||
return new KambalProfiteeringMayorEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (UUID tokenId : tokensIds) {
|
||||
new CreateTokenCopyTargetEffect(source.getControllerId(), null, false, 1, true, false)
|
||||
.setTargetPointer(new FixedTarget(tokenId))
|
||||
.apply(game, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -145,6 +145,7 @@ public final class OutlawsOfThunderJunction extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Jem Lightfoote, Sky Explorer", 209, Rarity.UNCOMMON, mage.cards.j.JemLightfooteSkyExplorer.class));
|
||||
cards.add(new SetCardInfo("Jolene, Plundering Pugilist", 210, Rarity.UNCOMMON, mage.cards.j.JolenePlunderingPugilist.class));
|
||||
cards.add(new SetCardInfo("Kaervek, the Punisher", 92, Rarity.RARE, mage.cards.k.KaervekThePunisher.class));
|
||||
cards.add(new SetCardInfo("Kambal, Profiteering Mayor", 211, Rarity.RARE, mage.cards.k.KambalProfiteeringMayor.class));
|
||||
cards.add(new SetCardInfo("Kellan Joins Up", 212, Rarity.RARE, mage.cards.k.KellanJoinsUp.class));
|
||||
cards.add(new SetCardInfo("Kraum, Violent Cacophony", 214, Rarity.UNCOMMON, mage.cards.k.KraumViolentCacophony.class));
|
||||
cards.add(new SetCardInfo("Lassoed by the Law", 18, Rarity.UNCOMMON, mage.cards.l.LassoedByTheLaw.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
package org.mage.test.cards.single.otj;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class KambalProfiteeringMayorTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.k.KambalProfiteeringMayor Kambal, Profiteering Mayor} {1}{W}{B}
|
||||
* Legendary Creature — Human Advisor
|
||||
* Whenever one or more tokens enter the battlefield under your opponents’ control, for each of them, create a tapped token that’s a copy of it. This ability triggers only once each turn.
|
||||
* Whenever one or more tokens enter the battlefield under your control, each opponent loses 1 life and you gain 1 life.
|
||||
* 2/4
|
||||
*/
|
||||
private static final String kambal = "Kambal, Profiteering Mayor";
|
||||
|
||||
@Test
|
||||
public void Test_KrenkosCommand() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, kambal);
|
||||
// Create two 1/1 red Goblin creature tokens.
|
||||
addCard(Zone.HAND, playerA, "Krenko's Command");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Krenko's Command");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20 - 1); // Second Trigger happened
|
||||
assertLife(playerB, 20 + 1); // Second Trigger happened
|
||||
assertPermanentCount(playerA, "Goblin Token", 2);
|
||||
assertPermanentCount(playerB, "Goblin Token", 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Test_BestialMenace() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, kambal);
|
||||
// Create a 1/1 green Snake creature token, a 2/2 green Wolf creature token, and a 3/3 green Elephant creature token.
|
||||
addCard(Zone.HAND, playerA, "Bestial Menace");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bestial Menace");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20 - 1); // Second Trigger happened
|
||||
assertLife(playerB, 20 + 1); // Second Trigger happened
|
||||
assertPermanentCount(playerA, "Snake Token", 1);
|
||||
assertPermanentCount(playerA, "Wolf Token", 1);
|
||||
assertPermanentCount(playerA, "Elephant Token", 1);
|
||||
assertPermanentCount(playerB, "Snake Token", 1);
|
||||
assertPermanentCount(playerB, "Wolf Token", 0); // TODO: this is a bug, should be 1, see #10811
|
||||
assertPermanentCount(playerB, "Elephant Token", 0); // TODO: this is a bug, should be 1, see #10811
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Test_Chatterfang() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, kambal);
|
||||
// Create two 1/1 red Goblin creature tokens.
|
||||
addCard(Zone.HAND, playerA, "Krenko's Command");
|
||||
// If one or more tokens would be created under your control, those tokens plus that many 1/1 green Squirrel creature tokens are created instead.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Chatterfang, Squirrel General");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Krenko's Command");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20 - 1); // Second Trigger happened
|
||||
assertLife(playerB, 20 + 1); // Second Trigger happened
|
||||
assertPermanentCount(playerA, "Goblin Token", 2);
|
||||
assertPermanentCount(playerA, "Squirrel Token", 2);
|
||||
assertPermanentCount(playerB, "Goblin Token", 2);
|
||||
assertPermanentCount(playerB, "Squirrel Token", 2);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue