mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
Implemented Rielle, the Everwise
This commit is contained in:
parent
186239ffa0
commit
618af9b365
5 changed files with 178 additions and 31 deletions
124
Mage.Sets/src/mage/cards/r/RielleTheEverwise.java
Normal file
124
Mage.Sets/src/mage/cards/r/RielleTheEverwise.java
Normal file
|
@ -0,0 +1,124 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class RielleTheEverwise extends CardImpl {
|
||||
|
||||
private static final DynamicValue xValue
|
||||
= new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY);
|
||||
|
||||
public RielleTheEverwise(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}");
|
||||
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Rielle, the Everwise gets +1/+0 for each instant and sorcery card in your graveyard.
|
||||
this.addAbility(new SimpleStaticAbility(new BoostSourceEffect(
|
||||
xValue, StaticValue.get(0), Duration.WhileOnBattlefield
|
||||
).setText("{this} gets +1/+0 for each instant and sorcery card in your graveyard")));
|
||||
|
||||
// Whenever you discard one or more cards for the first time each turn, draw that many cards.
|
||||
this.addAbility(new RielleTheEverwiseTriggeredAbility());
|
||||
}
|
||||
|
||||
private RielleTheEverwise(final RielleTheEverwise card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RielleTheEverwise copy() {
|
||||
return new RielleTheEverwise(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RielleTheEverwiseTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
RielleTheEverwiseTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, null);
|
||||
this.addWatcher(new RielleTheEverwiseWatcher());
|
||||
}
|
||||
|
||||
private RielleTheEverwiseTriggeredAbility(final RielleTheEverwiseTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DISCARDED_CARDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
RielleTheEverwiseWatcher watcher = game.getState().getWatcher(RielleTheEverwiseWatcher.class);
|
||||
if (watcher == null
|
||||
|| !watcher.checkDiscarded(event.getPlayerId())
|
||||
|| !event.getPlayerId().equals(getControllerId())
|
||||
|| event.getAmount() == 0) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().clear();
|
||||
this.addEffect(new DrawCardSourceControllerEffect(event.getAmount()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RielleTheEverwiseTriggeredAbility copy() {
|
||||
return new RielleTheEverwiseTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever you discard one or more cards for the first time each turn, draw that many cards.";
|
||||
}
|
||||
}
|
||||
|
||||
class RielleTheEverwiseWatcher extends Watcher {
|
||||
|
||||
private final Map<UUID, Integer> discardedThisTurn = new HashMap();
|
||||
|
||||
RielleTheEverwiseWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getAmount() > 0) {
|
||||
discardedThisTurn.compute(event.getPlayerId(), (u, i) -> i == null ? 1 : i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
this.discardedThisTurn.clear();
|
||||
}
|
||||
|
||||
boolean checkDiscarded(UUID playerId) {
|
||||
return discardedThisTurn.getOrDefault(playerId, 0) < 2;
|
||||
}
|
||||
}
|
|
@ -270,6 +270,7 @@ public final class IkoriaLairOfBehemoths extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Reconnaissance Mission", 65, Rarity.UNCOMMON, mage.cards.r.ReconnaissanceMission.class));
|
||||
cards.add(new SetCardInfo("Regal Leosaur", 202, Rarity.UNCOMMON, mage.cards.r.RegalLeosaur.class));
|
||||
cards.add(new SetCardInfo("Reptilian Reflection", 132, Rarity.UNCOMMON, mage.cards.r.ReptilianReflection.class));
|
||||
cards.add(new SetCardInfo("Rielle, the Everwise", 203, Rarity.MYTHIC, mage.cards.r.RielleTheEverwise.class));
|
||||
cards.add(new SetCardInfo("Rooting Moloch", 133, Rarity.UNCOMMON, mage.cards.r.RootingMoloch.class));
|
||||
cards.add(new SetCardInfo("Rugged Highlands", 252, Rarity.COMMON, mage.cards.r.RuggedHighlands.class));
|
||||
cards.add(new SetCardInfo("Ruinous Ultimatum", 204, Rarity.RARE, mage.cards.r.RuinousUltimatum.class));
|
||||
|
|
|
@ -33,12 +33,10 @@ public class DiscardHandControllerEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
for (Card card : player.getHand().getCards(game)) {
|
||||
player.discard(card, source, game);
|
||||
}
|
||||
return true;
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
player.discard(player.getHand().size(),false,source,game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ public class GameEvent implements Serializable {
|
|||
CONVOKED,
|
||||
DISCARD_CARD,
|
||||
DISCARDED_CARD,
|
||||
DISCARDED_CARDS,
|
||||
CYCLE_CARD, CYCLED_CARD, CYCLE_DRAW,
|
||||
CLASH, CLASHED,
|
||||
DAMAGE_PLAYER,
|
||||
|
|
|
@ -743,6 +743,18 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
@Override
|
||||
public Cards discard(int amount, boolean random, Ability source, Game game) {
|
||||
Cards discardedCards = doDiscard(amount, random, source, game);
|
||||
if (!discardedCards.isEmpty()) {
|
||||
UUID sourceId = source == null ? null : source.getSourceId();
|
||||
game.fireEvent(GameEvent.getEvent(
|
||||
GameEvent.EventType.DISCARDED_CARDS, sourceId,
|
||||
sourceId, playerId, discardedCards.size()
|
||||
));
|
||||
}
|
||||
return discardedCards;
|
||||
}
|
||||
|
||||
private Cards doDiscard(int amount, boolean random, Ability source, Game game) {
|
||||
Cards discardedCards = new CardsImpl();
|
||||
if (amount <= 0) {
|
||||
return discardedCards;
|
||||
|
@ -752,7 +764,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (this.getHand().size() == 1 || this.getHand().size() == amount) {
|
||||
List<UUID> cardsToDiscard = new ArrayList<>(this.getHand());
|
||||
for (UUID id : cardsToDiscard) {
|
||||
if (discard(this.getHand().get(id, game), source, game)) {
|
||||
if (doDiscard(this.getHand().get(id, game), source, game, false)) {
|
||||
discardedCards.add(id);
|
||||
}
|
||||
}
|
||||
|
@ -762,7 +774,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (random) {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
Card card = this.getHand().getRandom(game);
|
||||
if (discard(card, source, game)) {
|
||||
if (doDiscard(card, source, game, false)) {
|
||||
discardedCards.add(card);
|
||||
}
|
||||
}
|
||||
|
@ -773,7 +785,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
+ " 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)) {
|
||||
if (doDiscard(this.getHand().get(cardId, game), source, game, false)) {
|
||||
discardedCards.add(cardId);
|
||||
}
|
||||
}
|
||||
|
@ -783,6 +795,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
@Override
|
||||
public boolean discard(Card card, Ability source, Game game) {
|
||||
return doDiscard(card, source, game, true);
|
||||
}
|
||||
|
||||
private boolean doDiscard(Card card, Ability source, Game game, boolean fireEvent) {
|
||||
//20100716 - 701.7
|
||||
/* 701.7. Discard #
|
||||
701.7a To discard a card, move it from its owners hand to that players graveyard.
|
||||
|
@ -797,29 +813,36 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
about the discarded card, that cost payment is illegal; the game returns to
|
||||
the moment before the cost was paid (see rule 717, "Handling Illegal Actions").
|
||||
*/
|
||||
if (card != null) {
|
||||
GameEvent gameEvent = GameEvent.getEvent(GameEvent.EventType.DISCARD_CARD,
|
||||
card.getId(), source == null
|
||||
? null : source.getSourceId(), playerId);
|
||||
gameEvent.setFlag(source != null); // event from effect or from cost (source == null)
|
||||
if (!game.replaceEvent(gameEvent, source)) {
|
||||
// write info to game log first so game log infos from triggered or replacement effects follow in the game log
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(getLogName() + " discards " + card.getLogName());
|
||||
}
|
||||
/* If a card is discarded while Rest in Peace is on the battlefield, abilities that function
|
||||
* when a card is discarded (such as madness) still work, even though that card never reaches
|
||||
* a graveyard. In addition, spells or abilities that check the characteristics of a discarded
|
||||
* card (such as Chandra Ablaze's first ability) can find that card in exile. */
|
||||
card.moveToZone(Zone.GRAVEYARD, source == null ? null : source.getSourceId(), game, false);
|
||||
// So discard is also successful if card is moved to another zone by replacement effect!
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD,
|
||||
card.getId(), source == null
|
||||
? null : source.getSourceId(), playerId));
|
||||
return true;
|
||||
}
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
GameEvent gameEvent = GameEvent.getEvent(GameEvent.EventType.DISCARD_CARD,
|
||||
card.getId(), source == null
|
||||
? null : source.getSourceId(), playerId);
|
||||
gameEvent.setFlag(source != null); // event from effect or from cost (source == null)
|
||||
if (game.replaceEvent(gameEvent, source)) {
|
||||
return false;
|
||||
}
|
||||
// write info to game log first so game log infos from triggered or replacement effects follow in the game log
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(getLogName() + " discards " + card.getLogName());
|
||||
}
|
||||
/* If a card is discarded while Rest in Peace is on the battlefield, abilities that function
|
||||
* when a card is discarded (such as madness) still work, even though that card never reaches
|
||||
* a graveyard. In addition, spells or abilities that check the characteristics of a discarded
|
||||
* card (such as Chandra Ablaze's first ability) can find that card in exile. */
|
||||
card.moveToZone(Zone.GRAVEYARD, source == null ? null : source.getSourceId(), game, false);
|
||||
// So discard is also successful if card is moved to another zone by replacement effect!
|
||||
UUID sourceId = source == null ? null : source.getSourceId();
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD,
|
||||
card.getId(), sourceId, playerId));
|
||||
if (fireEvent) {
|
||||
game.fireEvent(GameEvent.getEvent(
|
||||
GameEvent.EventType.DISCARDED_CARDS, sourceId,
|
||||
sourceId, playerId, 1
|
||||
));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue