forked from External/mage
[40K] Implement Kharn the Betrayer (#10885)
* implements Kharn the Betrayer * added flavor text * fixed test * fixed issue with triggered ability not working * removed diacritic * added effect text to test * fixed several issues as per PR comments * fixed access * updated Kharn to use PreventionEffect * added unit test for control loss via other sources
This commit is contained in:
parent
113650e48b
commit
26012ee135
3 changed files with 206 additions and 0 deletions
134
Mage.Sets/src/mage/cards/k/KharnTheBetrayer.java
Normal file
134
Mage.Sets/src/mage/cards/k/KharnTheBetrayer.java
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
package mage.cards.k;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.abilities.effects.common.DrawCardTargetEffect;
|
||||
import mage.abilities.effects.common.combat.AttacksIfAbleSourceEffect;
|
||||
import mage.abilities.effects.common.combat.BlocksIfAbleSourceEffect;
|
||||
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
* @author Xanderhall
|
||||
*/
|
||||
public class KharnTheBetrayer extends CardImpl {
|
||||
|
||||
public KharnTheBetrayer(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.addSubType(SubType.ASTARTES, SubType.BERSERKER);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// {this} attacks or blocks each combat if able
|
||||
Ability ability = new SimpleStaticAbility(new AttacksIfAbleSourceEffect(Duration.WhileOnBattlefield).setText("{this} attacks"));
|
||||
ability.addEffect(new BlocksIfAbleSourceEffect(Duration.WhileOnBattlefield).setText("blocks each combat if able").concatBy("or"));
|
||||
this.addAbility(ability.withFlavorWord("Berzerker"));
|
||||
|
||||
// When you lose control of {this}, draw two cards
|
||||
this.addAbility(new KharnTheBetrayerTriggeredAbility().withFlavorWord("Sigil of Corruption"));
|
||||
|
||||
// If damage would be dealt to {this}, prevent that damage and an opponent of your choice gains control of it.
|
||||
this.addAbility(new SimpleStaticAbility(new KharnTheBetrayerPreventionEffect()).withFlavorWord("The Betrayer"));
|
||||
}
|
||||
|
||||
protected KharnTheBetrayer(final KharnTheBetrayer card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KharnTheBetrayer copy() {
|
||||
return new KharnTheBetrayer(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class KharnTheBetrayerTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
KharnTheBetrayerTriggeredAbility () {
|
||||
super(Zone.BATTLEFIELD, new DrawCardTargetEffect(2));
|
||||
this.setTriggerPhrase("When you lose control of {this}, ");
|
||||
}
|
||||
|
||||
private KharnTheBetrayerTriggeredAbility(KharnTheBetrayerTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.LOST_CONTROL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getTargetId().equals(sourceId)) {
|
||||
this.getEffects().setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KharnTheBetrayerTriggeredAbility copy() {
|
||||
return new KharnTheBetrayerTriggeredAbility(this);
|
||||
}
|
||||
}
|
||||
|
||||
class KharnTheBetrayerPreventionEffect extends PreventionEffectImpl {
|
||||
|
||||
KharnTheBetrayerPreventionEffect() {
|
||||
super(Duration.WhileOnBattlefield);
|
||||
}
|
||||
|
||||
private KharnTheBetrayerPreventionEffect(final KharnTheBetrayerPreventionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KharnTheBetrayerPreventionEffect copy() {
|
||||
return new KharnTheBetrayerPreventionEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null || preventDamageAction(event, source, game).getPreventedDamage() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TargetOpponent target = new TargetOpponent();
|
||||
if (!player.choose(outcome, target, source, game)) {
|
||||
return false;
|
||||
}
|
||||
ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, target.getFirstTarget());
|
||||
effect.setTargetPointer(new FixedTarget(source.getSourceId(), game));
|
||||
|
||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(effect, false, "an opponent of your choice gains control of it.");
|
||||
game.fireReflexiveTriggeredAbility(ability, source);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
return super.applies(event, source, game) && event.getTargetId().equals(source.getSourceId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -150,6 +150,7 @@ public final class Warhammer40000 extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Inspiring Call", 217, Rarity.UNCOMMON, mage.cards.i.InspiringCall.class));
|
||||
cards.add(new SetCardInfo("Island", 307, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Keeper of Secrets", 78, Rarity.RARE, mage.cards.k.KeeperOfSecrets.class));
|
||||
cards.add(new SetCardInfo("Kharn the Betrayer", 79, Rarity.RARE, mage.cards.k.KharnTheBetrayer.class));
|
||||
cards.add(new SetCardInfo("Kill! Maim! Burn!", 128, Rarity.RARE, mage.cards.k.KillMaimBurn.class));
|
||||
cards.add(new SetCardInfo("Knight Paladin", 160, Rarity.RARE, mage.cards.k.KnightPaladin.class));
|
||||
cards.add(new SetCardInfo("Knight Rampager", 80, Rarity.RARE, mage.cards.k.KnightRampager.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
package org.mage.test.cards.single._40k;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestCommander4Players;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
|
||||
public class KharnTheBetrayerTest extends CardTestCommander4Players {
|
||||
|
||||
private static final String KHARN = "Kharn the Betrayer";
|
||||
private static final String BOLT = "Lightning Bolt";
|
||||
private static final String OFFERING = "Harmless Offering";
|
||||
|
||||
/**
|
||||
*
|
||||
Berzerker — Khârn the Betrayer attacks or blocks each combat if able.
|
||||
Sigil of Corruption — When you lose control of Khârn the Betrayer, draw two cards.
|
||||
The Betrayer — If damage would be dealt to Khârn the Betrayer, prevent that damage and an opponent of your choice gains control of it.
|
||||
*/
|
||||
@Test
|
||||
public void testEffect() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, KHARN, 1);
|
||||
addCard(Zone.LIBRARY, playerA, "Mountain", 5);
|
||||
addCard(Zone.LIBRARY, playerB, "Mountain", 5);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerC, "Mountain", 2);
|
||||
addCard(Zone.HAND, playerC, BOLT, 2);
|
||||
|
||||
// Player C pings Kharn, which triggers his effect.
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerC, BOLT, KHARN);
|
||||
// Player A chooses Player B to gain control, draws 2 cards when losing control.
|
||||
setChoice(playerA, "PlayerB");
|
||||
|
||||
// // Player C pings Kharn, triggering effect again.
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerC, BOLT, KHARN);
|
||||
// // Player B chooses player A, draws 2 cards when losing control.
|
||||
setChoice(playerB, "PlayerC");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
// Account for draw for turn
|
||||
assertHandCount(playerA, 1 + 2);
|
||||
assertHandCount(playerB, 2);
|
||||
assertHandCount(playerC, 0);
|
||||
assertPermanentCount(playerC, KHARN, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLostControl() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, KHARN, 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.HAND, playerA, OFFERING);
|
||||
addCard(Zone.LIBRARY, playerA, "Mountain", 5);
|
||||
|
||||
// Player A gives Kharn to player B, should trigger Kharn's effect
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, OFFERING);
|
||||
addTarget(playerA, playerB);
|
||||
addTarget(playerA, KHARN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
// Account for draw for turn
|
||||
assertPermanentCount(playerB, KHARN, 1);
|
||||
assertHandCount(playerA, 1 + 2);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue