Merge branch 'feature/UphillBattle' of https://github.com/delftswa2018/mage into feature/UphillBattle

This commit is contained in:
Christiaan 2018-03-06 16:50:47 +01:00
commit 94de3b405b
217 changed files with 7964 additions and 1498 deletions

View file

@ -27,6 +27,7 @@
*/
package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@ -44,8 +45,6 @@ import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author LevelX2
@ -53,8 +52,7 @@ import java.util.UUID;
public class ActOfAuthority extends CardImpl {
public ActOfAuthority(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}");
// When Act of Authority enters the battlefield, you may exile target artifact or enchantment.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect(), true);
@ -96,9 +94,12 @@ class ActOfAuthorityEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Permanent targetPermanent = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (targetPermanent != null && new ExileTargetEffect().apply(game, source)) {
ContinuousEffect effect = new ActOfAuthorityGainControlEffect(Duration.Custom, targetPermanent.getControllerId());
effect.setTargetPointer(new FixedTarget(source.getSourceId()));
game.addEffect(effect, source);
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
if (sourcePermanent != null) {
ContinuousEffect effect = new ActOfAuthorityGainControlEffect(Duration.Custom, targetPermanent.getControllerId());
effect.setTargetPointer(new FixedTarget(sourcePermanent, game));
game.addEffect(effect, source);
}
return true;
}
return false;

View file

@ -109,7 +109,7 @@ class AdarkarValkyrieEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(new FixedTarget(this.getTargetPointer().getFirst(game, source)));
DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(getTargetPointer().getFixedTarget(game, source));
game.addDelayedTriggeredAbility(delayedAbility, source);
return false;
}

View file

@ -51,17 +51,17 @@ import mage.target.targetpointer.FixedTarget;
public class AmbuscadeShaman extends CardImpl {
public AmbuscadeShaman(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.ORC);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Ambuscade Shaman or another creature enters the battlefield under your control, that creature gets +2/+2 until end of turn.
Effect effect = new BoostTargetEffect(2,2, Duration.EndOfTurn);
Effect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn);
effect.setText("that creature gets +2/+2 until end of turn");
this.addAbility(new AmbuscadeShamanTriggeredAbility(effect));
// Dash {3}{B} <i>(You may cast this spell for its dash cost. If you do, it gains haste, and it's returned from the battlefield to its owner's hand at the beginning of the next end step.)</i>);
this.addAbility(new DashAbility(this, "{3}{B}"));
@ -103,9 +103,7 @@ class AmbuscadeShamanTriggeredAbility extends TriggeredAbilityImpl {
Permanent permanent = game.getPermanent(targetId);
if (permanent.getControllerId().equals(this.controllerId)
&& permanent.isCreature()) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
}
this.getEffects().setTargetPointer(new FixedTarget(permanent, game));
return true;
}
return false;
@ -115,4 +113,4 @@ class AmbuscadeShamanTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever {this} or another creature enters the battlefield under your control, that creature gets +2/+2 until end of turn.";
}
}
}

View file

@ -100,7 +100,7 @@ class AnimateDeadReAttachEffect extends OneShotEffect {
public AnimateDeadReAttachEffect() {
super(Outcome.Benefit);
this.staticText = "Return enchanted creature card to the battlefield under your control and attach {this} to it";
this.staticText = "return enchanted creature card to the battlefield under your control and attach {this} to it";
}
public AnimateDeadReAttachEffect(final AnimateDeadReAttachEffect effect) {

View file

@ -45,16 +45,16 @@ import mage.target.targetpointer.FixedTarget;
/**
*
* @author KholdFuzion
*
*/
public class AnkhOfMishra extends CardImpl {
public AnkhOfMishra(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// Whenever a land enters the battlefield, Ankh of Mishra deals 2 damage to that land's controller.
this.addAbility(new AnkhOfMishraAbility());
}
public AnkhOfMishra(final AnkhOfMishra card) {
@ -70,16 +70,16 @@ public class AnkhOfMishra extends CardImpl {
class AnkhOfMishraAbility extends TriggeredAbilityImpl {
public AnkhOfMishraAbility() {
super(Zone.BATTLEFIELD, new DamageTargetEffect(2));
super(Zone.BATTLEFIELD, new DamageTargetEffect(2));
}
AnkhOfMishraAbility(final AnkhOfMishraAbility ability) {
super(ability);
super(ability);
}
@Override
public AnkhOfMishraAbility copy() {
return new AnkhOfMishraAbility(this);
return new AnkhOfMishraAbility(this);
}
@Override
@ -104,6 +104,6 @@ class AnkhOfMishraAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return "Whenever a land enters the battlefield, Ankh of Mishra deals 2 damage to that land's controller.";
return "Whenever a land enters the battlefield, {this} deals 2 damage to that land's controller.";
}
}
}

View file

@ -29,6 +29,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
@ -53,7 +54,7 @@ import mage.target.targetpointer.FixedTarget;
public class ArbiterOfTheIdeal extends CardImpl {
public ArbiterOfTheIdeal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
this.subtype.add(SubType.SPHINX);
this.power = new MageInt(4);
@ -79,6 +80,7 @@ public class ArbiterOfTheIdeal extends CardImpl {
class ArbiterOfTheIdealEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard();
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
@ -102,32 +104,25 @@ class ArbiterOfTheIdealEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller == null || sourceObject == null) {
return false;
}
if (player.getLibrary().hasCards()) {
Card card = player.getLibrary().getFromTop(game);
Cards cards = new CardsImpl();
cards.add(card);
player.revealCards("Arbiter of the Ideal", cards, game);
if (card != null) {
if (filter.match(card, game) && player.chooseUse(outcome, new StringBuilder("Put ").append(card.getName()).append("onto battlefield?").toString(), source, game)) {
card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), source.getControllerId());
Permanent permanent = game.getPermanent(card.getId());
if (permanent != null) {
permanent.addCounters(new Counter("Manifestation"), source, game);
ContinuousEffect effect = new AddCardTypeTargetEffect(Duration.Custom, CardType.ENCHANTMENT);
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
}
Card card = controller.getLibrary().getFromTop(game);
if (card != null) {
controller.revealCards(sourceObject.getIdName(), new CardsImpl(card), game);
if (filter.match(card, game) && controller.chooseUse(outcome, "Put " + card.getName() + "onto battlefield?", source, game)) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
Permanent permanent = game.getPermanent(card.getId());
if (permanent != null) {
permanent.addCounters(new Counter("Manifestation"), source, game);
ContinuousEffect effect = new AddCardTypeTargetEffect(Duration.Custom, CardType.ENCHANTMENT);
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
}
}
return true;
}
return false;
return true;
}
}

View file

@ -29,23 +29,18 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
* @author Loki
@ -53,7 +48,7 @@ import mage.target.targetpointer.FixedTarget;
public class ArchonOfRedemption extends CardImpl {
public ArchonOfRedemption(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
this.subtype.add(SubType.ARCHON);
this.power = new MageInt(3);
@ -75,8 +70,9 @@ public class ArchonOfRedemption extends CardImpl {
}
class ArchonOfRedemptionTriggeredAbility extends TriggeredAbilityImpl {
ArchonOfRedemptionTriggeredAbility() {
super(Zone.BATTLEFIELD, new ArchonOfRedemptionEffect(), true);
super(Zone.BATTLEFIELD, null, true);
}
ArchonOfRedemptionTriggeredAbility(final ArchonOfRedemptionTriggeredAbility ability) {
@ -95,15 +91,13 @@ class ArchonOfRedemptionTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
UUID targetId = event.getTargetId();
Permanent permanent = game.getPermanent(targetId);
if (permanent.getControllerId().equals(this.controllerId)
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent.getControllerId().equals(getControllerId())
&& permanent.isCreature()
&& (targetId.equals(this.getSourceId())
|| (permanent.getAbilities().contains(FlyingAbility.getInstance()) && !targetId.equals(this.getSourceId())))) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
}
&& (permanent.getId().equals(getSourceId())
|| (permanent.getAbilities().contains(FlyingAbility.getInstance())))) {
this.getEffects().clear();
this.addEffect(new GainLifeEffect(permanent.getPower().getValue()));
return true;
}
return false;
@ -111,35 +105,6 @@ class ArchonOfRedemptionTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return "Whenever {this} or another creature with flying enters the battlefield under your control, you may gain life equal to that creature's power";
return "Whenever {this} or another creature with flying enters the battlefield under your control, you may gain life equal to that creature's power.";
}
}
class ArchonOfRedemptionEffect extends OneShotEffect {
ArchonOfRedemptionEffect() {
super(Outcome.GainLife);
}
ArchonOfRedemptionEffect(final ArchonOfRedemptionEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent p = game.getPermanent(targetPointer.getFirst(game, source));
Player player = game.getPlayer(source.getControllerId());
if (p == null) {
p = (Permanent) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.BATTLEFIELD);
}
if (p != null && player != null) {
player.gainLife(p.getPower().getValue(), game);
return true;
}
return false;
}
@Override
public ArchonOfRedemptionEffect copy() {
return new ArchonOfRedemptionEffect(this);
}
}

View file

@ -53,7 +53,7 @@ import mage.target.targetpointer.FixedTarget;
public class ArrogantBloodlord extends CardImpl {
public ArrogantBloodlord(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}");
this.subtype.add(SubType.VAMPIRE);
this.subtype.add(SubType.KNIGHT);
@ -104,11 +104,8 @@ class ArrogantBloodlordTriggeredAbility extends TriggeredAbilityImpl {
&& Objects.equals(blocked, arrogantBloodlord)) {
return true;
}
if (blocker != null && Objects.equals(blocker, arrogantBloodlord)
&& game.getPermanent(event.getTargetId()).getPower().getValue() < 2) {
return true;
}
return false;
return blocker != null && Objects.equals(blocker, arrogantBloodlord)
&& game.getPermanent(event.getTargetId()).getPower().getValue() < 2;
}
@Override
@ -133,7 +130,7 @@ class ArrogantBloodlordEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect());
delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(source.getSourceId()));
delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(permanent, game));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}

View file

@ -37,16 +37,13 @@ import mage.abilities.effects.common.CounterUnlessPaysEffect;
import mage.abilities.keyword.BandingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.FilterStackObject;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.stack.StackAbility;
import mage.target.common.TargetActivatedOrTriggeredAbility;
import mage.filter.FilterAbility;
import mage.filter.predicate.ability.ArtifactSourcePredicate;
import mage.target.common.TargetActivatedAbility;
/**
*
@ -54,26 +51,26 @@ import mage.target.common.TargetActivatedOrTriggeredAbility;
*/
public class AyeshaTanaka extends CardImpl {
private final static FilterStackObject filter = new FilterStackObject("activated ability from an artifact source");
private final static FilterAbility filter = new FilterAbility("activated ability from an artifact source");
static {
filter.add(new ArtifactSourcePredicate());
}
public AyeshaTanaka(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}{W}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}{U}{U}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ARTIFICER);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Banding
this.addAbility(BandingAbility.getInstance());
// {T}: Counter target activated ability from an artifact source unless that ability's controller pays {W}.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(new ManaCostsImpl("{W}")), new TapSourceCost());
ability.addTarget(new TargetActivatedOrTriggeredAbility(filter));
ability.addTarget(new TargetActivatedAbility(filter));
this.addAbility(ability);
}
@ -86,22 +83,3 @@ public class AyeshaTanaka extends CardImpl {
return new AyeshaTanaka(this);
}
}
class ArtifactSourcePredicate implements Predicate<Ability> {
public ArtifactSourcePredicate() {
}
@Override
public boolean apply(Ability input, Game game) {
if (input instanceof StackAbility) {
return input.getSourceObject(game).isArtifact() && input.getAbilityType() == AbilityType.ACTIVATED;
}
return false;
}
@Override
public String toString() {
return "Source(Artifact)";
}
}

View file

@ -103,7 +103,7 @@ class BackFromTheBrinkCost extends CostImpl {
if (controller != null) {
Card card = controller.getGraveyard().get(targets.getFirstTarget(), game);
if (card != null && controller.moveCards(card, Zone.EXILED, ability, game)) {
ability.getEffects().get(0).setTargetPointer(new FixedTarget(card.getId()));
ability.getEffects().get(0).setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId())));
paid = card.getManaCost().pay(ability, game, sourceId, controllerId, noMana);
}
}

View file

@ -161,14 +161,24 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect {
// Relevant ruling for Balduvian Warlord:
// 7/15/2006 If an attacking creature has an ability that triggers When this creature becomes blocked,
// it triggers when a creature blocks it due to the Warlords ability only if it was unblocked at that point.
boolean notYetBlocked = chosenGroup.getBlockers().isEmpty();
chosenGroup.addBlocker(permanent.getId(), controller.getId(), game);
chosenGroup.addBlockerToGroup(permanent.getId(), controller.getId(), game);
game.getCombat().addBlockingGroup(permanent.getId(), chosenPermanent.getId(), controller.getId(), game); // 702.21h
if (notYetBlocked) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, chosenPermanent.getId(), null));
for (UUID bandedId : chosenPermanent.getBandedCards()) {
CombatGroup bandedGroup = game.getCombat().findGroup(bandedId);
if (bandedGroup != null && chosenGroup.getBlockers().size() == 1) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, bandedId, null));
}
}
}
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, chosenPermanent.getId(), permanent.getId(), permanent.getControllerId()));
}
CombatGroup blockGroup = findBlockingGroup(permanent, game); // a new blockingGroup is formed, so it's necessary to find it again
if (blockGroup != null) {
blockGroup.pickAttackerOrder(permanent.getControllerId(), game);
}
}
}
return true;
@ -176,4 +186,15 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect {
}
return false;
}
private CombatGroup findBlockingGroup(Permanent blocker, Game game) {
if (game.getCombat().blockingGroupsContains(blocker.getId())) { // if (blocker.getBlocking() > 1) {
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
if (group.getBlockers().contains(blocker.getId())) {
return group;
}
}
}
return null;
}
}

View file

@ -52,7 +52,7 @@ public class BarrinsUnmaking extends CardImpl {
public BarrinsUnmaking(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
// Return target permanent to its owner's hand if that permanent shares a color with the most common color among all permanents or a color tied for most common.
// Return target permanent to its owner's hand if that permanent shares a color with the most common color among all permanents or a color tied for most common.
this.getSpellAbility().addEffect(new BarrinsUnmakingEffect());
this.getSpellAbility().addTarget(new TargetPermanent());
}
@ -85,12 +85,12 @@ class BarrinsUnmakingEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
Condition condition = new MostCommonColorCondition(permanent.getColor(game));
if (condition.apply(game, source)) {
Effect effect = new ReturnToHandTargetEffect();
effect.setTargetPointer(new FixedTarget(permanent.getId()));
effect.setTargetPointer(new FixedTarget(permanent, game));
return effect.apply(game, source);
}
}

View file

