mirror of
https://github.com/correl/mage.git
synced 2024-12-29 11:09:17 +00:00
Implemented Jalum Grifter and Burning Cinder Fury
This commit is contained in:
parent
8445e98e2e
commit
7260e8d2ab
3 changed files with 370 additions and 0 deletions
|
@ -0,0 +1,226 @@
|
||||||
|
|
||||||
|
package mage.cards.b;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
||||||
|
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.abilities.effects.ContinuousEffect;
|
||||||
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.Target;
|
||||||
|
import mage.target.common.TargetOpponent;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
import mage.watchers.Watcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author L_J
|
||||||
|
*/
|
||||||
|
public final class BurningCinderFuryOfCrimsonChaosFire extends CardImpl {
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFire(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}");
|
||||||
|
|
||||||
|
// Whenever any player taps a permanent, that player choose one of their opponents. The chosen player gains control of that permanent at the beginning of the next end step.
|
||||||
|
this.addAbility(new BurningCinderFuryOfCrimsonChaosFireAbility());
|
||||||
|
|
||||||
|
// At the beginning of each player’s end step, if that player didn’t tap any nonland permanents that turn, Burning Cinder Fury of Crimson Chaos Fire deals 3 damage to that player.
|
||||||
|
this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(3).setText("{this} deals 3 damage to that player"),
|
||||||
|
TargetController.ANY, new BurningCinderFuryOfCrimsonChaosFireCondition(), false), new BurningCinderFuryOfCrimsonChaosFireWatcher());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFire(final BurningCinderFuryOfCrimsonChaosFire card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFire copy() {
|
||||||
|
return new BurningCinderFuryOfCrimsonChaosFire(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BurningCinderFuryOfCrimsonChaosFireAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireAbility() {
|
||||||
|
super(Zone.BATTLEFIELD, new BurningCinderFuryOfCrimsonChaosFireEffect(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireAbility(BurningCinderFuryOfCrimsonChaosFireAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.TAPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||||
|
if (permanent != null) {
|
||||||
|
BurningCinderFuryOfCrimsonChaosFireEffect effect = (BurningCinderFuryOfCrimsonChaosFireEffect) this.getEffects().get(0);
|
||||||
|
effect.setTargetPointer(new FixedTarget(permanent.getId()));
|
||||||
|
effect.setFirstController(permanent.getControllerId()); // it's necessary to remember the original controller, as the controller might change by the time the trigger resolves
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireAbility copy() {
|
||||||
|
return new BurningCinderFuryOfCrimsonChaosFireAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return "Whenever any player taps a permanent, " + super.getRule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BurningCinderFuryOfCrimsonChaosFireEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
private UUID firstController = null;
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireEffect() {
|
||||||
|
super(Outcome.Detriment);
|
||||||
|
this.staticText = "that player choose one of their opponents. The chosen player gains control of that permanent at the beginning of the next end step";
|
||||||
|
}
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireEffect(final BurningCinderFuryOfCrimsonChaosFireEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
this.firstController = effect.firstController;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireEffect copy() {
|
||||||
|
return new BurningCinderFuryOfCrimsonChaosFireEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstController(UUID newId) {
|
||||||
|
this.firstController = newId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player player = game.getPlayer(firstController);
|
||||||
|
if (player != null) {
|
||||||
|
Target target = new TargetOpponent(true);
|
||||||
|
if (target.canChoose(player.getId(), game)) {
|
||||||
|
while (!target.isChosen() && target.canChoose(player.getId(), game) && player.canRespond()) {
|
||||||
|
player.chooseTarget(outcome, target, source, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source));
|
||||||
|
Player chosenOpponent = game.getPlayer(target.getFirstTarget());
|
||||||
|
|
||||||
|
if (permanent != null && chosenOpponent != null) {
|
||||||
|
game.informPlayers(player.getLogName() + " chose " + chosenOpponent.getLogName() + " to gain control of " + permanent.getLogName() + " at the beginning of the next end step");
|
||||||
|
ContinuousEffect effect = new BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(Duration.Custom, chosenOpponent.getId());
|
||||||
|
effect.setTargetPointer(new FixedTarget(permanent.getId()));
|
||||||
|
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
|
private UUID controller;
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(Duration duration, UUID controller) {
|
||||||
|
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
|
||||||
|
this.controller = controller;
|
||||||
|
this.staticText = "the chosen player gains control of that permanent";
|
||||||
|
}
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(final BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
this.controller = effect.controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect copy() {
|
||||||
|
return new BurningCinderFuryOfCrimsonChaosFireCreatureGainControlEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||||
|
if (targetPointer != null) {
|
||||||
|
permanent = game.getPermanent(targetPointer.getFirst(game, source));
|
||||||
|
}
|
||||||
|
if (permanent != null && controller != null) {
|
||||||
|
return permanent.changeControllerId(controller, game);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BurningCinderFuryOfCrimsonChaosFireCondition implements Condition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
BurningCinderFuryOfCrimsonChaosFireWatcher watcher = (BurningCinderFuryOfCrimsonChaosFireWatcher) game.getState().getWatchers().get(BurningCinderFuryOfCrimsonChaosFireWatcher.class.getSimpleName());
|
||||||
|
if (watcher != null) {
|
||||||
|
return !watcher.tappedNonlandThisTurn(game.getActivePlayerId());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "if that player didn’t tap any nonland permanents that turn";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BurningCinderFuryOfCrimsonChaosFireWatcher extends Watcher {
|
||||||
|
|
||||||
|
private final Set<UUID> tappedActivePlayerIds = new HashSet<>();
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireWatcher() {
|
||||||
|
super(BurningCinderFuryOfCrimsonChaosFireWatcher.class.getSimpleName(), WatcherScope.GAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireWatcher(final BurningCinderFuryOfCrimsonChaosFireWatcher watcher) {
|
||||||
|
super(watcher);
|
||||||
|
this.tappedActivePlayerIds.addAll(watcher.tappedActivePlayerIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void watch(GameEvent event, Game game) {
|
||||||
|
if (event.getType() == GameEvent.EventType.TAPPED) {
|
||||||
|
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||||
|
if (permanent != null && !permanent.isLand()) {
|
||||||
|
tappedActivePlayerIds.add(permanent.getControllerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tappedNonlandThisTurn(UUID playerId) {
|
||||||
|
return tappedActivePlayerIds.contains(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
tappedActivePlayerIds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BurningCinderFuryOfCrimsonChaosFireWatcher copy() {
|
||||||
|
return new BurningCinderFuryOfCrimsonChaosFireWatcher(this);
|
||||||
|
}
|
||||||
|
}
|
142
Mage.Sets/src/mage/cards/j/JalumGrifter.java
Normal file
142
Mage.Sets/src/mage/cards/j/JalumGrifter.java
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
|
||||||
|
package mage.cards.j;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.cards.CardsImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SuperType;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.common.FilterControlledLandPermanent;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.Target;
|
||||||
|
import mage.target.TargetCard;
|
||||||
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.common.TargetControlledPermanent;
|
||||||
|
import mage.target.common.TargetOpponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author L_J
|
||||||
|
*/
|
||||||
|
public final class JalumGrifter extends CardImpl {
|
||||||
|
|
||||||
|
public JalumGrifter(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{R}");
|
||||||
|
this.addSuperType(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.DEVIL);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
|
// {1}{R}, {T}: Shuffle Jalum Grifter and two lands you control face down. Target opponent chooses one of those cards. Turn the cards face up. If they chose Jalum Grifter, sacrifice it. Otherwise, destroy target permanent.
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new JalumGrifterEffect(), new ManaCostsImpl("{1}{R}"));
|
||||||
|
ability.addCost(new TapSourceCost());
|
||||||
|
ability.addTarget(new TargetOpponent());
|
||||||
|
ability.addTarget(new TargetPermanent());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JalumGrifter(final JalumGrifter card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JalumGrifter copy() {
|
||||||
|
return new JalumGrifter(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JalumGrifterEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public JalumGrifterEffect() {
|
||||||
|
super(Outcome.DestroyPermanent);
|
||||||
|
this.staticText = "Shuffle {this} and two lands you control face down. Target opponent chooses one of those cards. Turn the cards face up. If they chose {this}, sacrifice it. Otherwise, destroy target permanent";
|
||||||
|
}
|
||||||
|
|
||||||
|
public JalumGrifterEffect(final JalumGrifterEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JalumGrifterEffect copy() {
|
||||||
|
return new JalumGrifterEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
Player opponent = game.getPlayer(source.getTargets().get(0).getFirstTarget());
|
||||||
|
if (controller != null && opponent != null) {
|
||||||
|
List<Card> shellGamePile = new ArrayList<>();
|
||||||
|
Card sourceCard = game.getCard(source.getSourceId());
|
||||||
|
if (sourceCard != null) {
|
||||||
|
sourceCard = sourceCard.copy();
|
||||||
|
sourceCard.setFaceDown(true, game);
|
||||||
|
shellGamePile.add(sourceCard);
|
||||||
|
game.informPlayers(controller.getLogName() + " turns " + sourceCard.getLogName() + " face down");
|
||||||
|
}
|
||||||
|
|
||||||
|
Target target = new TargetControlledPermanent(2, 2, new FilterControlledLandPermanent(), true);
|
||||||
|
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
|
||||||
|
while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) {
|
||||||
|
controller.chooseTarget(outcome, target, source, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UUID cardId: target.getTargets()) {
|
||||||
|
Card card = game.getCard(cardId);
|
||||||
|
if (card != null) {
|
||||||
|
card = card.copy();
|
||||||
|
card.setFaceDown(true, game);
|
||||||
|
shellGamePile.add(card);
|
||||||
|
game.informPlayers(controller.getLogName() + " turns " + card.getLogName() + " face down");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shellGamePile.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Collections.shuffle(shellGamePile);
|
||||||
|
game.informPlayers(controller.getLogName() + " shuffles the face-down pile");
|
||||||
|
TargetCard targetCard = new TargetCard(Zone.HAND, new FilterCard());
|
||||||
|
CardsImpl cards = new CardsImpl();
|
||||||
|
cards.addAll(shellGamePile);
|
||||||
|
if (opponent.choose(Outcome.Sacrifice, cards, targetCard, game)) {
|
||||||
|
Card card = game.getCard(targetCard.getFirstTarget());
|
||||||
|
if (card != null) {
|
||||||
|
card.setFaceDown(false, game);
|
||||||
|
game.informPlayers(opponent.getLogName() + " reveals " + card.getLogName());
|
||||||
|
if (card.getId().equals(sourceCard.getId())) {
|
||||||
|
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||||
|
if (sourcePermanent != null) {
|
||||||
|
sourcePermanent.sacrifice(source.getSourceId(), game);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Permanent permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||||
|
if (permanent != null) {
|
||||||
|
permanent.destroy(source.getSourceId(), game, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ public final class Unglued extends ExpansionSet {
|
||||||
private Unglued() {
|
private Unglued() {
|
||||||
super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET);
|
super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET);
|
||||||
|
|
||||||
|
cards.add(new SetCardInfo("Burning Cinder Fury of Crimson Chaos Fire", 40, Rarity.RARE, mage.cards.b.BurningCinderFuryOfCrimsonChaosFire.class));
|
||||||
cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class));
|
cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class));
|
||||||
cards.add(new SetCardInfo("Chicken a la King", 17, Rarity.RARE, mage.cards.c.ChickenALaKing.class));
|
cards.add(new SetCardInfo("Chicken a la King", 17, Rarity.RARE, mage.cards.c.ChickenALaKing.class));
|
||||||
cards.add(new SetCardInfo("Elvish Impersonators", 56, Rarity.COMMON, mage.cards.e.ElvishImpersonators.class));
|
cards.add(new SetCardInfo("Elvish Impersonators", 56, Rarity.COMMON, mage.cards.e.ElvishImpersonators.class));
|
||||||
|
@ -33,6 +34,7 @@ public final class Unglued extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Incoming!", 64, Rarity.RARE, mage.cards.i.Incoming.class));
|
cards.add(new SetCardInfo("Incoming!", 64, Rarity.RARE, mage.cards.i.Incoming.class));
|
||||||
cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false)));
|
cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false)));
|
||||||
cards.add(new SetCardInfo("Jack-in-the-Mox", 75, Rarity.RARE, mage.cards.j.JackInTheMox.class));
|
cards.add(new SetCardInfo("Jack-in-the-Mox", 75, Rarity.RARE, mage.cards.j.JackInTheMox.class));
|
||||||
|
cards.add(new SetCardInfo("Jalum Grifter", 47, Rarity.RARE, mage.cards.j.JalumGrifter.class));
|
||||||
cards.add(new SetCardInfo("Jumbo Imp", 34, Rarity.UNCOMMON, mage.cards.j.JumboImp.class));
|
cards.add(new SetCardInfo("Jumbo Imp", 34, Rarity.UNCOMMON, mage.cards.j.JumboImp.class));
|
||||||
cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class));
|
cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class));
|
||||||
cards.add(new SetCardInfo("Mine, Mine, Mine!", 65, Rarity.RARE, mage.cards.m.MineMineMine.class));
|
cards.add(new SetCardInfo("Mine, Mine, Mine!", 65, Rarity.RARE, mage.cards.m.MineMineMine.class));
|
||||||
|
|
Loading…
Reference in a new issue