From 785917deb69034b3d55eec8c7cb30e7daa3ba664 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Wed, 10 Apr 2019 16:14:34 -0400 Subject: [PATCH] Implemented Chandra, Fire Artisan --- .../src/mage/cards/c/ChandraFireArtisan.java | 135 ++++++++++++++++++ Mage.Sets/src/mage/sets/WarOfTheSpark.java | 1 + Mage/src/main/java/mage/cards/CardImpl.java | 6 + .../main/java/mage/game/events/GameEvent.java | 2 +- .../main/java/mage/players/PlayerImpl.java | 15 +- 5 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/c/ChandraFireArtisan.java diff --git a/Mage.Sets/src/mage/cards/c/ChandraFireArtisan.java b/Mage.Sets/src/mage/cards/c/ChandraFireArtisan.java new file mode 100644 index 00000000000..22635da2dca --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChandraFireArtisan.java @@ -0,0 +1,135 @@ +package mage.cards.c; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; +import mage.cards.*; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.common.TargetOpponentOrPlaneswalker; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ChandraFireArtisan extends CardImpl { + + public ChandraFireArtisan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{R}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.CHANDRA); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); + + // Whenever one or more loyalty counters are removed from Chandra, Fire Artisan, she deals that much damage to target opponent or planeswalker. + this.addAbility(new ChandraFireArtisanTriggeredAbility()); + + // +1: Exile the top card of your library. You may play it this turn. + this.addAbility(new LoyaltyAbility(new ChandraFireArtisanEffect(false), 1)); + + // -7: Exile the top seven cards of your library. You may play them this turn. + this.addAbility(new LoyaltyAbility(new ChandraFireArtisanEffect(true), -7)); + } + + private ChandraFireArtisan(final ChandraFireArtisan card) { + super(card); + } + + @Override + public ChandraFireArtisan copy() { + return new ChandraFireArtisan(this); + } +} + +class ChandraFireArtisanTriggeredAbility extends TriggeredAbilityImpl { + + ChandraFireArtisanTriggeredAbility() { + super(Zone.BATTLEFIELD, null); + this.addTarget(new TargetOpponentOrPlaneswalker()); + } + + private ChandraFireArtisanTriggeredAbility(final ChandraFireArtisanTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COUNTERS_REMOVED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getAmount() == 0 || event.getData() != "loyalty") { + return false; + } + this.getEffects().clear(); + this.addEffect(new DamageTargetEffect(event.getAmount())); + return true; + } + + @Override + public ChandraFireArtisanTriggeredAbility copy() { + return new ChandraFireArtisanTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever one or more loyalty counters are removed from {this}, " + + "she deals that much damage to target opponent or planeswalker."; + } +} + +class ChandraFireArtisanEffect extends OneShotEffect { + + private final boolean exileSeven; + + ChandraFireArtisanEffect(boolean exileSeven) { + super(Outcome.Detriment); + this.exileSeven = exileSeven; + if (exileSeven) { + staticText = "Exile the top seven cards of your library. You may play them this turn."; + } else { + staticText = "Exile the top card of your library. You may play it this turn"; + } + } + + private ChandraFireArtisanEffect(final ChandraFireArtisanEffect effect) { + super(effect); + this.exileSeven = effect.exileSeven; + } + + @Override + public ChandraFireArtisanEffect copy() { + return new ChandraFireArtisanEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller == null || sourceObject == null) { + return false; + } + Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, (exileSeven ? 7 : 1))); + controller.moveCards(cards, Zone.EXILED, source, game); + for (Card card : cards.getCards(game)) { + if (card == null) { + continue; + } + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(card, game)); + game.addEffect(effect, source); + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/WarOfTheSpark.java b/Mage.Sets/src/mage/sets/WarOfTheSpark.java index aaaeaa6d6e2..dbc3c0e9839 100644 --- a/Mage.Sets/src/mage/sets/WarOfTheSpark.java +++ b/Mage.Sets/src/mage/sets/WarOfTheSpark.java @@ -45,6 +45,7 @@ public final class WarOfTheSpark extends ExpansionSet { cards.add(new SetCardInfo("Challenger Troll", 157, Rarity.UNCOMMON, mage.cards.c.ChallengerTroll.class)); cards.add(new SetCardInfo("Chandra's Pyrohelix", 120, Rarity.COMMON, mage.cards.c.ChandrasPyrohelix.class)); cards.add(new SetCardInfo("Chandra's Triumph", 121, Rarity.UNCOMMON, mage.cards.c.ChandrasTriumph.class)); + cards.add(new SetCardInfo("Chandra, Fire Artisan", 119, Rarity.RARE, mage.cards.c.ChandraFireArtisan.class)); cards.add(new SetCardInfo("Courage in Crisis", 158, Rarity.COMMON, mage.cards.c.CourageInCrisis.class)); cards.add(new SetCardInfo("Cruel Celebrant", 188, Rarity.UNCOMMON, mage.cards.c.CruelCelebrant.class)); cards.add(new SetCardInfo("Crush Dissent", 47, Rarity.COMMON, mage.cards.c.CrushDissent.class)); diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index ae22f9da2a2..1bb7efb4e42 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -720,6 +720,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { @Override public void removeCounters(String name, int amount, Game game) { + int finalAmount = 0; for (int i = 0; i < amount; i++) { if (!getCounters(game).removeCounter(name, 1)) { break; @@ -727,7 +728,12 @@ public abstract class CardImpl extends MageObjectImpl implements Card { GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTER_REMOVED, objectId, getControllerOrOwner()); event.setData(name); game.fireEvent(event); + finalAmount++; } + GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTERS_REMOVED, objectId, getControllerOrOwner()); + event.setData(name); + event.setAmount(finalAmount); + game.fireEvent(event); } @Override diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index edff7314ab5..2d20ce98a0e 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -292,7 +292,7 @@ public class GameEvent implements Serializable { UNATTACH, UNATTACHED, ADD_COUNTER, COUNTER_ADDED, ADD_COUNTERS, COUNTERS_ADDED, - COUNTER_REMOVED, + COUNTER_REMOVED, COUNTERS_REMOVED, LOSE_CONTROL, /* LOST_CONTROL targetId id of the creature that lost control diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index b36a18d1089..d3139c37978 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -70,7 +70,6 @@ import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.*; import java.util.Map.Entry; -import java.util.stream.Collectors; public abstract class PlayerImpl implements Player, Serializable { @@ -184,7 +183,6 @@ public abstract class PlayerImpl implements Player, Serializable { put(PhaseStep.DECLARE_ATTACKERS, Step.StepPart.PRE).build(); - public PlayerImpl(String name, RangeOfInfluence range) { this(UUID.randomUUID()); this.name = name; @@ -739,9 +737,9 @@ public abstract class PlayerImpl implements Player, Serializable { TargetDiscard target = new TargetDiscard(possibleAmount, possibleAmount, new FilterCard(CardUtil.numberToText(possibleAmount, "a") + " card" + (possibleAmount > 1 ? "s" : "")), playerId); choose(Outcome.Discard, target, source == null ? null : source.getSourceId(), game); for (UUID cardId : target.getTargets()) { - if(discard(this.getHand().get(cardId, game), source, game)) { - discardedCards.add(cardId); - } + if (discard(this.getHand().get(cardId, game), source, game)) { + discardedCards.add(cardId); + } } } return discardedCards; @@ -2046,6 +2044,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void removeCounters(String name, int amount, Ability source, Game game) { + int finalAmount = 0; for (int i = 0; i < amount; i++) { if (!counters.removeCounter(name, 1)) { break; @@ -2055,7 +2054,13 @@ public abstract class PlayerImpl implements Player, Serializable { event.setData(name); event.setAmount(1); game.fireEvent(event); + finalAmount++; } + GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTERS_REMOVED, + getId(), (source == null ? null : source.getSourceId()), (source == null ? null : source.getControllerId())); + event.setData(name); + event.setAmount(finalAmount); + game.fireEvent(event); } protected boolean canDamage(MageObject source, Game game) {