@ -0,0 +1,132 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.RedirectionEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.TargetSource;
/**
*
* @author L_J
*/
public class BeaconOfDestiny extends CardImpl {
public BeaconOfDestiny(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.CLERIC);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// {T}: The next time a source of your choice would deal damage to you this turn, that damage is dealt to Beacon of Destiny instead.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BeaconOfDestinyEffect(), new TapSourceCost()));
}
public BeaconOfDestiny(final BeaconOfDestiny card) {
super(card);
}
@Override
public BeaconOfDestiny copy() {
return new BeaconOfDestiny(this);
}
}
class BeaconOfDestinyEffect extends RedirectionEffect {
private final TargetSource damageSource;
public BeaconOfDestinyEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, true);
staticText = "The next time a source of your choice would deal damage to you this turn, that damage is dealt to {this} instead";
this.damageSource = new TargetSource();
}
public BeaconOfDestinyEffect(final BeaconOfDestinyEffect effect) {
super(effect);
this.damageSource = effect.damageSource.copy();
}
@Override
public BeaconOfDestinyEffect copy() {
return new BeaconOfDestinyEffect(this);
}
@Override
public void init(Ability source, Game game) {
this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
super.init(source, game);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
// check source
MageObject object = game.getObject(event.getSourceId());
if (object == null) {
game.informPlayers("Couldn't find source of damage");
return false;
}
if (!object.getId().equals(damageSource.getFirstTarget())
&& (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(damageSource.getFirstTarget()))) {
return false;
}
TargetPermanent target = new TargetPermanent();
target.add(source.getSourceId(), game);
this.redirectTarget = target;
// check player
Player player = game.getPlayer(event.getTargetId());
if (player != null) {
if (player.getId().equals(source.getControllerId())) {
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,127 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.b;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.BeforeBlockersAreDeclaredCondition;
import mage.abilities.effects.RequirementEffect;
import mage.abilities.effects.common.combat.CanBlockAdditionalCreatureTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.TurnPhase;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.ObjectPlayer;
import mage.filter.predicate.ObjectPlayerPredicate;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public class BlazeOfGlory extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls");
static {
filter.add(new BlazeOfGloryDefendingPlayerControlsPredicate());
}
public BlazeOfGlory(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
// Cast Blaze of Glory only during combat before blockers are declared.
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(TurnPhase.COMBAT, BeforeBlockersAreDeclaredCondition.instance));
// Target creature defending player controls can block any number of creatures this turn. It blocks each attacking creature this turn if able.
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
this.getSpellAbility().addEffect(new CanBlockAdditionalCreatureTargetEffect(Duration.EndOfTurn, 0));
this.getSpellAbility().addEffect(new BlazeOfGloryRequirementEffect());
}
public BlazeOfGlory(final BlazeOfGlory card) {
super(card);
}
@Override
public BlazeOfGlory copy() {
return new BlazeOfGlory(this);
}
}
class BlazeOfGloryDefendingPlayerControlsPredicate implements ObjectPlayerPredicate<ObjectPlayer<Controllable>> {
@Override
public boolean apply(ObjectPlayer<Controllable> input, Game game) {
return game.getCombat().getPlayerDefenders(game).contains(input.getObject().getControllerId());
}
}
class BlazeOfGloryRequirementEffect extends RequirementEffect {
public BlazeOfGloryRequirementEffect() {
super(Duration.EndOfTurn);
this.staticText = "It blocks each attacking creature this turn if able";
}
public BlazeOfGloryRequirementEffect(final BlazeOfGloryRequirementEffect effect) {
super(effect);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return permanent.getId().equals(targetPointer.getFirst(game, source));
}
@Override
public boolean mustAttack(Game game) {
return false;
}
@Override
public boolean mustBlock(Game game) {
return true;
}
@Override
public boolean mustBlockAllAttackers(Game game) {
return true;
}
@Override
public BlazeOfGloryRequirementEffect copy() {
return new BlazeOfGloryRequirementEffect(this);
}
}

View file

@ -53,7 +53,7 @@ import java.util.UUID;
*/
public class BrassTalonChimera extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Chimera creature you control");
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Chimera creature");
static {
filter.add(new SubtypePredicate(SubType.CHIMERA));

View file

@ -27,6 +27,7 @@
*/
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -35,17 +36,12 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterStackObject;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.stack.StackAbility;
import mage.target.common.TargetActivatedOrTriggeredAbility;
import java.util.UUID;
import mage.filter.FilterAbility;
import mage.filter.predicate.ability.ArtifactSourcePredicate;
import mage.target.common.TargetActivatedAbility;
/**
*
@ -53,7 +49,7 @@ import java.util.UUID;
*/
public class BrownOuphe extends CardImpl {
private final static FilterStackObject filter = new FilterStackObject("activated ability from an artifact source");
private final static FilterAbility filter = new FilterAbility("activated ability from an artifact source");
static {
filter.add(new ArtifactSourcePredicate());
@ -69,7 +65,7 @@ public class BrownOuphe extends CardImpl {
// {1}{G}, {tap}: Counter target activated ability from an artifact source.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl<>("{1}{G}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetActivatedOrTriggeredAbility(filter));
ability.addTarget(new TargetActivatedAbility(filter));
this.addAbility(ability);
}
@ -82,22 +78,3 @@ public class BrownOuphe extends CardImpl {
return new BrownOuphe(this);
}
}
class ArtifactSourcePredicate implements Predicate<Ability> {
public ArtifactSourcePredicate() {
}
@Override
public boolean apply(Ability input, Game game) {
if (input instanceof StackAbility) {
return input.getSourceObject(game).isArtifact() && input.getAbilityType() == AbilityType.ACTIVATED;
}
return false;
}
@Override
public String toString() {
return "Source(Artifact)";
}
}

View file

@ -28,21 +28,16 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.UntapAllEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
* @author Loki
@ -57,8 +52,9 @@ public class CallToGlory extends CardImpl {
public CallToGlory(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
this.getSpellAbility().addEffect(new CalltoGloryFirstEffect());
//Untap all creatures you control. Samurai creatures you control get +1/+1 until end of turn.
this.getSpellAbility().addEffect(new UntapAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE));
this.getSpellAbility().addEffect(new BoostControlledEffect(1, 1, Duration.EndOfTurn, filter, false));
}
@ -70,35 +66,4 @@ public class CallToGlory extends CardImpl {
public CallToGlory copy() {
return new CallToGlory(this);
}
}
class CalltoGloryFirstEffect extends OneShotEffect {
public CalltoGloryFirstEffect() {
super(Outcome.Untap);
staticText = "Untap all creatures you control";
}
public CalltoGloryFirstEffect(final CalltoGloryFirstEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
for (Permanent creature : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), game)) {
creature.untap(game);
}
return true;
}
return false;
}
@Override
public CalltoGloryFirstEffect copy() {
return new CalltoGloryFirstEffect(this);
}
}

View file

@ -28,6 +28,7 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
@ -48,7 +49,7 @@ import mage.game.events.GameEvent.EventType;
public class CityOfSolitude extends CardImpl {
public CityOfSolitude(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
// Players can cast spells and activate abilities only during their own turns.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CityOfSolitudeEffect()));
@ -74,12 +75,22 @@ class CityOfSolitudeEffect extends ContinuousRuleModifyingEffectImpl {
CityOfSolitudeEffect(final CityOfSolitudeEffect effect) {
super(effect);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.CAST_SPELL || event.getType() == EventType.ACTIVATE_ABILITY;
}
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject eventObject = game.getObject(event.getSourceId());
if (sourceObject != null && eventObject != null) {
return "You can cast or activate anability of " + eventObject.getIdName() + " only during your own turns (" + sourceObject.getIdName() + "). ";
}
return null;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return !game.getActivePlayerId().equals(event.getPlayerId());
@ -89,4 +100,4 @@ class CityOfSolitudeEffect extends ContinuousRuleModifyingEffectImpl {
public CityOfSolitudeEffect copy() {
return new CityOfSolitudeEffect(this);
}
}
}

View file

@ -41,9 +41,9 @@ import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffec
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
@ -60,7 +60,7 @@ import mage.target.targetpointer.FixedTarget;
public class CoffinQueen extends CardImpl {
public CoffinQueen(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(1);
@ -68,14 +68,14 @@ public class CoffinQueen extends CardImpl {
// You may choose not to untap Coffin Queen during your untap step.
this.addAbility(new SkipUntapOptionalAbility());
// {2}{B}, {tap}: Put target creature card from a graveyard onto the battlefield under your control. When Coffin Queen becomes untapped or you lose control of Coffin Queen, exile that creature.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), new ManaCostsImpl("{2}{B}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard")));
ability.addEffect(new CoffinQueenCreateDelayedTriggerEffect());
ability.addEffect(new CoffinQueenCreateDelayedTriggerEffect());
this.addAbility(ability);
}
public CoffinQueen(final CoffinQueen card) {
@ -87,33 +87,30 @@ public class CoffinQueen extends CardImpl {
return new CoffinQueen(this);
}
}
class CoffinQueenCreateDelayedTriggerEffect extends OneShotEffect {
public CoffinQueenCreateDelayedTriggerEffect() {
super(Outcome.Detriment);
this.staticText = "When Coffin Queen becomes untapped or you lose control of Coffin Queen, exile that creature";
this.staticText = "When {this} becomes untapped or you lose control of {this}, exile that creature.";
}
public CoffinQueenCreateDelayedTriggerEffect(final CoffinQueenCreateDelayedTriggerEffect effect) {
super(effect);
}
@Override
public CoffinQueenCreateDelayedTriggerEffect copy() {
return new CoffinQueenCreateDelayedTriggerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent controlledCreature = game.getPermanent(source.getFirstTarget());
if (controlledCreature != null) {
DelayedTriggeredAbility delayedAbility = new CoffinQueenDelayedTriggeredAbility();
delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(controlledCreature.getId()));
delayedAbility.setSourceId(source.getSourceId());
delayedAbility.setControllerId(source.getControllerId());
delayedAbility.setSourceObject(source.getSourceObject(game), game);
delayedAbility.init(game);
game.addDelayedTriggeredAbility(delayedAbility);
delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(controlledCreature, game));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
return false;
@ -123,7 +120,7 @@ class CoffinQueenCreateDelayedTriggerEffect extends OneShotEffect {
class CoffinQueenDelayedTriggeredAbility extends DelayedTriggeredAbility {
CoffinQueenDelayedTriggeredAbility() {
super(new ExileTargetEffect(), Duration.EndOfGame, true);
super(new ExileTargetEffect(), Duration.EndOfGame, true);
}
CoffinQueenDelayedTriggeredAbility(CoffinQueenDelayedTriggeredAbility ability) {
@ -136,7 +133,6 @@ class CoffinQueenDelayedTriggeredAbility extends DelayedTriggeredAbility {
|| event.getType() == EventType.UNTAPPED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (EventType.LOST_CONTROL == event.getType()
@ -146,14 +142,14 @@ class CoffinQueenDelayedTriggeredAbility extends DelayedTriggeredAbility {
return EventType.UNTAPPED == event.getType()
&& event.getTargetId() != null && event.getTargetId().equals(getSourceId());
}
@Override
public CoffinQueenDelayedTriggeredAbility copy() {
return new CoffinQueenDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When {this} becomes untapped or you lose control of {this}, exile that creature";
return "When {this} becomes untapped or you lose control of {this}, exile that creature.";
}
}

View file

@ -81,7 +81,7 @@ public class ConduitOfRuin extends CardImpl {
// The first creature spell you cast each turn costs {2} less to cast.
Effect effect = new SpellsCostReductionControllerEffect(filterCost, 2);
effect.setText("The first creature spell you cast each turn costs {2} less to cast");
effect.setText("The first creature spell you cast each turn costs {2} less to cast.");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new ConduitOfRuinWatcher());
}

View file

@ -30,7 +30,6 @@ package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.costs.common.DiscardXTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.DynamicValue;
@ -82,8 +81,8 @@ class ConflagrateVariableValue implements DynamicValue {
public int calculate(Game game, Ability sourceAbility, Effect effect) {
int xValue = sourceAbility.getManaCostsToPay().getX();
for (Cost cost : sourceAbility.getCosts()) {
if (cost instanceof DiscardTargetCost) {
xValue = ((DiscardTargetCost) cost).getCards().size();
if (cost instanceof DiscardXTargetCost) {
xValue = ((DiscardXTargetCost) cost).getAmount();
}
}
return xValue;

View file

@ -0,0 +1,142 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetOpponent;
/**
*
* @author TheElk801 & L_J
*/
public class CruelFate extends CardImpl {
public CruelFate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U}");
// Look at the top five cards of target opponent's library. Put one of those cards into that player's graveyard and the rest on top of his or her library in any order.
this.getSpellAbility().addEffect(new CruelFateEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
}
public CruelFate(final CruelFate card) {
super(card);
}
@Override
public CruelFate copy() {
return new CruelFate(this);
}
}
class CruelFateEffect extends OneShotEffect {
public CruelFateEffect() {
super(Outcome.DrawCard);
this.staticText = "Look at the top five cards of target opponent's library. Put one of those cards into that player's graveyard and the rest on top of his or her library in any order";
}
public CruelFateEffect(final CruelFateEffect effect) {
super(effect);
}
@Override
public CruelFateEffect copy() {
return new CruelFateEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard != null) {
Player you = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(source.getFirstTarget());
if (player != null && you != null) {
Cards cards = new CardsImpl();
int count = Math.min(player.getLibrary().size(), 5);
for (int i = 0; i < count; i++) {
Card card = player.getLibrary().removeFromTop(game);
if (card != null) {
cards.add(card);
}
}
you.lookAtCards(sourceCard.getIdName(), cards, game);
// card to put into opponent's graveyard
TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCard("card to put into target opponent's graveyard"));
if (player.canRespond()) {
if (cards.size() > 1) {
you.choose(Outcome.Detriment, cards, target, game);
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
card.moveToZone(Zone.GRAVEYARD, source.getSourceId(), game, true);
}
}
else if (cards.size() == 1) {
Card card = cards.get(cards.iterator().next(), game);
card.moveToZone(Zone.GRAVEYARD, source.getSourceId(), game, true);
}
}
// cards to put on the top of opponent's library
TargetCard target2 = new TargetCard(Zone.LIBRARY, new FilterCard("card to put on the top of target opponent's library"));
while (player.canRespond() && cards.size() > 1) {
you.choose(Outcome.Neutral, cards, target2, game);
Card card = cards.get(target2.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
target2.clearChosen();
}
if (cards.size() == 1) {
Card card = cards.get(cards.iterator().next(), game);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.PreventionEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.filter.common.FilterAttackingCreature;
import mage.game.Game;
import mage.game.events.DamagePlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author L_J
*/
public class DeepWood extends CardImpl {
public DeepWood(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}");
// Cast Deep Wood only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// Prevent all damage that would be dealt to you this turn by attacking creatures.
this.getSpellAbility().addEffect(new DeepWoodEffect());
}
public DeepWood(final DeepWood card) {
super(card);
}
@Override
public DeepWood copy() {
return new DeepWood(this);
}
}
class DeepWoodEffect extends PreventionEffectImpl {
private static final FilterAttackingCreature filter = new FilterAttackingCreature();
DeepWoodEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
staticText = "Prevent all damage that would be dealt to you this turn by attacking creatures";
}
DeepWoodEffect(final DeepWoodEffect effect) {
super(effect);
}
@Override
public DeepWoodEffect copy() {
return new DeepWoodEffect(this);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (super.applies(event, source, game) && event instanceof DamagePlayerEvent && event.getAmount() > 0) {
DamagePlayerEvent damageEvent = (DamagePlayerEvent) event;
if (event.getTargetId().equals(source.getControllerId())) {
Permanent permanent = game.getPermanentOrLKIBattlefield(damageEvent.getSourceId());
if (permanent != null && filter.match(permanent, game)) {
return true;
}
}
}
return false;
}
}

View file

@ -124,7 +124,7 @@ class DefiantVanguardEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent thisCreature = game.getPermanentOrLKIBattlefield(source.getId());
Permanent thisCreature = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (controller != null && thisCreature != null) {
BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName());
if (watcher != null) {
@ -136,10 +136,10 @@ class DefiantVanguardEffect extends OneShotEffect {
}
}
}
thisCreature.destroy(source.getSourceId(), game, false);
for (Permanent creature : toDestroy) {
creature.destroy(source.getSourceId(), game, false);
}
thisCreature.destroy(source.getSourceId(), game, false);
return true;
}
}

View file

@ -68,8 +68,7 @@ public class DiamondKaleidoscope extends CardImpl {
this.addAbility(ability);
// Sacrifice a Prism token: Add one mana of any color to your mana pool.
ability = new AnyColorManaAbility();
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
ability = new AnyColorManaAbility(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
this.addAbility(ability);
}

View file

@ -28,17 +28,14 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.*;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
@ -48,12 +45,6 @@ import mage.target.targetpointer.FixedTarget;
*/
public class DinosaurHunter extends CardImpl {
private static final FilterControlledCreaturePermanent filterAnotherDino = new FilterControlledCreaturePermanent();
static {
filterAnotherDino.add(new AnotherPredicate());
filterAnotherDino.add(new SubtypePredicate(SubType.DINOSAUR));
}
public DinosaurHunter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
@ -78,11 +69,6 @@ public class DinosaurHunter extends CardImpl {
class DinosaurHunterAbility extends TriggeredAbilityImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
static {
filter.add(new SubtypePredicate(SubType.DINOSAUR));
}
DinosaurHunterAbility() {
super(Zone.BATTLEFIELD, new DestroyTargetEffect());
}
@ -103,11 +89,13 @@ class DinosaurHunterAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent sourcePermanet = game.getPermanent(event.getSourceId());
Permanent targetPermanet = game.getPermanent(event.getTargetId());
if (sourcePermanet != null && targetPermanet != null && event.getSourceId().equals(sourceId) && filter.match(targetPermanet, game)) {
getEffects().get(0).setTargetPointer(new FixedTarget(event.getTargetId()));
return true;
if (((DamageEvent) event).isCombatDamage()
&& event.getSourceId().equals(getSourceId())) {
Permanent targetPermanet = game.getPermanentOrLKIBattlefield(event.getTargetId());
if (targetPermanet.hasSubtype(SubType.DINOSAUR, game)) {
getEffects().get(0).setTargetPointer(new FixedTarget(targetPermanet, game));
return true;
}
}
return false;
}
@ -116,4 +104,4 @@ class DinosaurHunterAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever {this} deals combat damage to a Dinosaur, destroy that creature.";
}
}
}

View file

@ -108,7 +108,8 @@ class DjinnIlluminatusGainReplicateEffect extends ContinuousEffectImpl {
if ((stackObject instanceof Spell)
&& !stackObject.isCopy()
&& stackObject.getControllerId().equals(source.getControllerId())
&& djinn.getControllerId().equals(source.getControllerId())) { // verify that the controller of the djinn cast that spell
&& djinn.getControllerId().equals(source.getControllerId()) // verify that the controller of the djinn cast that spell
&& !stackObject.getManaCost().isEmpty()) { //handle cases like Ancestral Vision
Spell spell = (Spell) stackObject;
if (filter.match(stackObject, game)) {
ReplicateAbility replicateAbility = replicateAbilities.computeIfAbsent(spell.getId(), k -> new ReplicateAbility(spell.getCard(), spell.getSpellAbility().getManaCosts().getText()));

View file

@ -0,0 +1,73 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
/**
*
* @author L_J
*/
public class DreadCharge extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Black creatures you control");
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("except by black creatures");
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
filter2.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK)));
filter.add(new ControllerPredicate(TargetController.YOU));
}
public DreadCharge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}");
// Black creatures you control can't be blocked this turn except by black creatures.
this.getSpellAbility().addEffect(new CantBeBlockedByCreaturesAllEffect(filter, filter2, Duration.EndOfTurn));
}
public DreadCharge(final DreadCharge card) {
super(card);
}
@Override
public DreadCharge copy() {
return new DreadCharge(this);
}
}

View file

@ -27,6 +27,7 @@
*/
package mage.cards.d;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
@ -52,7 +53,7 @@ public class DreamThief extends CardImpl {
private static final String rule = "draw a card if you've cast another blue spell this turn";
public DreamThief(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.FAERIE);
this.subtype.add(SubType.ROGUE);
@ -84,9 +85,12 @@ class CastBlueSpellThisTurnCondition implements Condition {
public boolean apply(Game game, Ability source) {
SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName());
if (watcher != null) {
for (Spell spell : watcher.getSpellsCastThisTurn(source.getControllerId())) {
if (!spell.getSourceId().equals(source.getSourceId()) && spell.getColor(game).isBlue()) {
return true;
List<Spell> spells = watcher.getSpellsCastThisTurn(source.getControllerId());
if (spells != null) {
for (Spell spell : spells) {
if (!spell.getSourceId().equals(source.getSourceId()) && spell.getColor(game).isBlue()) {
return true;
}
}
}
}

View file

@ -0,0 +1,145 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.common.TargetOpponent;
/**
*
* @author TheElk801 & L_J
*/
public class EunuchsIntrigues extends CardImpl {
public EunuchsIntrigues(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
// Target opponent chooses a creature he or she controls. Other creatures he or she controls can't block this turn.
this.getSpellAbility().addEffect(new EunuchsIntriguesEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
}
public EunuchsIntrigues(final EunuchsIntrigues card) {
super(card);
}
@Override
public EunuchsIntrigues copy() {
return new EunuchsIntrigues(this);
}
}
class EunuchsIntriguesEffect extends OneShotEffect {
EunuchsIntriguesEffect() {
super(Outcome.Benefit);
this.staticText = "Target opponent chooses a creature he or she controls. Other creatures he or she controls can't block this turn.";
}
EunuchsIntriguesEffect(final EunuchsIntriguesEffect effect) {
super(effect);
}
@Override
public EunuchsIntriguesEffect copy() {
return new EunuchsIntriguesEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getFirstTarget());
if (player == null) {
return false;
}
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control");
filter.add(new ControllerIdPredicate(player.getId()));
Target target = new TargetPermanent(1, 1, filter, true);
if (target.canChoose(source.getSourceId(), player.getId(), game)) {
while (!target.isChosen() && target.canChoose(player.getId(), game) && player.canRespond()) {
player.chooseTarget(Outcome.DestroyPermanent, target, source, game);
}
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null) {
game.informPlayers(player.getLogName() + " has chosen " + permanent.getLogName() + " as his only creature able to block this turn");
}
}
game.addEffect(new EunuchsIntriguesRestrictionEffect(target.getFirstTarget()), source);
return true;
}
}
class EunuchsIntriguesRestrictionEffect extends RestrictionEffect {
protected UUID targetId;
public EunuchsIntriguesRestrictionEffect(UUID targetId) {
super(Duration.EndOfTurn);
this.targetId = targetId;
}
public EunuchsIntriguesRestrictionEffect(final EunuchsIntriguesRestrictionEffect effect) {
super(effect);
targetId = effect.targetId;
}
@Override
public EunuchsIntriguesRestrictionEffect copy() {
return new EunuchsIntriguesRestrictionEffect(this);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
if (permanent.getControllerId().equals(source.getFirstTarget())) {
return true;
}
return false;
}
@Override
public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) {
if (targetId != null && blocker.getId().equals(targetId)) {
return true;
}
return false;
}
}

View file

@ -80,7 +80,7 @@ class ExaltedDragonCostToAttackBlockEffect extends PayCostToAttackBlockEffectImp
ExaltedDragonCostToAttackBlockEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.ATTACK,
new SacrificeTargetCost(new TargetControlledPermanent(new FilterControlledLandPermanent("a land"))));
staticText = "{this} can't attack unless you sacrifice a land <i>(This cost is paid as attackers are declared.)</i>";
staticText = "{this} can't attack unless you sacrifice a land. <i>(This cost is paid as attackers are declared.)</i>";
}
ExaltedDragonCostToAttackBlockEffect(ExaltedDragonCostToAttackBlockEffect effect) {

View file

@ -28,24 +28,22 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.target.TargetSource;
/**
*
* @author MarcoMarin
*
* @author L_J
*/
public class EyeForAnEye extends CardImpl {
@ -53,8 +51,7 @@ public class EyeForAnEye extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}{W}");
// The next time a source of your choice would deal damage to you this turn, instead that source deals that much damage to you and Eye for an Eye deals that much damage to that source's controller.
this.addAbility(new EyeForAnEyeTriggeredAbility(new EyeForAnEyeEffect()));
this.getSpellAbility().addEffect(new EyeForAnEyeEffect());
}
public EyeForAnEye(final EyeForAnEye card) {
@ -67,48 +64,19 @@ public class EyeForAnEye extends CardImpl {
}
}
class EyeForAnEyeTriggeredAbility extends TriggeredAbilityImpl {
class EyeForAnEyeEffect extends ReplacementEffectImpl {
public EyeForAnEyeTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect);
}
public EyeForAnEyeTriggeredAbility(final EyeForAnEyeTriggeredAbility ability) {
super(ability);
}
@Override
public EyeForAnEyeTriggeredAbility copy() {
return new EyeForAnEyeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
MageObject sourceObject = game.getObject(event.getSourceId());
this.getEffects().get(0).setValue("damageAmount", event.getAmount());
this.getEffects().get(0).setTargetPointer(new FixedTarget(game.getControllerId(sourceObject.getId())));
return true;
}
@Override
public String getRule() {
return "The next time a source of your choice would deal damage to you this turn, instead that source deals that much damage to you and {this} deals that much damage to that source's controller.";
}
}
class EyeForAnEyeEffect extends OneShotEffect {
private final TargetSource damageSource;
public EyeForAnEyeEffect() {
super(Outcome.Damage);
super(Duration.EndOfTurn, Outcome.RedirectDamage);
staticText = "The next time a source of your choice would deal damage to you this turn, instead that source deals that much damage to you and {this} deals that much damage to that source's controller";
this.damageSource = new TargetSource();
}
public EyeForAnEyeEffect(final EyeForAnEyeEffect effect) {
super(effect);
this.damageSource = effect.damageSource.copy();
}
@Override
@ -116,15 +84,48 @@ class EyeForAnEyeEffect extends OneShotEffect {
return new EyeForAnEyeEffect(this);
}
@Override
public void init(Ability source, Game game) {
this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
super.init(source, game);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
}
@Override
public boolean apply(Game game, Ability source) {
Integer damageAmount = (Integer) this.getValue("damageAmount");
UUID targetId = this.targetPointer.getFirst(game, source);
if (damageAmount != null && targetId != null) {
Player player = game.getPlayer(targetId);
if (player != null) {
player.damage(damageAmount, targetId, game, false, true);
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
DamageEvent damageEvent = (DamageEvent) event;
if (controller != null) {
controller.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects());
UUID sourceControllerId = game.getControllerId(damageEvent.getSourceId());
if (sourceControllerId != null) {
Player sourceController = game.getPlayer(sourceControllerId);
if (sourceController != null) {
sourceController.damage(damageEvent.getAmount(), source.getSourceId(), game, false, true);
return true;
}
}
}
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
DamageEvent damageEvent = (DamageEvent) event;
if (controller != null) {
if (controller.getId() == damageEvent.getTargetId() && damageEvent.getSourceId().equals(damageSource.getFirstTarget())) {
this.discard();
return true;
}
}
return false;

View file

@ -175,20 +175,41 @@ class FalseOrdersUnblockEffect extends OneShotEffect {
// Relevant ruling for Balduvian Warlord:
// 7/15/2006 If an attacking creature has an ability that triggers When this creature becomes blocked,
// it triggers when a creature blocks it due to the Warlords ability only if it was unblocked at that point.
boolean notYetBlocked = chosenGroup.getBlockers().isEmpty();
chosenGroup.addBlocker(permanent.getId(), controller.getId(), game);
chosenGroup.addBlockerToGroup(permanent.getId(), controller.getId(), game);
game.getCombat().addBlockingGroup(permanent.getId(), chosenPermanent.getId(), controller.getId(), game); // 702.21h
if (notYetBlocked) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, chosenPermanent.getId(), null));
for (UUID bandedId : chosenPermanent.getBandedCards()) {
CombatGroup bandedGroup = game.getCombat().findGroup(bandedId);
if (bandedGroup != null && chosenGroup.getBlockers().size() == 1) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, bandedId, null));
}
}
}
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, chosenPermanent.getId(), permanent.getId(), permanent.getControllerId()));
}
CombatGroup blockGroup = findBlockingGroup(permanent, game); // a new blockingGroup is formed, so it's necessary to find it again
if (blockGroup != null) {
blockGroup.pickAttackerOrder(permanent.getControllerId(), game);
}
}
}
}
}
return true;
}
}
return false;
}
private CombatGroup findBlockingGroup(Permanent blocker, Game game) {
if (game.getCombat().blockingGroupsContains(blocker.getId())) { // if (blocker.getBlocking() > 1) {
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
if (group.getBlockers().contains(blocker.getId())) {
return group;
}
}
}
return null;
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.NameACardEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
/**
*
* @author Quercitron & L_J
*/
public class Foreshadow extends CardImpl {
public Foreshadow(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
// Choose a card name, then target opponent puts the top card of his or her library into his or her graveyard. If that card has the chosen name, you draw a card.
this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.ALL));
this.getSpellAbility().addEffect(new ForeshadowEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
// Draw a card at the beginning of the next turn's upkeep.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1)), false));
}
public Foreshadow(final Foreshadow card) {
super(card);
}
@Override
public Foreshadow copy() {
return new Foreshadow(this);
}
}
class ForeshadowEffect extends OneShotEffect {
public ForeshadowEffect() {
super(Outcome.DrawCard);
this.staticText = ", then target opponent puts the top card of his or her library into his or her graveyard. If that card has the chosen name, you draw a card";
}
public ForeshadowEffect(final ForeshadowEffect effect) {
super(effect);
}
@Override
public ForeshadowEffect copy() {
return new ForeshadowEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) {
Card card = targetPlayer.getLibrary().getFromTop(game);
if (card != null) {
controller.moveCards(card, Zone.GRAVEYARD, source, game);
if (card.getName().equals(cardName)) {
controller.drawCards(1, game);
}
}
return true;
}
return false;
}
}

View file

@ -27,10 +27,13 @@
*/
package mage.cards.g;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.RegenerateTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -43,10 +46,6 @@ import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.BlockedAttackerWatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author LevelX2
@ -60,8 +59,7 @@ public class GazeOfTheGorgon extends CardImpl {
// Regenerate target creature. At end of combat, destroy all creatures that blocked or were blocked by that creature this turn.
this.getSpellAbility().addEffect(new RegenerateTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new AtTheEndOfCombatDelayedTriggeredAbility(new GazeOfTheGorgonEffect())));
this.getSpellAbility().addEffect(new GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect());
this.getSpellAbility().addWatcher(new BlockedAttackerWatcher());
}
@ -75,15 +73,46 @@ public class GazeOfTheGorgon extends CardImpl {
}
}
class GazeOfTheGorgonEffect extends OneShotEffect {
class GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect extends OneShotEffect {
public GazeOfTheGorgonEffect() {
public GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect() {
super(Outcome.Benefit);
this.staticText = "At this turn's next end of combat, destroy all creatures that blocked or were blocked by it this turn";
}
public GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect(final GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect effect) {
super(effect);
}
@Override
public GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect copy() {
return new GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (!source.getTargets().isEmpty() && source.getFirstTarget() != null) {
MageObjectReference mor = new MageObjectReference(source.getFirstTarget(), game);
AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new GazeOfTheGorgonEffect(mor));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
return false;
}
}
class GazeOfTheGorgonEffect extends OneShotEffect {
MageObjectReference targetCreature;
public GazeOfTheGorgonEffect(MageObjectReference targetCreature) {
super(Outcome.DestroyPermanent);
this.staticText = "destroy all creatures that blocked or were blocked by that creature this turn";
this.targetCreature = targetCreature;
}
public GazeOfTheGorgonEffect(final GazeOfTheGorgonEffect effect) {
super(effect);
targetCreature = effect.targetCreature;
}
@Override
@ -94,14 +123,13 @@ class GazeOfTheGorgonEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent targetCreature = game.getPermanentOrLKIBattlefield(source.getTargets().getFirstTarget());
if (controller != null && targetCreature != null) {
BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName());
if (watcher != null) {
List<Permanent> toDestroy = new ArrayList<>();
for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) {
if (!creature.getId().equals(targetCreature.getId())) {
if (watcher.creatureHasBlockedAttacker(creature, targetCreature, game) || watcher.creatureHasBlockedAttacker(targetCreature, creature, game)) {
if (!creature.getId().equals(targetCreature.getSourceId())) {
if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature, game) || watcher.creatureHasBlockedAttacker(targetCreature, new MageObjectReference(creature, game), game)) {
toDestroy.add(creature);
}
}

View file

@ -0,0 +1,153 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.g;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.BlockedAttackerWatcher;
/**
*
* @author LevelX2 & L_J
*/
public class GlyphOfDoom extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Wall creature");
static {
filter.add(new SubtypePredicate(SubType.WALL));
}
public GlyphOfDoom(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
// Choose target Wall creature. At this turn's next end of combat, destroy all creatures that were blocked by that creature this turn.
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
this.getSpellAbility().addEffect(new InfoEffect("Choose target Wall creature"));
this.getSpellAbility().addEffect(new GlyphOfDoomCreateDelayedTriggeredAbilityEffect());
this.getSpellAbility().addWatcher(new BlockedAttackerWatcher());
}
public GlyphOfDoom(final GlyphOfDoom card) {
super(card);
}
@Override
public GlyphOfDoom copy() {
return new GlyphOfDoom(this);
}
}
class GlyphOfDoomCreateDelayedTriggeredAbilityEffect extends OneShotEffect {
public GlyphOfDoomCreateDelayedTriggeredAbilityEffect() {
super(Outcome.Benefit);
this.staticText = "At this turn's next end of combat, destroy all creatures that were blocked by that creature this turn";
}
public GlyphOfDoomCreateDelayedTriggeredAbilityEffect(final GlyphOfDoomCreateDelayedTriggeredAbilityEffect effect) {
super(effect);
}
@Override
public GlyphOfDoomCreateDelayedTriggeredAbilityEffect copy() {
return new GlyphOfDoomCreateDelayedTriggeredAbilityEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (!source.getTargets().isEmpty() && source.getFirstTarget() != null) {
MageObjectReference mor = new MageObjectReference(source.getFirstTarget(), game);
AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new GlyphOfDoomEffect(mor));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
return false;
}
}
class GlyphOfDoomEffect extends OneShotEffect {
MageObjectReference targetCreature;
public GlyphOfDoomEffect(MageObjectReference targetCreature) {
super(Outcome.DestroyPermanent);
this.targetCreature = targetCreature;
}
public GlyphOfDoomEffect(final GlyphOfDoomEffect effect) {
super(effect);
targetCreature = effect.targetCreature;
}
@Override
public GlyphOfDoomEffect copy() {
return new GlyphOfDoomEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && targetCreature != null) {
BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName());
if (watcher != null) {
List<Permanent> toDestroy = new ArrayList<>();
for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) {
if (!creature.getId().equals(targetCreature.getSourceId())) {
if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature, game)) {
toDestroy.add(creature);
}
}
}
for (Permanent creature : toDestroy) {
creature.destroy(source.getSourceId(), game, false);
}
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,145 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.g;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.common.TargetOpponent;
/**
*
* @author TheElk801 & L_J
*/
public class GoblinWarCry extends CardImpl {
public GoblinWarCry(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
// Target opponent chooses a creature he or she controls. Other creatures he or she controls can't block this turn.
this.getSpellAbility().addEffect(new GoblinWarCryEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
}
public GoblinWarCry(final GoblinWarCry card) {
super(card);
}
@Override
public GoblinWarCry copy() {
return new GoblinWarCry(this);
}
}
class GoblinWarCryEffect extends OneShotEffect {
GoblinWarCryEffect() {
super(Outcome.Benefit);
this.staticText = "Target opponent chooses a creature he or she controls. Other creatures he or she controls can't block this turn.";
}
GoblinWarCryEffect(final GoblinWarCryEffect effect) {
super(effect);
}
@Override
public GoblinWarCryEffect copy() {
return new GoblinWarCryEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getFirstTarget());
if (player == null) {
return false;
}
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control");
filter.add(new ControllerIdPredicate(player.getId()));
Target target = new TargetPermanent(1, 1, filter, true);
if (target.canChoose(source.getSourceId(), player.getId(), game)) {
while (!target.isChosen() && target.canChoose(player.getId(), game) && player.canRespond()) {
player.chooseTarget(Outcome.DestroyPermanent, target, source, game);
}
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null) {
game.informPlayers(player.getLogName() + " has chosen " + permanent.getLogName() + " as his only creature able to block this turn");
}
}
game.addEffect(new GoblinWarCryRestrictionEffect(target.getFirstTarget()), source);
return true;
}
}
class GoblinWarCryRestrictionEffect extends RestrictionEffect {
protected UUID targetId;
public GoblinWarCryRestrictionEffect(UUID targetId) {
super(Duration.EndOfTurn);
this.targetId = targetId;
}
public GoblinWarCryRestrictionEffect(final GoblinWarCryRestrictionEffect effect) {
super(effect);
targetId = effect.targetId;
}
@Override
public GoblinWarCryRestrictionEffect copy() {
return new GoblinWarCryRestrictionEffect(this);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
if (permanent.getControllerId().equals(source.getFirstTarget())) {
return true;
}
return false;
}
@Override
public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) {
if (targetId != null && blocker.getId().equals(targetId)) {
return true;
}
return false;
}
}

View file

@ -0,0 +1,170 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.h;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AttackingPredicate;
import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author LevelX2 & L_J
*/
public class HarshJustice extends CardImpl {
public HarshJustice(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
// Cast Harsh Justice only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// This turn, whenever an attacking creature deals combat damage to you, it deals that much damage to its controller.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new HarshJusticeTriggeredAbility()));
}
public HarshJustice(final HarshJustice card) {
super(card);
}
@Override
public HarshJustice copy() {
return new HarshJustice(this);
}
}
class HarshJusticeTriggeredAbility extends DelayedTriggeredAbility {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature");
static {
filter.add(new AttackingPredicate());
}
public HarshJusticeTriggeredAbility() {
super(new HarshJusticeEffect(), Duration.EndOfTurn, false);
}
public HarshJusticeTriggeredAbility(final HarshJusticeTriggeredAbility ability) {
super(ability);
}
@Override
public HarshJusticeTriggeredAbility copy() {
return new HarshJusticeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Player controller = game.getPlayer(this.getControllerId());
DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event;
Permanent damagePermanent = game.getPermanentOrLKIBattlefield(damageEvent.getSourceId());
if (controller != null && damagePermanent != null) {
if (damageEvent.isCombatDamage() && controller.getId().equals(damageEvent.getTargetId()) && filter.match(damagePermanent, game)) {
for (Effect effect : this.getEffects()) {
effect.setValue("damage", damageEvent.getAmount());
effect.setValue("sourceId", damageEvent.getSourceId());
}
return true;
}
}
return false;
}
@Override
public String getRule() {
return "This turn, whenever an attacking creature deals combat damage to you, " + super.getRule();
}
}
class HarshJusticeEffect extends OneShotEffect {
public HarshJusticeEffect() {
super(Outcome.Benefit);
this.staticText = "it deals that much damage to its controller";
}
public HarshJusticeEffect(final HarshJusticeEffect effect) {
super(effect);
}
@Override
public HarshJusticeEffect copy() {
return new HarshJusticeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int damage = (Integer) this.getValue("damage");
UUID sourceId = (UUID) this.getValue("sourceId");
MageObject sourceObject = game.getObject(source.getSourceId());
if (sourceObject != null && damage > 0 && sourceId != null) {
Permanent targetObject = game.getPermanentOrLKIBattlefield(sourceId);
if (targetObject != null) {
Player controller = game.getPlayer(targetObject.getControllerId());
if (controller != null) {
game.informPlayers(sourceObject.getLogName() + ": " + targetObject.getLogName() + " deals " + damage + " damage to " + controller.getLogName());
controller.damage(damage, sourceId, game, false, true);
return true;
}
}
}
return false;
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.h;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.PreventionEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.filter.common.FilterAttackingCreature;
import mage.game.Game;
import mage.game.events.DamagePlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author L_J
*/
public class HeavyFog extends CardImpl {
public HeavyFog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}");
// Cast Deep Wood only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// Prevent all damage that would be dealt to you this turn by attacking creatures.
this.getSpellAbility().addEffect(new HeavyFogEffect());
}
public HeavyFog(final HeavyFog card) {
super(card);
}
@Override
public HeavyFog copy() {
return new HeavyFog(this);
}
}
class HeavyFogEffect extends PreventionEffectImpl {
private static final FilterAttackingCreature filter = new FilterAttackingCreature();
HeavyFogEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
staticText = "Prevent all damage that would be dealt to you this turn by attacking creatures";
}
HeavyFogEffect(final HeavyFogEffect effect) {
super(effect);
}
@Override
public HeavyFogEffect copy() {
return new HeavyFogEffect(this);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (super.applies(event, source, game) && event instanceof DamagePlayerEvent && event.getAmount() > 0) {
DamagePlayerEvent damageEvent = (DamagePlayerEvent) event;
if (event.getTargetId().equals(source.getControllerId())) {
Permanent permanent = game.getPermanentOrLKIBattlefield(damageEvent.getSourceId());
if (permanent != null && filter.match(permanent, game)) {
return true;
}
}
}
return false;
}
}

View file

@ -27,35 +27,34 @@
*/
package mage.cards.h;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterNonlandCard;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInExile;
import mage.target.targetpointer.FixedTarget;
import mage.target.TargetCard;
/**
*
* @author jeffwadsworth
* @author jeffwadsworth & L_J
*/
public class HellcarverDemon extends CardImpl {
@ -84,9 +83,6 @@ public class HellcarverDemon extends CardImpl {
class HellcarverDemonEffect extends OneShotEffect {
private static final FilterControlledPermanent filterPermanents = new FilterControlledPermanent("Permanent");
private static FilterNonlandCard filter = new FilterNonlandCard("nonland card exiled with Hellcarver Demon");
public HellcarverDemonEffect() {
super(Outcome.PlayForFree);
staticText = "sacrifice all other permanents you control and discard your hand. Exile the top six cards of your library. You may cast any number of nonland cards exiled this way without paying their mana costs.";
@ -99,41 +95,43 @@ class HellcarverDemonEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent hellcarverDemon = game.getPermanent(source.getSourceId());
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanents, source.getControllerId(), game)) {
if (!Objects.equals(permanent, hellcarverDemon)) {
permanent.sacrifice(source.getSourceId(), game);
}
}
if (controller != null && !controller.getHand().isEmpty()) {
int cardsInHand = controller.getHand().size();
controller.discard(cardsInHand, false, source, game);
}
for (int i = 0; i < 6; i++) {
if (controller != null
&& controller.getLibrary().hasCards()) {
Card topCard = controller.getLibrary().getFromTop(game);
topCard.moveToExile(source.getSourceId(), "Cards exiled by Hellcarver Demon", source.getSourceId(), game);
}
}
while (controller != null
&& controller.canRespond()
&& controller.chooseUse(Outcome.PlayForFree, controller.getLogName() + " can cast another nonland card exiled with Hellcarver Demon without paying that card's mana cost.", source, game)) {
TargetCardInExile target = new TargetCardInExile(filter, source.getSourceId());
while (controller.chooseUse(Outcome.PlayForFree, "Cast another spell exiled by Hellcarver Demon?", source, game)) {
controller.choose(Outcome.PlayForFree, game.getExile().getExileZone(source.getSourceId()), target, game);
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
ContinuousEffect effect = new HellcarverDemonCastFromExileEffect();
effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source);
controller.cast(card.getSpellAbility(), game, true);
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (controller != null && sourceObject != null) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
if (!Objects.equals(permanent, sourceObject)) {
permanent.sacrifice(source.getSourceId(), game);
}
}
if (!controller.getHand().isEmpty()) {
int cardsInHand = controller.getHand().size();
controller.discard(cardsInHand, false, source, game);
}
// move cards from library to exile
Set<Card> currentExiledCards = new HashSet<>();
currentExiledCards.addAll(controller.getLibrary().getTopCards(game, 6));
controller.moveCardsToExile(currentExiledCards, source, game, true, source.getSourceId(), sourceObject.getIdName());
// cast the possible cards without paying the mana
Cards cardsToCast = new CardsImpl();
cardsToCast.addAll(currentExiledCards);
boolean alreadyCast = false;
while (!cardsToCast.isEmpty()
&& controller.canRespond()) {
if (!controller.chooseUse(outcome, "Cast a" + (alreadyCast ? "nother" : "" ) + " card exiled with " + sourceObject.getLogName() + " without paying its mana cost?", source, game)) {
break;
}
TargetCard targetCard = new TargetCard(1, Zone.EXILED, new FilterCard("nonland card to cast for free"));
if (controller.choose(Outcome.PlayForFree, cardsToCast, targetCard, game)) {
alreadyCast = true;
Card card = game.getCard(targetCard.getFirstTarget());
if (card != null) {
if (controller.cast(card.getSpellAbility(), game, true)) {
cardsToCast.remove(card);
} else {
game.informPlayer(controller, "You're not able to cast " + card.getIdName() + " or you canceled the casting.");
}
}
}
target.clearChosen();
}
return true;
}
@ -145,33 +143,3 @@ class HellcarverDemonEffect extends OneShotEffect {
return new HellcarverDemonEffect(this);
}
}
class HellcarverDemonCastFromExileEffect extends AsThoughEffectImpl {
public HellcarverDemonCastFromExileEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
staticText = "You may play the card from exile without paying its mana cost";
}
public HellcarverDemonCastFromExileEffect(final HellcarverDemonCastFromExileEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public HellcarverDemonCastFromExileEffect copy() {
return new HellcarverDemonCastFromExileEffect(this);
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
if (targetPointer.getTargets(game, source).contains(sourceId)) {
return game.getState().getZone(sourceId) == Zone.EXILED;
}
return false;
}
}

View file

@ -48,7 +48,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
*/
public class HeraldOfThePantheon extends CardImpl {
private static final FilterCard filter = new FilterCard("enchantment spells");
private static final FilterCard filter = new FilterCard("Enchantment spells");
private static final FilterSpell filter2 = new FilterSpell("an enchantment spell");
static {

View file

@ -0,0 +1,108 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.h;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.common.TargetCreatureOrPlayer;
/**
*
* @author L_J
*/
public class HonorablePassage extends CardImpl {
public HonorablePassage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}");
// The next time a source of your choice would deal damage to target creature or player this turn, prevent that damage. If damage from a red source is prevented this way, Honorable Passage deals that much damage to the source's controller.
this.getSpellAbility().addEffect(new HonorablePassageEffect());
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
}
public HonorablePassage(final HonorablePassage card) {
super(card);
}
@Override
public HonorablePassage copy() {
return new HonorablePassage(this);
}
}
class HonorablePassageEffect extends PreventNextDamageFromChosenSourceToTargetEffect {
public HonorablePassageEffect() {
super(Duration.EndOfTurn);
}
public HonorablePassageEffect(final HonorablePassageEffect effect) {
super(effect);
}
@Override
public HonorablePassageEffect copy() {
return new HonorablePassageEffect(this);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
int damage = event.getAmount();
PreventionEffectData preventEffectData = preventDamageAction(event, source, game);
if (preventEffectData.getPreventedDamage() > 0) {
MageObject sourceObject = game.getObject(event.getSourceId());
if (sourceObject != null && sourceObject.getColor(game).isRed()) {
UUID sourceControllerId = game.getControllerId(event.getSourceId());
if (sourceControllerId != null) {
Player sourceController = game.getPlayer(sourceControllerId);
if (sourceController != null) {
sourceController.damage(damage, source.getSourceId(), game, false, true);
}
}
}
this.used = true;
}
return false;
}
@Override
public String getText(Mode mode) {
return "The next time a source of your choice would deal damage to target creature or player this turn, prevent that damage. If damage from a red source is prevented this way, {this} deals that much damage to the source's controller";
}
}

View file

@ -41,10 +41,10 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.ManaType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
@ -118,8 +118,8 @@ class HostageTakerExileEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent card = game.getPermanent(targetPointer.getFirst(game, source));
Permanent permanent = game.getPermanent(source.getSourceId());
Permanent card = game.getPermanent(getTargetPointer().getFirst(game, source));
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (permanent != null && card != null) {
Player controller = game.getPlayer(card.getControllerId());
if (controller != null) {

View file

@ -31,6 +31,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.keyword.FlashAbility;
@ -39,9 +40,9 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
@ -55,7 +56,7 @@ import mage.game.permanent.Permanent;
public class HushwingGryff extends CardImpl {
public HushwingGryff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HIPPOGRIFF);
this.power = new MageInt(2);
@ -92,10 +93,15 @@ class HushwingGryffEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(event.getSourceId());
MageObject enteringObject = game.getObject(event.getSourceId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (mageObject != null && sourceObject != null) {
return sourceObject.getLogName() + " prevented ability of " + mageObject.getLogName() + " to trigger";
Ability ability = (Ability) getValue("targetAbility");
if (enteringObject != null && sourceObject != null && ability != null) {
MageObject abilitObject = game.getObject(ability.getSourceId());
if (abilitObject != null) {
return sourceObject.getLogName() + " prevented ability of " + abilitObject.getLogName()
+ " to trigger for " + enteringObject.getLogName() + " entering the battlefield.";
}
}
return null;
}
@ -111,7 +117,7 @@ class HushwingGryffEffect extends ContinuousRuleModifyingEffectImpl {
if (ability != null && ability.getAbilityType() == AbilityType.TRIGGERED) {
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
if (permanent != null && permanent.isCreature()) {
return true;
return (((TriggeredAbility) ability).checkTrigger(event, game));
}
}
return false;

View file

@ -28,6 +28,7 @@
package mage.cards.i;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect;
@ -88,7 +89,7 @@ class InterdictPredicate implements Predicate<Ability> {
@Override
public boolean apply(Ability input, Game game) {
if (input instanceof StackAbility && input.getAbilityType() == AbilityType.ACTIVATED) {
Permanent sourceObject = game.getPermanentOrLKIBattlefield(input.getSourceId());
MageObject sourceObject = input.getSourceObject(game);
if (sourceObject != null) {
return (sourceObject.isArtifact()
|| sourceObject.isEnchantment()
@ -120,9 +121,12 @@ class InterdictCounterEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget());
if (stackObject != null && game.getStack().counter(source.getFirstTarget(), source.getSourceId(), game)) {
InterdictCantActivateEffect effect = new InterdictCantActivateEffect();
effect.setTargetPointer(new FixedTarget(stackObject.getSourceId()));
game.getContinuousEffects().addEffect(effect, source);
Permanent sourcePermanent = stackObject.getStackAbility().getSourcePermanentIfItStillExists(game);
if (sourcePermanent != null) {
InterdictCantActivateEffect effect = new InterdictCantActivateEffect();
effect.setTargetPointer(new FixedTarget(sourcePermanent, game));
game.getContinuousEffects().addEffect(effect, source);
}
return true;
}
return false;
@ -143,7 +147,7 @@ class InterdictCantActivateEffect extends RestrictionEffect {
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return getTargetPointer().getFirst(game, source).equals(permanent.getId());
return permanent.getId().equals(getTargetPointer().getFirst(game, source));
}
@Override

View file

@ -48,7 +48,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
public class JacesSanctum extends CardImpl {
private static final FilterCard filter = new FilterCard("instant and sorcery spells");
private static final FilterCard filter = new FilterCard("Instant and sorcery spells");
private static final FilterSpell filter2 = new FilterSpell("an instant or sorcery spell");

View file

@ -0,0 +1,73 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.j;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.target.common.TargetAttackingCreature;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author TheElk801
*/
public class JustFate extends CardImpl {
public JustFate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
// Cast Just Fate only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// Destroy target attacking creature.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetAttackingCreature());
}
public JustFate(final JustFate card) {
super(card);
}
@Override
public JustFate copy() {
return new JustFate(this);
}
}

View file

@ -12,25 +12,24 @@ import mage.filter.common.FilterControlledPermanent;
public class KaerveksSpite extends CardImpl {
private FilterControlledPermanent permanentsYouControl = new FilterControlledPermanent("all permanents you control");
public KaerveksSpite(UUID ownerId, CardSetInfo cardSetInfo) {
super(ownerId, cardSetInfo, new CardType[]{CardType.INSTANT}, "{B}{B}{B}");
//As an additional cost to cast Kaervek's Spite, sacrifice all permanents you control and discard your hand.
this.getSpellAbility().addCost(new SacrificeAllCost(permanentsYouControl));
// As an additional cost to cast Kaervek's Spite, sacrifice all permanents you control and discard your hand.
this.getSpellAbility().addCost(new SacrificeAllCost(new FilterControlledPermanent("permanents you control")));
this.getSpellAbility().addCost(new DiscardHandCost());
//Target player loses 5 life.
// Target player loses 5 life.
Effect effect = new LoseLifeTargetEffect(5);
this.getSpellAbility().addEffect(effect);
}
public KaerveksSpite(final KaerveksSpite other){
public KaerveksSpite(final KaerveksSpite other) {
super(other);
}
public KaerveksSpite copy(){
@Override
public KaerveksSpite copy() {
return new KaerveksSpite(this);
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.RedirectDamageFromSourceToTargetEffect;
import mage.abilities.keyword.MorphAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public class KaronasZealot extends CardImpl {
public KaronasZealot(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.CLERIC);
this.power = new MageInt(2);
this.toughness = new MageInt(5);
// Morph {3}{W}{W}
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{3}{W}{W}")));
// When Karona's Zealot is turned face up, all damage that would be dealt to it this turn is dealt to target creature instead.
Ability ability = new TurnedFaceUpSourceTriggeredAbility(new RedirectDamageFromSourceToTargetEffect(Duration.EndOfTurn, Integer.MAX_VALUE, false)
.setText("all damage that would be dealt to it this turn is dealt to target creature instead"));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public KaronasZealot(final KaronasZealot card) {
super(card);
}
@Override
public KaronasZealot copy() {
return new KaronasZealot(this);
}
}

View file

@ -0,0 +1,80 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.condition.CompoundCondition;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.condition.common.IsStepCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.common.FilterAttackingCreature;
import mage.target.TargetPermanent;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author L_J
*/
public class KongmingsContraptions extends CardImpl {
public KongmingsContraptions(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(2);
this.toughness = new MageInt(4);
// {T}: Kongming's Contraptions deals 2 damage to target attacking creature. Activate this ability only during the declare attackers step and only if you've been attacked this step.
Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new TapSourceCost(),
new CompoundCondition("during the declare attackers step and only if you've been attacked this step",
new IsStepCondition(PhaseStep.DECLARE_ATTACKERS, false), AttackedThisStepCondition.instance)
);
ability.addTarget(new TargetPermanent(new FilterAttackingCreature()));
this.addAbility(ability, new PlayerAttackedStepWatcher());
}
public KongmingsContraptions(final KongmingsContraptions card) {
super(card);
}
@Override
public KongmingsContraptions copy() {
return new KongmingsContraptions(this);
}
}

View file

@ -30,6 +30,7 @@ package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -61,7 +62,9 @@ public class KrosanDrover extends CardImpl {
this.toughness = new MageInt(2);
// Creature spells you cast with converted mana cost 6 or greater cost {2} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 2)));
Effect effect = new SpellsCostReductionControllerEffect(filter, 2);
effect.setText("Creature spells you cast with converted mana cost 6 or greater cost {2} less to cast.");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public KrosanDrover(final KrosanDrover card) {

View file

@ -35,7 +35,6 @@ import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.AdjustingSourceCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeTargetEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.effects.common.RegenerateSourceEffect;
@ -58,7 +57,7 @@ import mage.util.CardUtil;
public class LaquatussChampion extends CardImpl {
public LaquatussChampion(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}");
this.subtype.add(SubType.NIGHTMARE);
this.subtype.add(SubType.HORROR);
@ -126,9 +125,7 @@ class LaquatussChampionLeavesBattlefieldTriggeredAbility extends LeavesBattlefie
String key = CardUtil.getCardZoneString("targetPlayer", this.getSourceId(), game, true);
Object object = game.getState().getValue(key);
if (object instanceof UUID) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget((UUID) object));
}
this.getEffects().setTargetPointer(new FixedTarget((UUID) object));
return true;
}
}

View file

@ -118,7 +118,7 @@ class LeviathanCostToAttackBlockEffect extends PayCostToAttackBlockEffectImpl {
LeviathanCostToAttackBlockEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.ATTACK,
new SacrificeTargetCost(new TargetControlledPermanent(2, 2, filter, false)));
staticText = "{this} can't attack unless you sacrifice two Islands <i>(This cost is paid as attackers are declared.)</i>";
staticText = "{this} can't attack unless you sacrifice two Islands. <i>(This cost is paid as attackers are declared.)</i>";
}
LeviathanCostToAttackBlockEffect(LeviathanCostToAttackBlockEffect effect) {

View file

@ -47,7 +47,7 @@ import mage.target.common.TargetCreaturePermanent;
public class LyevDecree extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures your opponent controls");
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures your opponents control");
static {
filter.add(new ControllerPredicate(TargetController.OPPONENT));
}
@ -56,7 +56,7 @@ public class LyevDecree extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{W}");
// Detain up to two target creatures your opponent controls.
// Detain up to two target creatures your opponents control.
this.getSpellAbility().addEffect(new DetainTargetEffect());
Target target = new TargetCreaturePermanent(0,2,filter,false);
this.getSpellAbility().addTarget(target);

View file

@ -44,7 +44,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
*/
public class ManaMatrix extends CardImpl {
private static final FilterCard filter = new FilterCard("instant and enchantment spells");
private static final FilterCard filter = new FilterCard("Instant and enchantment spells");
static {
filter.add(Predicates.or(

View file

@ -0,0 +1,112 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.permanent.Permanent;
/**
*
* @author jeffwadsworth
*/
public class MercadiasDownfall extends CardImpl {
private static String rule = "Each attacking creature gets +1/+0 until end of turn for each nonbasic land defending player controls";
public MercadiasDownfall(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
// Each attacking creature gets +1/+0 until end of turn for each nonbasic land defending player controls.
this.getSpellAbility().addEffect(new BoostAllEffect(new DefendersNonBasicLandCount(), new StaticValue(0), Duration.EndOfTurn, new FilterAttackingCreature(), true, rule));
}
public MercadiasDownfall(final MercadiasDownfall card) {
super(card);
}
@Override
public MercadiasDownfall copy() {
return new MercadiasDownfall(this);
}
class DefendersNonBasicLandCount implements DynamicValue {
UUID defenderId;
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
for (CombatGroup group : game.getCombat().getGroups()) {
defenderId = group.getDefenderId();
if (group.isDefenderIsPlaneswalker()) {
Permanent permanent = game.getPermanent(defenderId);
if (permanent != null) {
defenderId = permanent.getControllerId();
}
}
FilterLandPermanent filter = new FilterLandPermanent("nonbasic land");
filter.add(Predicates.not(new SupertypePredicate(SuperType.BASIC)));
System.out.println("The number of nonbasic lands is " + game.getBattlefield().countAll(filter, defenderId, game));
return game.getBattlefield().countAll(filter, defenderId, game);
}
return 0;
}
@Override
public DynamicValue copy() {
return new DefendersNonBasicLandCount();
}
@Override
public String toString() {
return "X";
}
@Override
public String getMessage() {
return "the number of nonbasic lands defending player controls";
}
}
}

View file

@ -50,10 +50,10 @@ public class MerfolkRaiders extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Phasing
this.addAbility(PhasingAbility.getInstance());
// Islandwalk
this.addAbility(new IslandwalkAbility());
// Phasing
this.addAbility(PhasingAbility.getInstance());
}
public MerfolkRaiders(final MerfolkRaiders card) {

View file

@ -49,7 +49,7 @@ import mage.filter.predicate.mageobject.SubtypePredicate;
*/
public class MilitantInquisitor extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("equipment you control");
private static final FilterControlledPermanent filter = new FilterControlledPermanent("Equipment you control");
static {
filter.add(new CardTypePredicate(CardType.ARTIFACT));

View file

@ -38,8 +38,8 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -122,7 +122,7 @@ class MimicVatTriggeredAbility extends TriggeredAbilityImpl {
&& !(permanent instanceof PermanentToken)
&& permanent.isCreature()) {
getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId()));
getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId(), game));
return true;
}
return false;
@ -152,22 +152,22 @@ class MimicVatEffect extends OneShotEffect {
if (controller == null || permanent == null) {
return false;
}
// return older cards to graveyard
Set<Card> toGraveyard = new HashSet<>();
for (UUID imprintedId : permanent.getImprinted()) {
Card card = game.getCard(imprintedId);
if (card != null) {
toGraveyard.add(card);
}
}
controller.moveCards(toGraveyard, Zone.GRAVEYARD, source, game);
permanent.clearImprinted(game);
// Imprint a new one
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (card != null) {
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), permanent.getName() + " (Imprint)");
permanent.imprint(card.getId(), game);
Card newCard = game.getCard(getTargetPointer().getFirst(game, source));
if (newCard != null) {
// return older cards to graveyard
Set<Card> toGraveyard = new HashSet<>();
for (UUID imprintedId : permanent.getImprinted()) {
Card card = game.getCard(imprintedId);
if (card != null) {
toGraveyard.add(card);
}
}
controller.moveCards(toGraveyard, Zone.GRAVEYARD, source, game);
permanent.clearImprinted(game);
controller.moveCardsToExile(newCard, source, game, true, source.getSourceId(), permanent.getName() + " (Imprint)");
permanent.imprint(newCard.getId(), game);
}
return true;

View file

@ -0,0 +1,113 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author L_J
*/
public class MinionOfTheWastes extends CardImpl {
public MinionOfTheWastes(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}{B}");
this.subtype.add(SubType.MINION);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// Trample
this.addAbility(TrampleAbility.getInstance());
// As Minion of the Wastes enters the battlefield, pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards.
this.addAbility(new AsEntersBattlefieldAbility(new MinionOfTheWastesEffect()));
// Minion of the Wastes's power and toughness are each equal to the life paid as it entered the battlefield.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield")));
}
public MinionOfTheWastes(final MinionOfTheWastes card) {
super(card);
}
@Override
public MinionOfTheWastes copy() {
return new MinionOfTheWastes(this);
}
}
class MinionOfTheWastesEffect extends OneShotEffect {
public MinionOfTheWastesEffect() {
super(Outcome.LoseLife);
staticText = "pay any amount of life";
}
public MinionOfTheWastesEffect(final MinionOfTheWastesEffect effect) {
super(effect);
}
@Override
public MinionOfTheWastesEffect copy() {
return new MinionOfTheWastesEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card sourceCard = game.getCard(source.getSourceId());
int payAmount = controller.getAmount(0, controller.getLife(), "Pay any amount of life", game);
controller.loseLife(payAmount, game, false);
game.informPlayers(new StringBuilder(sourceCard.getLogName()).append(": ").append(controller.getLogName())
.append(" pays ").append(payAmount).append(" life").toString());
game.addEffect(new SetPowerToughnessSourceEffect(payAmount, payAmount, Duration.Custom, SubLayer.SetPT_7b), source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,137 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
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.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BecomesChosenCreatureTypeSourceEffect;
import mage.abilities.effects.common.continuous.BecomesCreatureTypeTargetEffect;
import mage.constants.SubType;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceCreatureType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class MistformWakecaster extends CardImpl {
public MistformWakecaster(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}");
this.subtype.add(SubType.ILLUSION);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// {1}: Mistform Wakecaster becomes the creature type of your choice until end of turn.
this.addAbility(new SimpleActivatedAbility(new BecomesChosenCreatureTypeSourceEffect(), new ManaCostsImpl("{1}")));
// {2}{U}{U}, {T}: Choose a creature type. Each creature you control becomes that type until end of turn.
Ability ability = new SimpleActivatedAbility(new BecomesChosenCreatureTypeControlledEffect(), new ManaCostsImpl("{2}{U}{U}"));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
public MistformWakecaster(final MistformWakecaster card) {
super(card);
}
@Override
public MistformWakecaster copy() {
return new MistformWakecaster(this);
}
}
class BecomesChosenCreatureTypeControlledEffect extends OneShotEffect {
public BecomesChosenCreatureTypeControlledEffect() {
super(Outcome.BoostCreature);
staticText = "Choose a creature type. Each creature you control becomes that type until end of turn";
}
public BecomesChosenCreatureTypeControlledEffect(final BecomesChosenCreatureTypeControlledEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Card card = game.getCard(source.getSourceId());
String chosenType = "";
if (player != null && card != null) {
Choice typeChoice = new ChoiceCreatureType();
String msg = "Choose a creature type";
typeChoice.setMessage(msg);
while (!player.choose(Outcome.BoostCreature, typeChoice, game)) {
if (!player.canRespond()) {
return false;
}
}
game.informPlayers(card.getName() + ": " + player.getLogName() + " has chosen " + typeChoice.getChoice());
chosenType = typeChoice.getChoice();
if (chosenType != null && !chosenType.isEmpty()) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game)) {
ContinuousEffect effect = new BecomesCreatureTypeTargetEffect(Duration.EndOfTurn, SubType.byDescription(chosenType));
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
}
return true;
}
}
return false;
}
@Override
public Effect copy() {
return new BecomesChosenCreatureTypeControlledEffect(this);
}
}

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.m;
import java.io.Serializable;
@ -50,9 +49,11 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.MyrToken;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.watchers.common.CreatureAttackedWhichPlayerWatcher;
/**
*
@ -61,7 +62,7 @@ import mage.target.TargetPermanent;
public class MyrBattlesphere extends CardImpl {
public MyrBattlesphere(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{7}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}");
this.subtype.add(SubType.MYR);
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(4);
@ -71,7 +72,8 @@ public class MyrBattlesphere extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new MyrToken(), 4), false));
// Whenever Myr Battlesphere attacks, you may tap X untapped Myr you control. If you do, Myr Battlesphere gets +X/+0 until end of turn and deals X damage to defending player.
this.addAbility(new AttacksTriggeredAbility(new MyrBattlesphereEffect(), true));
this.addAbility(new AttacksTriggeredAbility(new MyrBattlesphereEffect(), true), new CreatureAttackedWhichPlayerWatcher());
}
public MyrBattlesphere(final MyrBattlesphere card) {
@ -107,42 +109,46 @@ class MyrBattlesphereEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int tappedAmount = 0;
TargetPermanent target = new TargetPermanent(0,1,filter, false);
while (true && controller.canRespond()) {
target.clearChosen();
if (target.canChoose(source.getControllerId(), game)) {
Map<String, Serializable> options = new HashMap<>();
options.put("UI.right.btn.text", "Myr tapping complete");
controller.choose(outcome, target, source.getControllerId(), game, options);
if (!target.getTargets().isEmpty()) {
UUID creature = target.getFirstTarget();
if (creature != null) {
game.getPermanent(creature).tap(game);
tappedAmount++;
CreatureAttackedWhichPlayerWatcher watcher = (CreatureAttackedWhichPlayerWatcher) game.getState().getWatchers().get(CreatureAttackedWhichPlayerWatcher.class.getSimpleName());
if (watcher != null) {
// even if the Myr Battlesphere is off the battlefield, it still does damage to the defender
Permanent myr = game.getPermanentOrLKIBattlefield(source.getSourceId());
UUID defenderId = watcher.getPlayerAttackedThisTurnByCreature(myr.getId());
Player defender = game.getPlayer(defenderId);
int tappedAmount = 0;
TargetPermanent target = new TargetPermanent(0, 1, filter, false);
while (true && controller.canRespond()) {
target.clearChosen();
if (target.canChoose(source.getControllerId(), game)) {
Map<String, Serializable> options = new HashMap<>();
options.put("UI.right.btn.text", "Myr tapping complete");
controller.choose(outcome, target, source.getControllerId(), game, options);
if (!target.getTargets().isEmpty()) {
UUID creature = target.getFirstTarget();
if (creature != null) {
game.getPermanent(creature).tap(game);
tappedAmount++;
}
} else {
break;
}
} else {
break;
}
}
else {
break;
}
}
if (tappedAmount > 0) {
game.informPlayers(new StringBuilder(controller.getLogName()).append(" taps ").append(tappedAmount).append(" Myrs").toString());
// boost effect
game.addEffect(new BoostSourceEffect(tappedAmount, 0, Duration.EndOfTurn), source);
// damage to defender
UUID defenderId = game.getCombat().getDefendingPlayerId(source.getSourceId(), game);
Player defender = game.getPlayer(defenderId);
if (defender != null) {
defender.damage(tappedAmount, source.getSourceId(), game, false, true);
return true;
}
if (tappedAmount > 0) {
game.informPlayers(new StringBuilder(controller.getLogName()).append(" taps ").append(tappedAmount).append(" Myrs").toString());
// boost effect
game.addEffect(new BoostSourceEffect(tappedAmount, 0, Duration.EndOfTurn), source);
// damage to defender
if (defender != null) {
defender.damage(tappedAmount, myr.getId(), game, false, true);
return true;
}
}
return true;
}
return true;
}
return false;
}

View file

@ -0,0 +1,136 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.other.OwnerPredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author L_J
*/
public class NamelessRace extends CardImpl {
public NamelessRace(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// Trample
this.addAbility(TrampleAbility.getInstance());
// As Nameless Race enters the battlefield, pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards.
this.addAbility(new AsEntersBattlefieldAbility(new NamelessRaceEffect()));
// Nameless Race's power and toughness are each equal to the life paid as it entered the battlefield.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield")));
}
public NamelessRace(final NamelessRace card) {
super(card);
}
@Override
public NamelessRace copy() {
return new NamelessRace(this);
}
}
class NamelessRaceEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent("white nontoken permanents your opponents control");
private static final FilterCard filter2 = new FilterCard("white cards in their graveyards");
static {
filter.add(new ColorPredicate(ObjectColor.WHITE));
filter.add(Predicates.not(new TokenPredicate()));
filter.add(new ControllerPredicate(TargetController.OPPONENT));
filter2.add(new ColorPredicate(ObjectColor.WHITE));
filter2.add(new OwnerPredicate(TargetController.OPPONENT));
}
public NamelessRaceEffect() {
super(Outcome.LoseLife);
staticText = "pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards";
}
public NamelessRaceEffect(final NamelessRaceEffect effect) {
super(effect);
}
@Override
public NamelessRaceEffect copy() {
return new NamelessRaceEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card sourceCard = game.getCard(source.getSourceId());
int permanentsInPlay = new PermanentsOnBattlefieldCount(filter).calculate(game, source, null);
int cardsInGraveyards = new CardsInAllGraveyardsCount(filter2).calculate(game, source, null);
int maxAmount = Math.min(permanentsInPlay + cardsInGraveyards, controller.getLife());
int payAmount = controller.getAmount(0, maxAmount, "Pay up to " + maxAmount + " life", game);
controller.loseLife(payAmount, game, false);
game.informPlayers(new StringBuilder(sourceCard.getLogName()).append(": ").append(controller.getLogName())
.append(" pays ").append(payAmount).append(" life").toString());
game.addEffect(new SetPowerToughnessSourceEffect(payAmount, payAmount, Duration.Custom, SubLayer.SetPT_7b), source);
return true;
}
return false;
}
}

View file

@ -51,18 +51,23 @@ import mage.target.common.TargetCreatureOrPlayer;
public class NivMizzetTheFiremind extends CardImpl {
public NivMizzetTheFiremind(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{U}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}{R}{R}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.DRAGON);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever you draw a card, Niv-Mizzet, the Firemind deals 1 damage to target creature or player.
Ability ability = new DrawCardControllerTriggeredAbility(new DamageTargetEffect(1), false);
ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability);
// {T}: Draw a card.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new TapSourceCost()));
}

View file

@ -0,0 +1,94 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.o;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.dynamicvalue.common.AttackingCreatureCount;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
/**
*
* @author L_J
*/
public class OrimsPrayer extends CardImpl {
public OrimsPrayer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}");
// Whenever one or more creatures attack you, you gain 1 life for each attacking creature.
this.addAbility(new OrimsPrayerTriggeredAbility());
}
public OrimsPrayer(final OrimsPrayer card) {
super(card);
}
@Override
public OrimsPrayer copy() {
return new OrimsPrayer(this);
}
}
class OrimsPrayerTriggeredAbility extends TriggeredAbilityImpl {
public OrimsPrayerTriggeredAbility() {
super(Zone.BATTLEFIELD, new GainLifeEffect(new AttackingCreatureCount()));
}
public OrimsPrayerTriggeredAbility(final OrimsPrayerTriggeredAbility ability) {
super(ability);
}
@Override
public OrimsPrayerTriggeredAbility copy() {
return new OrimsPrayerTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.DECLARED_ATTACKERS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return game.getCombat().getDefenders().contains(getControllerId());
}
@Override
public String getRule() {
return "Whenever one or more creatures attack you, " + super.getRule();
}
}

View file

@ -50,7 +50,7 @@ import mage.game.events.NumberOfTriggersEvent;
public class Panharmonicon extends CardImpl {
public Panharmonicon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PanharmoniconEffect()));
@ -95,7 +95,9 @@ class PanharmoniconEffect extends ReplacementEffectImpl {
if (source.getControllerId().equals(event.getPlayerId())) {
GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent();
// Only EtB triggers
if (sourceEvent.getType() == EventType.ENTERS_THE_BATTLEFIELD && sourceEvent instanceof EntersTheBattlefieldEvent) {
if (sourceEvent != null
&& sourceEvent.getType() == EventType.ENTERS_THE_BATTLEFIELD
&& sourceEvent instanceof EntersTheBattlefieldEvent) {
EntersTheBattlefieldEvent entersTheBattlefieldEvent = (EntersTheBattlefieldEvent) sourceEvent;
// Only for entering artifacts or creatures
if (entersTheBattlefieldEvent.getTarget().isArtifact()
@ -116,4 +118,4 @@ class PanharmoniconEffect extends ReplacementEffectImpl {
event.setAmount(event.getAmount() + 1);
return false;
}
}
}

View file

@ -0,0 +1,181 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.p;
import java.util.Arrays;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.util.CardUtil;
import mage.util.RandomUtil;
/**
*
* @author jeffwadsworth
*/
public class ParallelThoughts extends CardImpl {
public ParallelThoughts(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}");
// When Parallel Thoughts enters the battlefield, search your library for seven cards, exile them in a face-down pile, and shuffle that pile. Then shuffle your library.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ParallelThoughtsSearchEffect()));
// If you would draw a card, you may instead put the top card of the pile you exiled into your hand.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ParallelThoughtsReplacementEffect()));
}
public ParallelThoughts(final ParallelThoughts card) {
super(card);
}
@Override
public ParallelThoughts copy() {
return new ParallelThoughts(this);
}
}
class ParallelThoughtsSearchEffect extends OneShotEffect {
ParallelThoughtsSearchEffect() {
super(Outcome.Neutral);
this.staticText = "search your library for seven cards, exile them in a face-down pile, and shuffle that pile. Then shuffle your library";
}
ParallelThoughtsSearchEffect(final ParallelThoughtsSearchEffect effect) {
super(effect);
}
@Override
public ParallelThoughtsSearchEffect copy() {
return new ParallelThoughtsSearchEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
Cards cardsInExilePile = new CardsImpl();
if (controller != null
&& permanent != null) {
TargetCardInLibrary target = new TargetCardInLibrary(7, new FilterCard());
if (controller.searchLibrary(target, game)) {
for (UUID targetId : target.getTargets()) {
Card card = controller.getLibrary().getCard(targetId, game);
if (card != null) {
cardsInExilePile.add(card);
}
}
// shuffle that exiled pile
UUID[] shuffled = cardsInExilePile.toArray(new UUID[0]);
for (int n = shuffled.length - 1; n > 0; n--) {
int r = RandomUtil.nextInt(n + 1);
UUID temp = shuffled[n];
shuffled[n] = shuffled[r];
shuffled[r] = temp;
}
cardsInExilePile.clear();
cardsInExilePile.addAll(Arrays.asList(shuffled));
// move to exile zone and turn face down
for (Card card : cardsInExilePile.getCards(game)) {
controller.moveCardsToExile(card, source, game, false, CardUtil.getCardExileZoneId(game, source), permanent.getLogName());
card.setFaceDown(true, game);
}
// shuffle controller library
controller.shuffleLibrary(source, game);
}
return true;
}
return false;
}
}
class ParallelThoughtsReplacementEffect extends ReplacementEffectImpl {
ParallelThoughtsReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.DrawCard);
staticText = "If you would draw a card, you may instead put the top card of the pile you exiled with Parallel Thoughts into your hand";
}
ParallelThoughtsReplacementEffect(final ParallelThoughtsReplacementEffect effect) {
super(effect);
}
@Override
public ParallelThoughtsReplacementEffect copy() {
return new ParallelThoughtsReplacementEffect(this);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null
&& !game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)).getCards(game).isEmpty()) {
Card card = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)).getCards(game).iterator().next();
if (card != null) {
controller.moveCards(card, Zone.HAND, source, game);
}
}
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.DRAW_CARD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return source.getControllerId().equals(event.getPlayerId());
}
}

View file

@ -0,0 +1,115 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.p;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.PutCardFromHandOnTopOfLibraryCost;
import mage.abilities.effects.PreventionEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.TargetSource;
/**
*
* @author jeffwadsworth
*/
public class Penance extends CardImpl {
public Penance(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// Put a card from your hand on top of your library: The next time a black or red source of your choice would deal damage this turn, prevent that damage.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PenanceEffect(), new PutCardFromHandOnTopOfLibraryCost()));
}
public Penance(final Penance card) {
super(card);
}
@Override
public Penance copy() {
return new Penance(this);
}
}
class PenanceEffect extends PreventionEffectImpl {
private final TargetSource target;
public PenanceEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
this.staticText = "The next time a black or red source of your choice would deal damage to you this turn, prevent that damage.";
this.target = new TargetSource();
}
public PenanceEffect(final PenanceEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public PenanceEffect copy() {
return new PenanceEffect(this);
}
@Override
public void init(Ability source, Game game) {
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
super.init(source, game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
this.used = true;
this.discard(); // only one use
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (!this.used
&& super.applies(event, source, game)) {
if (event.getTargetId().equals(source.getControllerId())
&& event.getSourceId().equals(target.getFirstTarget())) {
return (game.getObject(target.getFirstTarget()).getColor(game).contains(ObjectColor.BLACK)
|| game.getObject(target.getFirstTarget()).getColor(game).contains(ObjectColor.RED));
}
}
return false;
}
}

View file

@ -46,7 +46,7 @@ public class PlanarGate extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}");
// Creature spells you cast cost up to {2} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCreatureCard("creature spells"), 2, true)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCreatureCard("Creature spells"), 2, true)));
}
public PlanarGate(final PlanarGate card) {

View file

@ -0,0 +1,133 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.PreventDamageByTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetEnchantmentPermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class PowerLeak extends CardImpl {
public PowerLeak(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}");
this.subtype.add(SubType.AURA);
// Enchant enchantment
TargetPermanent auraTarget = new TargetEnchantmentPermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// At the beginning of the upkeep of enchanted enchantment's controller, that player may pay any amount of mana. Power Leak deals 2 damage to that player. Prevent X of that damage, where X is the amount of mana that player paid this way.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new PowerLeakEffect(), TargetController.CONTROLLER_ATTACHED_TO, false, true, "At the beginning of the upkeep of enchanted enchantment's controller, "));
}
public PowerLeak(final PowerLeak card) {
super(card);
}
@Override
public PowerLeak copy() {
return new PowerLeak(this);
}
}
class PowerLeakEffect extends OneShotEffect {
public PowerLeakEffect() {
super(Outcome.Detriment);
this.staticText = "that player may pay any amount of mana. {this} deals 2 damage to that player. Prevent X of that damage, where X is the amount of mana that player paid this way";
}
public PowerLeakEffect(final PowerLeakEffect effect) {
super(effect);
}
@Override
public PowerLeakEffect copy() {
return new PowerLeakEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId());
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (player != null && permanent != null) {
ManaCosts<ManaCost> cost = new ManaCostsImpl<>("{X}");
String message = "Pay {X} to prevent X damage from " + permanent.getLogName() + "?";
int xValue = 0;
if (player != null && player.chooseUse(Outcome.Neutral, message, source, game)) {
xValue = player.announceXMana(0, Integer.MAX_VALUE, "Choose the amount of mana to pay", game, source);
cost.add(new GenericManaCost(xValue));
if (cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) {
game.informPlayers(player.getLogName() + " paid {" + xValue + "} for " + permanent.getLogName());
} else {
game.informPlayers(player.getLogName() + " didn't pay {X} for " + permanent.getLogName());
}
} else {
game.informPlayers(player.getLogName() + " didn't pay {X} for " + permanent.getLogName());
}
PreventDamageByTargetEffect effect = new PreventDamageByTargetEffect(Duration.OneUse, xValue, false);
if (xValue != 0 && cost.isPaid()) {
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
}
player.damage(2, source.getSourceId(), game, false, true);
effect.discard();
return true;
}
return false;
}
}

View file

@ -93,11 +93,6 @@ class ProgenitusProtectionAbility extends ProtectionAbility {
return new ProgenitusProtectionAbility(this);
}
@Override
public String getRule() {
return "Protection from everything";
}
@Override
public boolean canTarget(MageObject source, Game game) {
return false;

View file

@ -0,0 +1,134 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.p;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.Mana;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.PreventionEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetSource;
import mage.util.CardUtil;
/**
*
* @author jeffwadsworth
*/
public class ProtectiveSphere extends CardImpl {
public ProtectiveSphere(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// {1}, Pay 1 life: Prevent all damage that would be dealt to you this turn by a source of your choice that shares a color with the mana spent on this activation cost.
Ability ability = new SimpleActivatedAbility(new ProtectiveSphereEffect(), new ManaCostsImpl("{1}"));
ability.addCost(new PayLifeCost(1));
this.addAbility(ability);
}
public ProtectiveSphere(final ProtectiveSphere card) {
super(card);
}
@Override
public ProtectiveSphere copy() {
return new ProtectiveSphere(this);
}
}
class ProtectiveSphereEffect extends PreventionEffectImpl {
private final TargetSource target;
private static Mana manaUsed;
private static List<ObjectColor> colorsOfChosenSource = new ArrayList<>();
public ProtectiveSphereEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
this.staticText = "Prevent all damage that would be dealt to you this turn by a source of your choice that shares a color with the mana spent on this activation cost.";
this.target = new TargetSource();
}
public ProtectiveSphereEffect(final ProtectiveSphereEffect effect) {
super(effect);
this.target = effect.target.copy();
}
@Override
public ProtectiveSphereEffect copy() {
return new ProtectiveSphereEffect(this);
}
@Override
public void init(Ability source, Game game) {
target.setNotTarget(true);
target.setRequired(false);
Player controller = game.getPlayer(source.getControllerId());
Permanent protectiveSphere = game.getPermanent(source.getSourceId());
if (controller != null
&& protectiveSphere != null) {
game.getState().setValue("ProtectiveSphere" + source.getSourceId().toString(), source.getManaCostsToPay().getUsedManaToPay()); //store the mana used to pay
protectiveSphere.addInfo("MANA USED", CardUtil.addToolTipMarkTags("Last mana used for protective ability: " + source.getManaCostsToPay().getUsedManaToPay()), game);
}
this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
super.init(source, game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
manaUsed = (Mana) game.getState().getValue("ProtectiveSphere" + source.getSourceId().toString());
if (super.applies(event, source, game)) {
if (event.getTargetId().equals(source.getControllerId())
&& event.getSourceId().equals(target.getFirstTarget())) {
colorsOfChosenSource = game.getObject(target.getFirstTarget()).getColor(game).getColors();
if (colorsOfChosenSource.stream().anyMatch((c) -> (manaUsed.getColor(c.getColoredManaSymbol()) > 0))) {
return true;
}
}
}
return false;
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.continuous.BecomesChosenCreatureTypeSourceEffect;
import mage.abilities.keyword.MorphAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.SubType;
/**
*
* @author L_J
*/
public class ProteusMachine extends CardImpl {
public ProteusMachine(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{3}");
this.subtype.add(SubType.SHAPESHIFTER);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Morph {0}
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{0}")));
// When Proteus Machine is turned face up, it becomes the creature type of your choice. (This effect lasts indefinitely.)
this.addAbility(new TurnedFaceUpSourceTriggeredAbility(new BecomesChosenCreatureTypeSourceEffect(false, Duration.Custom)));
}
public ProteusMachine(final ProteusMachine card) {
super(card);
}
@Override
public ProteusMachine copy() {
return new ProteusMachine(this);
}
}

View file

@ -0,0 +1,112 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class PutridCyclops extends CardImpl {
public PutridCyclops(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.CYCLOPS);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// When Putrid Cyclops enters the battlefield, scry 1, then reveal the top card of your library. Putrid Cyclops gets -X/-X until end of turn, where X is that card's converted mana cost.
this.addAbility(new EntersBattlefieldTriggeredAbility(new PutridCyclopEffect()));
}
public PutridCyclops(final PutridCyclops card) {
super(card);
}
@Override
public PutridCyclops copy() {
return new PutridCyclops(this);
}
}
class PutridCyclopEffect extends OneShotEffect {
public PutridCyclopEffect() {
super(Outcome.Detriment);
this.staticText = "scry 1, then reveal the top card of your library. {this} gets -X/-X until end of turn, where X is that card's converted mana cost"
+ " <i>(To scry 1, look at the top card of your library, then you may put that card on the bottom of your library.)</i>";
}
public PutridCyclopEffect(final PutridCyclopEffect effect) {
super(effect);
}
@Override
public PutridCyclopEffect copy() {
return new PutridCyclopEffect(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) {
new ScryEffect(1).apply(game, source);
Card card = controller.getLibrary().getFromTop(game);
if (card != null) {
controller.revealCards(sourceObject.getIdName(), new CardsImpl(card), game);
int unboost = card.getConvertedManaCost() * -1;
ContinuousEffect effect = new BoostSourceEffect(unboost, unboost, Duration.EndOfTurn);
game.addEffect(effect, source);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,135 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.r;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.watchers.Watcher;
/**
*
* @author jeffwadsworth, MTGFan & L_J
*/
public class ReversePolarity extends CardImpl {
public ReversePolarity(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}{W}");
// You gain X life, where X is twice the damage dealt to you so far this turn by artifacts.
this.getSpellAbility().addEffect(new GainLifeEffect(new ReversePolarityAmount(), "You gain X life, where X is twice the damage dealt to you so far this turn by artifacts"));
this.getSpellAbility().addWatcher(new ReversePolarityWatcher());
}
public ReversePolarity(final ReversePolarity card) {
super(card);
}
@Override
public ReversePolarity copy() {
return new ReversePolarity(this);
}
}
class ReversePolarityAmount implements DynamicValue {
@Override
public int calculate(Game game, Ability source, Effect effect) {
ReversePolarityWatcher watcher = (ReversePolarityWatcher) game.getState().getWatchers().get(ReversePolarityWatcher.class.getSimpleName());
if(watcher != null) {
return watcher.getArtifactDamageReceivedThisTurn(source.getControllerId()) * 2;
}
return 0;
}
@Override
public ReversePolarityAmount copy() {
return new ReversePolarityAmount();
}
@Override
public String getMessage() {
return "";
}
}
class ReversePolarityWatcher extends Watcher {
private final Map<UUID, Integer> artifactDamageReceivedThisTurn = new HashMap<>();
public ReversePolarityWatcher() {
super(ReversePolarityWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public ReversePolarityWatcher(final ReversePolarityWatcher watcher) {
super(watcher);
for (Entry<UUID, Integer> entry : watcher.artifactDamageReceivedThisTurn.entrySet()) {
artifactDamageReceivedThisTurn.put(entry.getKey(), entry.getValue());
}
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) {
UUID playerId = event.getTargetId();
if (playerId != null) {
Permanent permanent = game.getPermanent(event.getSourceId());
if (permanent != null && permanent.isArtifact()) {
artifactDamageReceivedThisTurn.putIfAbsent(playerId, 0);
artifactDamageReceivedThisTurn.compute(playerId, (k, v) -> v + event.getAmount());
}
}
}
}
public int getArtifactDamageReceivedThisTurn(UUID playerId) {
return artifactDamageReceivedThisTurn.getOrDefault(playerId, 0);
}
@Override
public void reset() {
artifactDamageReceivedThisTurn.clear();
}
@Override
public ReversePolarityWatcher copy() {
return new ReversePolarityWatcher(this);
}
}

View file

@ -0,0 +1,173 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.replacement.DealtDamageToCreatureBySourceDies;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.target.common.TargetAttackingCreature;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.DamagedByWatcher;
/**
*
* @author L_J
*/
public class Runesword extends CardImpl {
public Runesword(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}");
// {3}, {T}: Target attacking creature gets +2/+0 until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(2, 0, Duration.EndOfTurn), new GenericManaCost(3));
// When that creature leaves the battlefield this turn, sacrifice Runesword.
ability.addEffect(new RuneswordCreateTriggeredAbilityEffect());
// If the creature deals damage to a creature this turn, the creature dealt damage can't be regenerated this turn.
ability.addEffect(new RuneswordCantBeRegeneratedEffect());
// If a creature dealt damage by the targeted creature would die this turn, exile that creature instead.
SimpleStaticAbility ability2 = new SimpleStaticAbility(Zone.BATTLEFIELD, new DealtDamageToCreatureBySourceDies(this, Duration.Custom));
ability2.addWatcher(new DamagedByWatcher());
ability2.setRuleVisible(false);
ability.addEffect(new GainAbilityTargetEffect(ability2, Duration.EndOfTurn, null, false).setText(
"If a creature dealt damage by the targeted creature would die this turn, exile that creature instead"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetAttackingCreature());
this.addAbility(ability);
}
public Runesword(final Runesword card) {
super(card);
}
@Override
public Runesword copy() {
return new Runesword(this);
}
}
class RuneswordCreateTriggeredAbilityEffect extends OneShotEffect {
public RuneswordCreateTriggeredAbilityEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "When that creature leaves the battlefield this turn, sacrifice {this}";
}
public RuneswordCreateTriggeredAbilityEffect(final RuneswordCreateTriggeredAbilityEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
Permanent targetObject = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (sourceObject != null && targetObject != null) {
Effect sacrificeEffect = new SacrificeTargetEffect("sacrifice " + sourceObject.getName());
sacrificeEffect.setTargetPointer(new FixedTarget(sourceObject, game));
LeavesBattlefieldTriggeredAbility triggerAbility = new LeavesBattlefieldTriggeredAbility(sacrificeEffect, false);
triggerAbility.setRuleVisible(false);
ContinuousEffect continuousEffect = new GainAbilityTargetEffect(triggerAbility, Duration.EndOfTurn);
continuousEffect.setTargetPointer(new FixedTarget(targetObject, game));
game.addEffect(continuousEffect, source);
return true;
}
return false;
}
@Override
public RuneswordCreateTriggeredAbilityEffect copy() {
return new RuneswordCreateTriggeredAbilityEffect(this);
}
}
class RuneswordCantBeRegeneratedEffect extends ContinuousRuleModifyingEffectImpl {
private UUID targetCreatureId;
public RuneswordCantBeRegeneratedEffect() {
super(Duration.EndOfTurn, Outcome.Benefit, false, false);
this.staticText = "If the creature deals damage to a creature this turn, the creature dealt damage can't be regenerated this turn";
}
public RuneswordCantBeRegeneratedEffect(final RuneswordCantBeRegeneratedEffect effect) {
super(effect);
targetCreatureId = effect.targetCreatureId;
}
@Override
public RuneswordCantBeRegeneratedEffect copy() {
return new RuneswordCantBeRegeneratedEffect(this);
}
public void init(Ability source, Game game) {
targetCreatureId = getTargetPointer().getFirst(game, source);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.REGENERATE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (targetCreatureId != null) {
DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get(DamagedByWatcher.class.getSimpleName(), targetCreatureId);
if (watcher != null) {
return watcher.wasDamaged(event.getTargetId(), game);
}
}
return false;
}
}

View file

@ -28,17 +28,13 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityType;
import mage.constants.CardType;
import mage.filter.FilterStackObject;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.stack.StackAbility;
import mage.target.common.TargetActivatedOrTriggeredAbility;
import mage.filter.FilterAbility;
import mage.filter.predicate.ability.ArtifactSourcePredicate;
import mage.target.common.TargetActivatedAbility;
/**
*
@ -46,7 +42,7 @@ import mage.target.common.TargetActivatedOrTriggeredAbility;
*/
public class Rust extends CardImpl {
private final static FilterStackObject filter = new FilterStackObject("activated ability from an artifact source");
private final static FilterAbility filter = new FilterAbility("activated ability from an artifact source");
static {
filter.add(new ArtifactSourcePredicate());
@ -57,7 +53,7 @@ public class Rust extends CardImpl {
// Counter target activated ability from an artifact source.
this.getSpellAbility().addEffect(new CounterTargetEffect());
this.getSpellAbility().addTarget(new TargetActivatedOrTriggeredAbility(filter));
this.getSpellAbility().addTarget(new TargetActivatedAbility(filter));
}
public Rust(final Rust card) {
@ -69,22 +65,3 @@ public class Rust extends CardImpl {
return new Rust(this);
}
}
class ArtifactSourcePredicate implements Predicate<Ability> {
public ArtifactSourcePredicate() {
}
@Override
public boolean apply(Ability input, Game game) {
if (input instanceof StackAbility) {
return input.getSourceObject(game).isArtifact() && input.getAbilityType() == AbilityType.ACTIVATED;
}
return false;
}
@Override
public String toString() {
return "Source(Artifact)";
}
}

View file

@ -0,0 +1,142 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.EchoAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class ShahOfNaarIsle extends CardImpl {
public ShahOfNaarIsle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.EFREET);
this.power = new MageInt(6);
this.toughness = new MageInt(6);
// Trample
this.addAbility(TrampleAbility.getInstance());
// Echo {0}
this.addAbility(new EchoAbility("{0}"));
// When Shah of Naar Isle's echo cost is paid, each opponent may draw up to three cards.
this.addAbility(new ShahOfNaarIsleTriggeredAbility());
}
public ShahOfNaarIsle(final ShahOfNaarIsle card) {
super(card);
}
@Override
public ShahOfNaarIsle copy() {
return new ShahOfNaarIsle(this);
}
}
class ShahOfNaarIsleTriggeredAbility extends TriggeredAbilityImpl {
public ShahOfNaarIsleTriggeredAbility() {
super(Zone.BATTLEFIELD, new ShahOfNaarIsleEffect(), false);
}
public ShahOfNaarIsleTriggeredAbility(final ShahOfNaarIsleTriggeredAbility effect) {
super(effect);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ECHO_PAID;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return getSourceId().equals(event.getSourceId());
}
@Override
public ShahOfNaarIsleTriggeredAbility copy() {
return new ShahOfNaarIsleTriggeredAbility(this);
}
@Override
public String getRule() {
return "When {this}'s echo cost is paid, " + super.getRule();
}
}
class ShahOfNaarIsleEffect extends OneShotEffect {
public ShahOfNaarIsleEffect() {
super(Outcome.DrawCard);
this.staticText = "each opponent may draw up to three cards";
}
public ShahOfNaarIsleEffect(final ShahOfNaarIsleEffect effect) {
super(effect);
}
@Override
public ShahOfNaarIsleEffect copy() {
return new ShahOfNaarIsleEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (UUID playerId : game.getOpponents(controller.getId())) {
Player opponent = game.getPlayer(playerId);
if (opponent != null) {
int number = opponent.getAmount(0, 3, "Draw how many cards?", game);
opponent.drawCards(number, game);
}
}
return true;
}
return false;
}
}

View file

@ -36,7 +36,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -48,14 +48,12 @@ import mage.target.common.TargetCreatureOrPlayer;
*/
public class Soulblast extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures you control");
public Soulblast(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}{R}{R}");
// As an additional cost to cast Soulblast, sacrifice all creatures you control.
this.getSpellAbility().addCost(new SacrificeAllCost(filter));
this.getSpellAbility().addCost(new SacrificeAllCost(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED));
// Soulblast deals damage to target creature or player equal to the total power of the sacrificed creatures.
this.getSpellAbility().addEffect(new SoulblastEffect());
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
@ -90,7 +88,7 @@ class SoulblastEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
int power = 0;
for (Cost cost :source.getCosts()) {
for (Cost cost : source.getCosts()) {
if (cost instanceof SacrificeAllCost) {
for (Permanent permanent : ((SacrificeAllCost) cost).getPermanents()) {
power += permanent.getPower().getValue();

View file

@ -76,7 +76,7 @@ class CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect extends RestrictionE
public CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect() {
super(Duration.WhileOnBattlefield);
staticText = "Can't be blocked except by creatures with flying or reach";
staticText = "{this} can't be blocked except by creatures with flying or reach";
}
public CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect(final CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect effect) {

View file

@ -51,7 +51,7 @@ public class SpiritCairn extends CardImpl {
// Whenever a player discards a card, you may pay {W}. If you do, create a 1/1 white Spirit creature token with flying.
this.addAbility(new SimpleTriggeredAbility(Zone.BATTLEFIELD, GameEvent.EventType.DISCARDED_CARD,
new DoIfCostPaid(new CreateTokenEffect(new SpiritWhiteToken()), new ManaCostsImpl("{W}")),
"Whenever a player discards a card, you ",
"Whenever a player discards a card, ",
false, false));
}

View file

@ -66,7 +66,7 @@ public class SpiritMirror extends CardImpl {
this.addAbility(new ConditionalTriggeredAbility(
new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new ReflectionToken()), TargetController.YOU, false),
new PermanentsOnTheBattlefieldCondition(filterToken, ComparisonType.EQUAL_TO, 0, false),
"At the beginning of your upkeep, if there are no Reflection tokens on the battlefield, create a 2/2 white Reflection creature token"));
"At the beginning of your upkeep, if there are no Reflection tokens on the battlefield, create a 2/2 white Reflection creature token."));
// {0}: Destroy target Reflection.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new GenericManaCost(0));

View file

@ -0,0 +1,83 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import static mage.filter.predicate.permanent.ControllerControlsIslandPredicate.filter;
/**
*
* @author LevelX2
*/
public class SteamfloggerBoss extends CardImpl {
public SteamfloggerBoss(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.GOBLIN);
this.subtype.add(SubType.RIGGER);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Other Rigger creatures you control get +1/+0 and have haste.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD,
new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield, new FilterCreaturePermanent(SubType.RIGGER, "Rigger creatures"), true));
Effect effect = new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter);
effect.setText("and have haste");
ability.addEffect(effect);
this.addAbility(ability);
// If a Rigger you control would assemble a Contraption, it assembles two Contraptions instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("If a Rigger you control would assemble a Contraption, it assembles two Contraptions instead. (NOT IMPLEMENTED)")));
}
public SteamfloggerBoss(final SteamfloggerBoss card) {
super(card);
}
@Override
public SteamfloggerBoss copy() {
return new SteamfloggerBoss(this);
}
}

View file

@ -41,8 +41,8 @@ import mage.abilities.keyword.IndestructibleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -56,7 +56,7 @@ import mage.players.Player;
public class StuffyDoll extends CardImpl {
public StuffyDoll(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{5}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}");
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(0);
this.toughness = new MageInt(1);
@ -67,7 +67,7 @@ public class StuffyDoll extends CardImpl {
this.addAbility(IndestructibleAbility.getInstance());
// Whenever Stuffy Doll is dealt damage, it deals that much damage to the chosen player.
this.addAbility(new StuffyDollTriggeredAbility());
// {tap}: Stuffy Doll deals 1 damage to itself.
// {T}: Stuffy Doll deals 1 damage to itself.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageSelfEffect(1), new TapSourceCost()));
}

View file

@ -46,8 +46,7 @@ import mage.filter.FilterCard;
public class SultaiAscendancy extends CardImpl {
public SultaiAscendancy(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}{G}{U}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{G}{U}");
// At the beginning of your upkeep, look at the top two cards of your library. Put any number of them into your graveyard and the rest on top of your library in any order.
Effect effect = new LookLibraryAndPickControllerEffect(

View file

@ -141,12 +141,7 @@ class TeferisProtectionAbility extends ProtectionAbility {
public TeferisProtectionAbility copy() {
return new TeferisProtectionAbility(this);
}
@Override
public String getRule() {
return "Protection from everything";
}
@Override
public boolean canTarget(MageObject source, Game game) {
return false;

View file

@ -0,0 +1,66 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DiscardsACardPlayerTriggeredAbility;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.MayTapOrUntapTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.TargetPermanent;
/**
*
* @author jeffwadsworth
*/
public class TelekineticBonds extends CardImpl {
public TelekineticBonds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}{U}");
// Whenever a player discards a card, you may pay {1}{U}. If you do, you may tap or untap target permanent.
Ability ability = new DiscardsACardPlayerTriggeredAbility(new DoIfCostPaid(new MayTapOrUntapTargetEffect(), new ManaCostsImpl("{1}{U}")), true);
ability.addTarget(new TargetPermanent());
this.addAbility(ability);
}
public TelekineticBonds(final TelekineticBonds card) {
super(card);
}
@Override
public TelekineticBonds copy() {
return new TelekineticBonds(this);
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author L_J
*/
public class TemporaryTruce extends CardImpl {
public TemporaryTruce(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{W}");
// Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life.
this.getSpellAbility().addEffect(new TemporaryTruceEffect());
}
public TemporaryTruce(final TemporaryTruce card) {
super(card);
}
@Override
public TemporaryTruce copy() {
return new TemporaryTruce(this);
}
}
class TemporaryTruceEffect extends OneShotEffect {
TemporaryTruceEffect() {
super(Outcome.DrawCard);
this.staticText = "Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life";
}
TemporaryTruceEffect(final TemporaryTruceEffect effect) {
super(effect);
}
@Override
public TemporaryTruceEffect copy() {
return new TemporaryTruceEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
int cardsToDraw = player.getAmount(0, 2, "Draw how many cards?", game);
player.drawCards(cardsToDraw, game);
player.gainLife((2 - cardsToDraw) * 2, game);
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,146 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.*;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.Watcher;
/**
*
* @author L_J
*/
public class TheFallen extends CardImpl {
public TheFallen(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// At the beginning of your upkeep, The Fallen deals 1 damage to each opponent it has dealt damage to this game.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TheFallenEffect(), TargetController.YOU, false), new TheFallenWatcher());
}
public TheFallen(final TheFallen card) {
super(card);
}
@Override
public TheFallen copy() {
return new TheFallen(this);
}
}
class TheFallenEffect extends OneShotEffect {
public TheFallenEffect() {
super(Outcome.Damage);
this.staticText = "{this} deals 1 damage to each opponent it has dealt damage to this game";
}
public TheFallenEffect(final TheFallenEffect effect) {
super(effect);
}
@Override
public TheFallenEffect copy() {
return new TheFallenEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
TheFallenWatcher watcher = (TheFallenWatcher) game.getState().getWatchers().get(TheFallenWatcher.class.getSimpleName());
if (watcher != null && watcher.getPlayerDealtDamageThisGame(source.getSourceId()) != null) {
for (UUID playerId : watcher.getPlayerDealtDamageThisGame(source.getSourceId())) {
if (!source.getControllerId().equals(playerId)) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.damage(1, source.getSourceId(), game, false, true);
}
}
}
return true;
}
return false;
}
}
class TheFallenWatcher extends Watcher {
private Map<UUID, Set<UUID>> playersDealtDamageThisGame = new HashMap<>(); // Map<creatureId, Set<playerId>>
public TheFallenWatcher() {
super(TheFallenWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public TheFallenWatcher(final TheFallenWatcher watcher) {
super(watcher);
playersDealtDamageThisGame = new HashMap<>(watcher.playersDealtDamageThisGame);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) {
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
if (permanent != null) {
Set<UUID> toAdd;
if (playersDealtDamageThisGame.get(event.getSourceId()) == null) {
toAdd = new HashSet<>();
} else {
toAdd = playersDealtDamageThisGame.get(event.getSourceId());
}
toAdd.add(event.getPlayerId());
playersDealtDamageThisGame.put(event.getSourceId(), toAdd);
}
}
}
public Set<UUID> getPlayerDealtDamageThisGame(UUID creatureId) {
return playersDealtDamageThisGame.get(creatureId);
}
@Override
public TheFallenWatcher copy() {
return new TheFallenWatcher(this);
}
}

View file

@ -68,7 +68,7 @@ public class TheImmortalSun extends CardImpl {
this.addAbility(new BeginningOfDrawTriggeredAbility(new DrawCardSourceControllerEffect(1)
.setText("draw an additional card"), TargetController.YOU, false));
// Spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCard("Spells you cast"), 1)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCard("Spells"), 1)));
// Creatures you control get +1/+1.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield)));
}

View file

@ -0,0 +1,104 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCreatureOrPlayer;
/**
*
* @author LevelX2
*/
public class ThunderbladeCharge extends CardImpl {
public ThunderbladeCharge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}{R}");
// Thunderblade Charge deals 3 damage to target creature or player.
this.getSpellAbility().addEffect(new DamageTargetEffect(3));
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
// Whenever one or more creatures you control deal combat damage to a player, if Thunderblade Charge is in your graveyard, you may pay {2}{R}{R}{R}. If you do, you may cast it without paying its mana cost.
this.addAbility(new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(Zone.GRAVEYARD,
new DoIfCostPaid(new ThunderbladeChargeCastEffect(), new ManaCostsImpl("{2}{R}{R}{R}"))
.setText("if {this} is in your graveyard, you may pay {2}{R}{R}{R}. If you do, you may cast it without paying its mana cost")));
}
public ThunderbladeCharge(final ThunderbladeCharge card) {
super(card);
}
@Override
public ThunderbladeCharge copy() {
return new ThunderbladeCharge(this);
}
}
class ThunderbladeChargeCastEffect extends OneShotEffect {
public ThunderbladeChargeCastEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "you may cast {this} without paying its mana cost";
}
public ThunderbladeChargeCastEffect(final ThunderbladeChargeCastEffect effect) {
super(effect);
}
@Override
public ThunderbladeChargeCastEffect copy() {
return new ThunderbladeChargeCastEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Card sourceCard = game.getCard(source.getSourceId());
if (controller != null
&& sourceCard != null
&& Zone.GRAVEYARD == game.getState().getZone(sourceCard.getId())) {
controller.cast(sourceCard.getSpellAbility(), game, true);
return true;
}
return false;
}
}

View file

@ -86,7 +86,7 @@ class TormentOfHailfireEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int repeat = source.getManaCostsToPay().getX();
for (int i = 0; i < repeat; i++) {
for (int i = 1; i <= repeat; i++) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
Player opponent = game.getPlayer(opponentId);
if (opponent != null) {
@ -97,8 +97,9 @@ class TormentOfHailfireEffect extends OneShotEffect {
if (opponent.choose(outcome, target, source.getSourceId(), game)) {
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null) {
permanent.sacrifice(source.getSourceId(), game);
continue;
if (permanent.sacrifice(source.getSourceId(), game)) {
continue;
}
}
}
}

View file

@ -30,6 +30,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.cards.CardImpl;
@ -51,7 +52,7 @@ import mage.game.permanent.Permanent;
public class TorporOrb extends CardImpl {
public TorporOrb(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// Creatures entering the battlefield don't cause abilities to trigger.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TorporOrbEffect()));
@ -89,7 +90,7 @@ class TorporOrbEffect extends ContinuousRuleModifyingEffectImpl {
if (ability != null && ability.getAbilityType() == AbilityType.TRIGGERED) {
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
if (permanent != null && permanent.isCreature()) {
return true;
return (((TriggeredAbility) ability).checkTrigger(event, game));
}
}
return false;
@ -97,10 +98,15 @@ class TorporOrbEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(event.getSourceId());
MageObject enteringObject = game.getObject(event.getSourceId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (mageObject != null && sourceObject != null) {
return sourceObject.getLogName() + " prevented ability of " + mageObject.getLogName() + " to trigger";
Ability ability = (Ability) getValue("targetAbility");
if (enteringObject != null && sourceObject != null && ability != null) {
MageObject abilitObject = game.getObject(ability.getSourceId());
if (abilitObject != null) {
return sourceObject.getLogName() + " prevented ability of " + abilitObject.getLogName()
+ " to trigger for " + enteringObject.getLogName() + " entering the battlefield.";
}
}
return null;
}

View file

@ -29,6 +29,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.ContinuousEffectImpl;
@ -49,7 +50,7 @@ import mage.target.common.TargetOpponent;
public class TreacherousPitDweller extends CardImpl {
public TreacherousPitDweller(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}");
this.subtype.add(SubType.DEMON);
this.power = new MageInt(4);
@ -77,24 +78,24 @@ class TreacherousPitDwellerTriggeredAbility extends TriggeredAbilityImpl {
private static final String ruleText = "When {this} enters the battlefield from a graveyard, ";
public TreacherousPitDwellerTriggeredAbility() {
super(Zone.BATTLEFIELD, new TreacherousPitDwellerEffect(),false);
super(Zone.BATTLEFIELD, new TreacherousPitDwellerEffect(), false);
addTarget(new TargetOpponent());
}
public TreacherousPitDwellerTriggeredAbility(final TreacherousPitDwellerTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getTargetId().equals(getSourceId()) && ((EntersTheBattlefieldEvent) event).getFromZone() == Zone.GRAVEYARD;
}
return event.getTargetId().equals(getSourceId()) && ((EntersTheBattlefieldEvent) event).getFromZone() == Zone.GRAVEYARD;
}
@Override
public TreacherousPitDwellerTriggeredAbility copy() {
return new TreacherousPitDwellerTriggeredAbility(this);
@ -104,7 +105,7 @@ class TreacherousPitDwellerTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return ruleText + super.getRule();
}
}
class TreacherousPitDwellerEffect extends ContinuousEffectImpl {
@ -125,10 +126,12 @@ class TreacherousPitDwellerEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = (Permanent) source.getSourceObjectIfItStillExists(game);
MageObject permanent = source.getSourceObjectIfItStillExists(game); // it can also return Card object
Player targetOpponent = game.getPlayer(source.getFirstTarget());
if (permanent != null && targetOpponent != null) {
return permanent.changeControllerId(targetOpponent.getId(), game);
if (permanent != null
&& (permanent instanceof Permanent)
&& targetOpponent != null) {
return ((Permanent) permanent).changeControllerId(targetOpponent.getId(), game);
} else {
discard();
}

View file

@ -0,0 +1,253 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.v;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.TapTargetCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.watchers.Watcher;
/**
*
* @author L_J
*/
public class VodalianWarMachine extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Merfolk you control");
static {
filter.add(Predicates.not(new TappedPredicate()));
filter.add(new SubtypePredicate(SubType.MERFOLK));
}
public VodalianWarMachine(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}");
this.subtype.add(SubType.WALL);
this.power = new MageInt(0);
this.toughness = new MageInt(4);
// Defender
this.addAbility(DefenderAbility.getInstance());
// Tap an untapped Merfolk you control: Vodalian War Machine can attack this turn as though it didn't have defender.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true)));
this.addAbility(ability);
// Tap an untapped Merfolk you control: Vodalian War Machine gets +2/+1 until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(2, 1, Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))));
// When Vodalian War Machine dies, destroy all Merfolk tapped this turn to pay for its abilities.
this.addAbility(new VodalianWarMachineTriggeredAbility(), new VodalianWarMachineWatcher());
}
public VodalianWarMachine(final VodalianWarMachine card) {
super(card);
}
@Override
public VodalianWarMachine copy() {
return new VodalianWarMachine(this);
}
}
class VodalianWarMachineTriggeredAbility extends DiesTriggeredAbility {
public VodalianWarMachineTriggeredAbility() {
super(new VodalianWarMachineEffect(), false);
}
public VodalianWarMachineTriggeredAbility(VodalianWarMachineTriggeredAbility ability) {
super(ability);
}
@Override
public VodalianWarMachineTriggeredAbility copy() {
return new VodalianWarMachineTriggeredAbility(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent before = ((ZoneChangeEvent) event).getTarget();
if (before == null) {
return false;
}
if (super.checkTrigger(event, game)) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.getTarget().isTransformable()) {
if (!zEvent.getTarget().getAbilities().contains(this)) {
return false;
}
}
return true;
}
return false;
}
}
class VodalianWarMachineEffect extends OneShotEffect {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Merfolk tapped this turn to pay for its abilities");
static {
filter.add(new SubtypePredicate(SubType.MERFOLK));
}
public VodalianWarMachineEffect() {
super(Outcome.Detriment);
staticText = "destroy all " + filter.getMessage();
}
public VodalianWarMachineEffect(final VodalianWarMachineEffect effect) {
super(effect);
}
@Override
public VodalianWarMachineEffect copy() {
return new VodalianWarMachineEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (sourcePermanent != null) {
VodalianWarMachineWatcher watcher = (VodalianWarMachineWatcher) game.getState().getWatchers().get(VodalianWarMachineWatcher.class.getSimpleName());
if (watcher != null && watcher.getTappedMerfolkIds(sourcePermanent, game) != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
if (watcher.getTappedMerfolkIds(sourcePermanent, game).contains(new MageObjectReference(permanent, game))) {
permanent.destroy(source.getSourceId(), game, false);
}
}
return true;
}
}
return false;
}
}
class VodalianWarMachineWatcher extends Watcher {
public Map<MageObjectReference, Set<MageObjectReference>> tappedMerfolkIds = new HashMap<>();
public VodalianWarMachineWatcher() {
super(VodalianWarMachineWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public VodalianWarMachineWatcher(final VodalianWarMachineWatcher watcher) {
super(watcher);
// We have for sure to use copied collections, but there is no need to copy the MageObjectReference objects.
for (Entry<MageObjectReference, Set<MageObjectReference>> entry : watcher.tappedMerfolkIds.entrySet()) {
this.tappedMerfolkIds.put(entry.getKey(), new HashSet<>(entry.getValue()));
}
}
@Override
public VodalianWarMachineWatcher copy() {
return new VodalianWarMachineWatcher(this);
}
public Set<MageObjectReference> getTappedMerfolkIds(Permanent permanent, Game game) {
return tappedMerfolkIds.get(new MageObjectReference(permanent, game));
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.ACTIVATED_ABILITY) {
if (event.getSourceId() != null) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
if (sourcePermanent != null) {
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
if (stackAbility != null) {
Ability ability = stackAbility.getStackAbility();
if (ability != null) {
for (Cost cost : ability.getCosts()) {
if (cost instanceof TapTargetCost && cost.isPaid()) {
TapTargetCost tapCost = (TapTargetCost) cost;
if (tapCost.getTarget().isChosen()) {
MageObjectReference mor = new MageObjectReference(sourcePermanent.getId(), sourcePermanent.getZoneChangeCounter(game), game);
Set<MageObjectReference> toAdd;
if (tappedMerfolkIds.get(mor) == null) {
toAdd = new HashSet<>();
} else {
toAdd = tappedMerfolkIds.get(mor);
}
for (UUID targetId : tapCost.getTarget().getTargets()) {
toAdd.add(new MageObjectReference(targetId, game));
}
tappedMerfolkIds.put(mor, toAdd);
break;
}
}
}
}
}
}
}
}
}
@Override
public void reset() {
super.reset();
tappedMerfolkIds.clear();
}
}

View file

@ -0,0 +1,72 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.w;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.condition.common.AttackedThisStepCondition;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase;
import mage.filter.StaticFilters;
import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
* @author L_J
*/
public class WarriorsStand extends CardImpl {
public WarriorsStand(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Cast Warrior's Stand only during the declare attackers step and only if you've been attacked this step.
Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
"Cast {this} only during the declare attackers step and only if you've been attacked this step."
);
ability.addWatcher(new PlayerAttackedStepWatcher());
this.addAbility(ability);
// Creatures you control get +2/+2 until end of turn.
this.getSpellAbility().addEffect(new BoostControlledEffect(2, 2, Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE, false));
}
public WarriorsStand(final WarriorsStand card) {
super(card);
}
@Override
public WarriorsStand copy() {
return new WarriorsStand(this);
}
}

View file

@ -0,0 +1,125 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.w;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.combat.CantAttackBlockUnlessPaysSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author emerald000 & L_J
*/
public class WhipgrassEntangler extends CardImpl {
public WhipgrassEntangler(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.CLERIC);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// {1}{W}: Until end of turn, target creature gains "This creature can't attack or block unless its controller pays {1} for each Cleric on the battlefield."
Ability abilityToGain = new SimpleStaticAbility(Zone.BATTLEFIELD, new WhipgrassEntanglerCantAttackUnlessYouPayEffect());
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new GainAbilityTargetEffect(abilityToGain, Duration.EndOfTurn).setText("Until end of turn, target creature gains \"This creature can't attack or block unless its controller pays {1} for each Cleric on the battlefield.\""),
new ManaCostsImpl("{1}{W}"));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public WhipgrassEntangler(final WhipgrassEntangler card) {
super(card);
}
@Override
public WhipgrassEntangler copy() {
return new WhipgrassEntangler(this);
}
}
class WhipgrassEntanglerCantAttackUnlessYouPayEffect extends CantAttackBlockUnlessPaysSourceEffect {
private static final FilterPermanent filter = new FilterPermanent("Cleric on the battlefield");
static {
filter.add(new SubtypePredicate(SubType.CLERIC));
}
WhipgrassEntanglerCantAttackUnlessYouPayEffect() {
super(new ManaCostsImpl("{0}"), RestrictType.ATTACK_AND_BLOCK);
staticText = "This creature can't attack or block unless its controller pays {1} for each Cleric on the battlefield";
}
WhipgrassEntanglerCantAttackUnlessYouPayEffect(WhipgrassEntanglerCantAttackUnlessYouPayEffect effect) {
super(effect);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return source.getSourceId().equals(event.getSourceId());
}
@Override
public ManaCosts getManaCostToPay(GameEvent event, Ability source, Game game) {
Permanent sourceObject = game.getPermanent(source.getSourceId());
if (sourceObject != null) {
int payment = new PermanentsOnBattlefieldCount(filter).calculate(game, source, this);
if (payment > 0) {
return new ManaCostsImpl<>("{" + payment + '}');
}
}
return null;
}
@Override
public WhipgrassEntanglerCantAttackUnlessYouPayEffect copy() {
return new WhipgrassEntanglerCantAttackUnlessYouPayEffect(this);
}
}

View file

@ -8,6 +8,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
public class WickedReward extends CardImpl {
@ -19,6 +20,7 @@ public class WickedReward extends CardImpl {
//Target creature gets +4/+2 until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(4, 2, Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
public WickedReward(WickedReward other){

View file

@ -0,0 +1,69 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.w;
import java.util.UUID;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.abilities.effects.common.continuous.LoseAbilityAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.mageobject.AbilityPredicate;
/**
*
* @author L_J
*/
public class WindShear extends CardImpl {
private static final FilterAttackingCreature filter = new FilterAttackingCreature("Attacking creatures with flying");
static {
filter.add(new AbilityPredicate(FlyingAbility.class));
}
public WindShear(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{G}");
// Attacking creatures with flying get -2/-2 and lose flying until end of turn.
this.getSpellAbility().addEffect(new BoostAllEffect(-2, -2, Duration.EndOfTurn, filter, false).setText("Attacking creatures with flying get -2/-2"));
this.getSpellAbility().addEffect(new LoseAbilityAllEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, filter).setText("and lose flying until end of turn"));
}
public WindShear(final WindShear card) {
super(card);
}
@Override
public WindShear copy() {
return new WindShear(this);
}
}

View file

@ -0,0 +1,133 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.w;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author L_J
*/
public class WoodElemental extends CardImpl {
public WoodElemental(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
this.subtype.add(SubType.ELEMENTAL);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// As Wood Elemental enters the battlefield, sacrifice any number of untapped Forests.
this.addAbility(new AsEntersBattlefieldAbility(new WoodElementalEffect()));
// Wood Elemental's power and toughness are each equal to the number of Forests sacrificed as it entered the battlefield.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the number of Forests sacrificed as it entered the battlefield")));
}
public WoodElemental(final WoodElemental card) {
super(card);
}
@Override
public WoodElemental copy() {
return new WoodElemental(this);
}
}
class WoodElementalEffect extends OneShotEffect {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Forests you control");
static {
filter.add(Predicates.not(new TappedPredicate()));
filter.add(new SubtypePredicate(SubType.FOREST));
}
public WoodElementalEffect() {
super(Outcome.Sacrifice);
staticText = "sacrifice any number of untapped Forests";
}
public WoodElementalEffect(final WoodElementalEffect effect) {
super(effect);
}
@Override
public WoodElementalEffect copy() {
return new WoodElementalEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Card sourceCard = game.getCard(source.getSourceId());
if (controller != null && sourceCard != null) {
Target target = new TargetControlledPermanent(0, Integer.MAX_VALUE, filter, true);
if (target.canChoose(source.getSourceId(), source.getControllerId(), game)
&& controller.chooseTarget(Outcome.Detriment, target, source, game)) {
if (!target.getTargets().isEmpty()) {
int sacrificedForests = target.getTargets().size();
game.informPlayers(controller.getLogName() + " sacrifices " + sacrificedForests + " untapped Forests for " + sourceCard.getLogName());
for (UUID targetId : target.getTargets()) {
Permanent targetPermanent = game.getPermanent(targetId);
if (targetPermanent != null) {
targetPermanent.sacrifice(source.getSourceId(), game);
}
}
game.addEffect(new SetPowerToughnessSourceEffect(sacrificedForests, sacrificedForests, Duration.Custom, SubLayer.SetPT_7b), source);
return true;
}
}
}
return false;
}
}

Some files were not shown because too many files have changed in this diff Show more