1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-03-30 17:00:10 -09:00

13 new cards

[BOK] Akki Blizzard Herder / Crack the Earth
[CHK] Commune with Nature / Otherworldly Journey / Peer Through Depths / Rag Dealer / Reciprocate
[CON] Faerie Mechanist / Giltspire Avenger
[PLC] DuneriderOutlaw
[ROE] Ancient Stirrings
[SOK] Freed from the Real]
[TSB] WhirlingDervish

Some small fixes or refactoring
Aura of Dominion / Hikari Twilight Guardian / Wicked Akuba / Claustrophobia / Crab Umbra / Descendant of Soramaro

Framework changes
PlayerDamagedByWatcher - replaced by the new PlayerDamagedBySourceWatcher
PlayerDamagedBySource - new watcher which tracks what sources damged a player
DealtDamageToAnOpponent - new condition
LookLibraryControllerEffect - reworked to be usable with LookLibraryAndPickControllerEffect
LookLibraryAndPickControllerEffect - new effect to handle draw and pick effects
TapEnchantedEffect - new
UntapEnchantedEffect - new
ReturnFromExileEffect - added constructor rule text support
SacrificeAllEffect - fixed missing rule text creation
GameImpl - added the creation of the new PlayerDamagedBySource watcher for each player
This commit is contained in:
LevelX 2012-01-12 08:11:32 +01:00
parent dfffdfcf8c
commit 6b0f04d03f
28 changed files with 1734 additions and 161 deletions

View file

@ -0,0 +1,71 @@
/*
* 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.sets.betrayersofkamigawa;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageInt;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.effects.common.SacrificeAllEffect;
import mage.cards.CardImpl;
import mage.filter.common.FilterControlledPermanent;
/**
*
* @author Loki
*/
public class AkkiBlizzardHerder extends CardImpl<AkkiBlizzardHerder> {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("land");
static {
filter.getCardType().add(CardType.LAND);
}
public AkkiBlizzardHerder(UUID ownerId) {
super(ownerId, 91, "Akki Blizzard-Herder", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.expansionSetCode = "BOK";
this.subtype.add("Goblin");
this.subtype.add("Shaman");
this.color.setRed(true);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// When Akki Blizzard-Herder dies, each player sacrifices a land.
this.addAbility(new DiesTriggeredAbility(new SacrificeAllEffect(filter)));
}
public AkkiBlizzardHerder(final AkkiBlizzardHerder card) {
super(card);
}
@Override
public AkkiBlizzardHerder copy() {
return new AkkiBlizzardHerder(this);
}
}

View file

@ -0,0 +1,62 @@
/*
* 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 LIAB8LE 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.sets.betrayersofkamigawa;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.abilities.effects.common.SacrificeAllEffect;
import mage.cards.CardImpl;
import mage.filter.common.FilterControlledPermanent;
/**
*
* @author LevelX
*/
public class CrackTheEarth extends CardImpl<CrackTheEarth> {
public CrackTheEarth(UUID ownerId) {
super(ownerId, 98, "Crack the Earth", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{R}");
this.expansionSetCode = "BOK";
this.color.setRed(true);
// Each player sacrifices a permanent.
this.getSpellAbility().addEffect(new SacrificeAllEffect(1, new FilterControlledPermanent("permanent to sacrifice")));
}
public CrackTheEarth(final CrackTheEarth card) {
super(card);
}
@Override
public CrackTheEarth copy() {
return new CrackTheEarth(this);
}
}

View file

@ -39,6 +39,8 @@ import mage.abilities.costs.common.TapTargetCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.UntapEnchantedEffect;
import mage.abilities.effects.common.UntapTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.filter.Filter;
@ -72,7 +74,7 @@ public class AuraOfDominion extends CardImpl<AuraOfDominion> {
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Constants.Outcome.Untap));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
Ability ability = new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new AuraOfDominionEffect(), new GenericManaCost(1));
Ability ability = new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new UntapEnchantedEffect(), new GenericManaCost(1));
ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false)));
this.addAbility(ability);
}
@ -86,34 +88,4 @@ public class AuraOfDominion extends CardImpl<AuraOfDominion> {
return new AuraOfDominion(this);
}
}
class AuraOfDominionEffect extends OneShotEffect<AuraOfDominionEffect> {
AuraOfDominionEffect() {
super(Constants.Outcome.Untap);
staticText = "untap enchanted creature";
}
AuraOfDominionEffect(final AuraOfDominionEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
Permanent attach = game.getPermanent(permanent.getAttachedTo());
if (attach != null) {
attach.untap(game);
return true;
}
}
return false;
}
@Override
public AuraOfDominionEffect copy() {
return new AuraOfDominionEffect(this);
}
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright 2011 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.sets.championsofkamigawa;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.abilities.effects.common.LookLibraryControllerEffect;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
/**
*
* @author LevelX
*/
public class CommuneWithNature extends CardImpl<CommuneWithNature> {
private final static FilterCard filter = new FilterCard("creature card");
static {
filter.getCardType().add(CardType.CREATURE);
}
public CommuneWithNature (UUID ownerId) {
super(ownerId, 204, "Commune with Nature", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{G}");
this.expansionSetCode = "CHK";
this.color.setGreen(true);
// Look at the top five cards of your library. You may reveal a creature card from among them and put it into your hand. Put the rest on the bottom of your library in any order.
this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect(new StaticValue(5), false, new StaticValue(1), filter, false));
}
public CommuneWithNature (final CommuneWithNature card) {
super(card);
}
@Override
public CommuneWithNature copy() {
return new CommuneWithNature(this);
}
}

View file

@ -41,9 +41,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromExileEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.filter.Filter;
import mage.filter.FilterCard;
import mage.filter.FilterSpell;
import mage.filter.common.FilterSpiritOrArcaneCard;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -94,7 +91,7 @@ class HikariTwilightGuardianEffect extends OneShotEffect<HikariTwilightGuardianE
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
if (permanent.moveToExile(source.getSourceId(), "Hikari, Twilight Guardian Exile", source.getId(), game)) {
if (permanent.moveToExile(source.getSourceId(), "Hikari, Twilight Guardian", source.getId(), game)) {
//create delayed triggered ability
HikariTwilightGuardianDelayedTriggeredAbility delayedAbility = new HikariTwilightGuardianDelayedTriggeredAbility(source.getSourceId());
delayedAbility.setSourceId(source.getSourceId());

View file

@ -0,0 +1,141 @@
/*
* 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.sets.championsofkamigawa;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromExileEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.counters.CounterType;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
* @author LevelX
*/
public class OtherworldlyJourney extends CardImpl<OtherworldlyJourney> {
public OtherworldlyJourney(UUID ownerId) {
super(ownerId, 37, "Otherworldly Journey", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{W}");
this.expansionSetCode = "CHK";
this.color.setWhite(true);
// Exile target creature. At the beginning of the next end step, return that card to the battlefield under its owner's control with a +1/+1 counter on it.
this.getSpellAbility().addEffect(new OtherworldlyJourneyEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
public OtherworldlyJourney(final OtherworldlyJourney card) {
super(card);
}
@Override
public OtherworldlyJourney copy() {
return new OtherworldlyJourney(this);
}
}
class OtherworldlyJourneyEffect extends OneShotEffect<OtherworldlyJourneyEffect> {
private static final String effectText = "Exile target creature. At the beginning of the next end step, return that card to the battlefield under its owner's control with a +1/+1 counter on it";
OtherworldlyJourneyEffect ( ) {
super(Constants.Outcome.Benefit);
staticText = effectText;
}
OtherworldlyJourneyEffect(OtherworldlyJourneyEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
if (permanent.moveToExile(source.getSourceId(), "Otherworldly Journey", source.getId(), game)) {
ExileZone exile = game.getExile().getExileZone(source.getSourceId());
// only if permanent is in exile (tokens would be stop to exist)
if (exile != null && !exile.isEmpty()) {
//create delayed triggered ability
OtherworldlyJourneyDelayedTriggeredAbility delayedAbility = new OtherworldlyJourneyDelayedTriggeredAbility(source.getSourceId());
delayedAbility.setSourceId(source.getSourceId());
delayedAbility.setControllerId(source.getControllerId());
AddCountersTargetEffect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance());
effect.setTargetPointer(new FixedTarget(source.getFirstTarget()));
delayedAbility.addEffect(effect);
game.addDelayedTriggeredAbility(delayedAbility);
}
return true;
}
}
return false;
}
@Override
public OtherworldlyJourneyEffect copy() {
return new OtherworldlyJourneyEffect(this);
}
}
class OtherworldlyJourneyDelayedTriggeredAbility extends DelayedTriggeredAbility<OtherworldlyJourneyDelayedTriggeredAbility> {
OtherworldlyJourneyDelayedTriggeredAbility ( UUID exileId ) {
super(new ReturnFromExileEffect(exileId, Constants.Zone.BATTLEFIELD, "return that card to the battlefield under its owner's control with a +1/+1 counter on it"));
}
OtherworldlyJourneyDelayedTriggeredAbility(OtherworldlyJourneyDelayedTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.END_TURN_STEP_PRE) {
return true;
}
return false;
}
@Override
public OtherworldlyJourneyDelayedTriggeredAbility copy() {
return new OtherworldlyJourneyDelayedTriggeredAbility(this);
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright 2011 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.sets.championsofkamigawa;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.cards.CardImpl;
import mage.filter.Filter.ComparisonScope;
import mage.filter.FilterCard;
/**
*
* @author LevelX
*/
public class PeerThroughDepths extends CardImpl<PeerThroughDepths> {
private final static FilterCard filter = new FilterCard("instant or sorcery card");
static {
filter.getCardType().add(CardType.SORCERY);
filter.getCardType().add(CardType.INSTANT);
filter.setNotScopeCardType(ComparisonScope.Any);
}
public PeerThroughDepths (UUID ownerId) {
super(ownerId, 78, "Peer Through Depths", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U}");
this.expansionSetCode = "CHK";
this.subtype.add("Arcane");
this.color.setBlue(true);
// Look at the top five cards of your library. You may reveal an instant or sorcery card from among them and put it into your hand.
// Put the rest on the bottom of your library in any order.
this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect(new StaticValue(5), false, new StaticValue(1), filter, false));
}
public PeerThroughDepths (final PeerThroughDepths card) {
super(card);
}
@Override
public PeerThroughDepths copy() {
return new PeerThroughDepths(this);
}
}

View file

@ -0,0 +1,156 @@
/*
* 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.sets.championsofkamigawa;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Outcome;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.BushidoAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInGraveyard;
/**
*
* @author LevelX
*/
public class RagDealer extends CardImpl<RagDealer> {
protected static final FilterCard filter = new FilterCard("up to three target cards from a single graveyard");
public RagDealer (UUID ownerId) {
super(ownerId, 138, "Rag Dealer", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{B}");
this.expansionSetCode = "CHK";
this.subtype.add("Human");
this.subtype.add("Rogue");
this.color.setBlack(true);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {2}{B}, {T}: Exile up to three target cards from a single graveyard.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RagDealerExileEffect(), new ManaCostsImpl("{2}{B}"));
ability.addCost(new TapSourceCost());
TargetPlayer target = new TargetPlayer();
target.setTargetName("player from which graveyard you want to exile the cards");
ability.addTarget(target);
ability.addTarget(new TargetCardInGraveyard(0,3,filter));
this.addAbility(ability);
}
public RagDealer (final RagDealer card) {
super(card);
}
@Override
public RagDealer copy() {
return new RagDealer(this);
}
}
class RagDealerTargetCardsInGraveyard extends TargetCard<RagDealerTargetCardsInGraveyard> {
public RagDealerTargetCardsInGraveyard(int minNumTargets, int maxNumTargets, FilterCard filter) {
super(minNumTargets, maxNumTargets, Constants.Zone.GRAVEYARD, filter);
this.targetName = "up to three target cards from a single graveyard";
}
public RagDealerTargetCardsInGraveyard(final RagDealerTargetCardsInGraveyard target) {
super(target);
}
@Override
public boolean canTarget(UUID id, Ability source, Game game) {
Player player = game.getPlayer(source.getTargets().getFirstTarget());
if (player != null) {
filter.getOwnerId().clear();
filter.getOwnerId().add(player.getId());
return super.canTarget(id, source, game);
}
return false;
}
@Override
public RagDealerTargetCardsInGraveyard copy() {
return new RagDealerTargetCardsInGraveyard(this);
}
}
class RagDealerExileEffect extends OneShotEffect<RagDealerExileEffect> {
public RagDealerExileEffect() {
super(Outcome.Exile);
}
public RagDealerExileEffect(final RagDealerExileEffect effect) {
super(effect);
}
@Override
public RagDealerExileEffect copy() {
return new RagDealerExileEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Target targetCards = source.getTargets().get(1);
if (targetCards != null) {
for (UUID targetID : targetCards.getTargets()) {
Card card = game.getCard(targetID);
if (card != null) {
card.moveToExile(null, "", source.getId(), game);
}
}
return true;
}
return false;
}
@Override
public String getText(Mode mode) {
return "Exile " + mode.getTargets().get(1).getTargetName();
}
}

View file

@ -0,0 +1,130 @@
/*
* 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.sets.championsofkamigawa;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.PlayerDamagedBySourceWatcher;
/**
* @author LevelX
*/
public class Reciprocate extends CardImpl<Reciprocate> {
public Reciprocate(UUID ownerId) {
super(ownerId, 40, "Reciprocate", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{W}");
this.expansionSetCode = "CHK";
this.color.setWhite(true);
// Exile target creature that dealt damage to you this turn.
this.getSpellAbility().addEffect(new ExileTargetEffect());
this.getSpellAbility().addTarget(new ReciprocateTarget());
}
public Reciprocate(final Reciprocate card) {
super(card);
}
@Override
public Reciprocate copy() {
return new Reciprocate(this);
}
}
class ReciprocateTarget<T extends TargetCreaturePermanent<T>> extends TargetPermanent<TargetCreaturePermanent<T>> {
public ReciprocateTarget() {
super(1, 1, new FilterCreaturePermanent(), false);
targetName = "creature that dealt damage to you this turn";
}
public ReciprocateTarget(final ReciprocateTarget target) {
super(target);
}
@Override
public boolean canTarget(UUID id, Ability source, Game game) {
PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource",source.getControllerId());
if (watcher != null && watcher.damageSources.contains(id)) {
return super.canTarget(id, source, game);
}
return false;
}
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game);
Set<UUID> possibleTargets = new HashSet<UUID>();
PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId);
for (UUID targetId : availablePossibleTargets) {
Permanent permanent = game.getPermanent(targetId);
if(permanent != null && watcher != null && watcher.damageSources.contains(targetId)){
possibleTargets.add(targetId);
}
}
return possibleTargets;
}
@Override
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
int remainingTargets = this.minNumberOfTargets - targets.size();
if (remainingTargets == 0)
return true;
int count = 0;
MageObject targetSource = game.getObject(sourceId);
PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId);
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)
&& watcher != null && watcher.damageSources.contains(permanent.getId())) {
count++;
if (count >= remainingTargets)
return true;
}
}
return false;
}
@Override
public ReciprocateTarget copy() {
return new ReciprocateTarget(this);
}
}

View file

@ -33,16 +33,17 @@ import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ColoredManaCost;
//import mage.abilities.effects.common.continious.GainAbilitySourceEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.target.TargetPlayer;
import mage.target.common.TargetOpponent;
import mage.watchers.common.PlayerDamagedByWatcher;
import mage.watchers.common.PlayerDamagedBySourceWatcher;
/**
*
@ -63,8 +64,6 @@ public class WickedAkuba extends CardImpl<WickedAkuba> {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseLifeTargetEffect(1), new ColoredManaCost(Constants.ColoredManaSymbol.B));
ability.addTarget(new WickedAkubaTarget());
this.addAbility(ability);
// watcher to know if player was damaged by this Wicked Akuba
this.addWatcher(new PlayerDamagedByWatcher());
}
public WickedAkuba(final WickedAkuba card) {
@ -78,7 +77,7 @@ public class WickedAkuba extends CardImpl<WickedAkuba> {
}
class WickedAkubaTarget extends TargetPlayer<TargetOpponent> {
class WickedAkubaTarget extends TargetPlayer<WickedAkubaTarget> {
public WickedAkubaTarget() {
super();
@ -92,30 +91,39 @@ class WickedAkubaTarget extends TargetPlayer<TargetOpponent> {
@Override
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
filter.getPlayerId().clear();
PlayerDamagedByWatcher watcher = (PlayerDamagedByWatcher) game.getState().getWatchers().get("PlayerDamagedByWatcher", sourceId);
if (watcher != null) {
for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()){
if (watcher.damagedPlayers.contains(playerId))
filter.getPlayerId().add(playerId);
}
if (filter.getPlayerId().isEmpty()) // neccessary because empty playerId filter allows all players
return false;
UUID source = null;
MageObject targetSource = game.getObject(sourceId);
if (targetSource instanceof StackAbility) {
StackAbility stackAbility = (StackAbility) targetSource;
source = stackAbility.getSourceId();
}
if (targetSource instanceof Permanent) {
Permanent permanent = (Permanent) targetSource;
source = permanent.getId();
}
if (source != null) {
for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()){
PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", playerId);
if (watcher != null && watcher.damageSources.contains(source))
filter.getPlayerId().add(playerId);
}
}
if (filter.getPlayerId().isEmpty()) // neccessary because empty playerId filter allows all players
return false;
return super.canChoose(sourceId, sourceControllerId, game);
}
@Override
public boolean canTarget(UUID id, Ability source, Game game) {
filter.getPlayerId().clear();
PlayerDamagedByWatcher watcher = (PlayerDamagedByWatcher) game.getState().getWatchers().get("PlayerDamagedByWatcher", source.getSourceId());
if (watcher != null) {
for (UUID playerId: game.getPlayer(source.getControllerId()).getInRange()){
if (watcher.damagedPlayers.contains(playerId))
filter.getPlayerId().add(playerId);
}
if (filter.getPlayerId().isEmpty()) // neccessary because empty playerId filter allows all players
return false;
}
for (UUID playerId: game.getPlayer(source.getControllerId()).getInRange()){
PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", playerId);
if (watcher != null && watcher.damageSources.contains(source.getSourceId()))
filter.getPlayerId().add(playerId);
}
if (filter.getPlayerId().isEmpty()) // neccessary because empty playerId filter allows all players
return false;
return super.canTarget(id, source, game);
}

View file

@ -0,0 +1,77 @@
/*
* 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.sets.conflux;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
/**
*
* @author LevelX
*/
public class FaerieMechanist extends CardImpl<FaerieMechanist> {
private final static FilterCard filter = new FilterCard("artifact card");
static {
filter.getCardType().add(CardType.ARTIFACT);
}
public FaerieMechanist(UUID ownerId) {
super(ownerId, 27, "Faerie Mechanist", Rarity.COMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{U}");
this.expansionSetCode = "CON";
this.color.setBlue(true);
this.subtype.add("Faerie");
this.subtype.add("Artificer");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Faerie Mechanist enters the battlefield, look at the top three cards of your library.
// You may reveal an artifact card from among them and put it into your hand. Put the rest on the bottom of your library in any order.
this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect(new StaticValue(3), false, new StaticValue(1), filter, false)));
}
public FaerieMechanist(final FaerieMechanist card) {
super(card);
}
@Override
public FaerieMechanist copy() {
return new FaerieMechanist(this);
}
}

View file

@ -0,0 +1,149 @@
/*
* 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.sets.conflux;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.Constants.Zone;
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.common.DestroyTargetEffect;
import mage.abilities.keyword.ExaltedAbility;
import mage.cards.CardImpl;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.PlayerDamagedBySourceWatcher;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class GiltspireAvenger extends CardImpl<GiltspireAvenger> {
public GiltspireAvenger(UUID ownerId) {
super(ownerId, 108, "Giltspire Avenger", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{G}{W}{U}");
this.expansionSetCode = "CON";
this.subtype.add("Human");
this.subtype.add("Soldier");
this.color.setGreen(true);
this.color.setWhite(true);
this.color.setBlue(true);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.)
this.addAbility(new ExaltedAbility());
// {T}: Destroy target creature that dealt damage to you this turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new TapSourceCost());
ability.addTarget(new GiltspireAvengerTarget());
this.addAbility(ability);
}
public GiltspireAvenger(final GiltspireAvenger card) {
super(card);
}
@Override
public GiltspireAvenger copy() {
return new GiltspireAvenger(this);
}
}
class GiltspireAvengerTarget<T extends TargetCreaturePermanent<T>> extends TargetPermanent<TargetCreaturePermanent<T>> {
public GiltspireAvengerTarget() {
super(1, 1, new FilterCreaturePermanent(), false);
targetName = "creature that dealt damage to you this turn";
}
public GiltspireAvengerTarget(final GiltspireAvengerTarget target) {
super(target);
}
@Override
public boolean canTarget(UUID id, Ability source, Game game) {
PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource",source.getControllerId());
if (watcher != null && watcher.damageSources.contains(id)) {
return super.canTarget(id, source, game);
}
return false;
}
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game);
Set<UUID> possibleTargets = new HashSet<UUID>();
PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId);
for (UUID targetId : availablePossibleTargets) {
Permanent permanent = game.getPermanent(targetId);
if(permanent != null && watcher != null && watcher.damageSources.contains(targetId)){
possibleTargets.add(targetId);
}
}
return possibleTargets;
}
@Override
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
int remainingTargets = this.minNumberOfTargets - targets.size();
if (remainingTargets == 0)
return true;
int count = 0;
MageObject targetSource = game.getObject(sourceId);
PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId);
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)
&& watcher != null && watcher.damageSources.contains(permanent.getId())) {
count++;
if (count >= remainingTargets)
return true;
}
}
return false;
}
@Override
public GiltspireAvengerTarget copy() {
return new GiltspireAvengerTarget(this);
}
}

View file

@ -29,21 +29,17 @@ package mage.sets.innistrad;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Outcome;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.SkipEnchantedUntapEffect;
import mage.abilities.effects.common.TapEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
@ -65,7 +61,7 @@ public class Claustrophobia extends CardImpl<Claustrophobia> {
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// When Claustrophobia enters the battlefield, tap enchanted creature.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ClaustrophobiaEffect()));
this.addAbility(new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()));
// Enchanted creature doesn't untap during its controller's untap step.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SkipEnchantedUntapEffect()));
}
@ -79,31 +75,3 @@ public class Claustrophobia extends CardImpl<Claustrophobia> {
return new Claustrophobia(this);
}
}
class ClaustrophobiaEffect extends OneShotEffect<ClaustrophobiaEffect> {
ClaustrophobiaEffect() {
super(Constants.Outcome.Tap);
staticText = "tap enchanted creature";
}
ClaustrophobiaEffect(final ClaustrophobiaEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent enchantment = game.getPermanent(source.getSourceId());
if (enchantment != null && enchantment.getAttachedTo() != null) {
Permanent permanent = game.getPermanent(enchantment.getAttachedTo());
if (permanent != null) {
return permanent.tap(game);
}
}
return false;
}
@Override
public ClaustrophobiaEffect copy() {
return new ClaustrophobiaEffect();
}
}

View file

@ -0,0 +1,86 @@
/*
* 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.sets.planarchaos;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.OnEventTriggeredAbility;
import mage.abilities.condition.common.DealtDamageToAnOpponent;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl;
import mage.counters.CounterType;
import mage.filter.FilterCard;
import mage.game.events.GameEvent;
/**
*
* @author LevelX
*/
public class DuneriderOutlaw extends CardImpl<DuneriderOutlaw> {
private static final String ruleText = "At the beginning of each end step, if {this} dealt damage to an opponent this turn, put a +1/+1 counter on it.";
private static final FilterCard filter = new FilterCard("green");
static {
filter.setColor(ObjectColor.GREEN);
filter.setUseColor(true);
}
public DuneriderOutlaw(UUID ownerId) {
super(ownerId, 86, "Dunerider Outlaw", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{B}{B}");
this.expansionSetCode = "PLC";
this.subtype.add("Human");
this.subtype.add("Rebel");
this.subtype.add("Rogue");
this.color.setBlack(true);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Protection from green
this.addAbility(new ProtectionAbility(filter));
// At the beginning of each end step, if Dunerider Outlaw dealt damage to an opponent this turn, put a +1/+1 counter on it.
TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each end step", true, new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
this.addAbility(new ConditionalTriggeredAbility(triggered, new DealtDamageToAnOpponent(), ruleText));
}
public DuneriderOutlaw(final DuneriderOutlaw card) {
super(card);
}
@Override
public DuneriderOutlaw copy() {
return new DuneriderOutlaw(this);
}
}

View file

@ -0,0 +1,72 @@
/*
* Copyright 2011 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.sets.riseoftheeldrazi;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
/**
*
* @author LevelX
*/
public class AncientStirrings extends CardImpl<AncientStirrings> {
private final static FilterCard filter = new FilterCard("colorless card");
static {
filter.setColorless(true);
filter.setUseColorless(true);
}
public AncientStirrings (UUID ownerId) {
super(ownerId, 174, "Ancient Stirrings", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{G}");
this.expansionSetCode = "ROE";
this.color.setGreen(true);
// Look at the top five cards of your library. You may reveal a colorless card from among them and put it into your hand.
// Then put the rest on the bottom of your library in any order. (Cards with no colored mana in their mana costs are colorless. Lands are also colorless.)
this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect(new StaticValue(5), false, new StaticValue(1), filter, false));
}
public AncientStirrings (final AncientStirrings card) {
super(card);
}
@Override
public AncientStirrings copy() {
return new AncientStirrings(this);
}
}

View file

@ -37,6 +37,7 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.UntapEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.TotemArmorAbility;
import mage.cards.CardImpl;
@ -65,7 +66,7 @@ public class CrabUmbra extends CardImpl<CrabUmbra> {
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// {2}{U}: Untap enchanted creature.
this.addAbility(new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new CrabUmbraEffect(), new ManaCostsImpl("{2}{U}")));
this.addAbility(new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new UntapEnchantedEffect(), new ManaCostsImpl("{2}{U}")));
this.addAbility(new TotemArmorAbility());
}
@ -77,34 +78,4 @@ public class CrabUmbra extends CardImpl<CrabUmbra> {
public CrabUmbra copy() {
return new CrabUmbra(this);
}
}
class CrabUmbraEffect extends OneShotEffect<CrabUmbraEffect> {
CrabUmbraEffect() {
super(Constants.Outcome.Untap);
staticText = "untap enchanted creature";
}
CrabUmbraEffect(final CrabUmbraEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
Permanent attach = game.getPermanent(permanent.getAttachedTo());
if (attach != null) {
attach.untap(game);
return true;
}
}
return false;
}
@Override
public CrabUmbraEffect copy() {
return new CrabUmbraEffect(this);
}
}
}

View file

@ -53,7 +53,7 @@ public class DescendantOfSoramaro extends CardImpl<DescendantOfSoramaro> {
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// {1}{U}: Look at the top X cards of your library, where X is the number of cards in your hand, then put them back in any order.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(new CardsInControllerHandCount(), false), new ManaCostsImpl("{1}{U}")));
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(new CardsInControllerHandCount()), new ManaCostsImpl("{1}{U}")));
}
public DescendantOfSoramaro(final DescendantOfSoramaro card) {

View file

@ -0,0 +1,77 @@
/*
* 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.sets.saviorsofkamigawa;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.TapEnchantedEffect;
import mage.abilities.effects.common.UntapEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author LevelX
*/
public class FreedFromTheReal extends CardImpl<FreedFromTheReal> {
public FreedFromTheReal(UUID ownerId) {
super(ownerId, 38, "Freed from the Real", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
this.expansionSetCode = "SOK";
this.color.setBlue(true);
this.subtype.add("Aura");
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Constants.Outcome.Untap));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// {U}: Tap enchanted creature.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapEnchantedEffect(), new ManaCostsImpl("{U}")));
// {U}: Untap enchanted creature.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapEnchantedEffect(), new ManaCostsImpl("{U}")));
}
public FreedFromTheReal(final FreedFromTheReal card) {
super(card);
}
@Override
public FreedFromTheReal copy() {
return new FreedFromTheReal(this);
}
}

View file

@ -0,0 +1,85 @@
/*
* 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.sets.timeshifted;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.OnEventTriggeredAbility;
import mage.abilities.condition.common.DealtDamageToAnOpponent;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl;
import mage.counters.CounterType;
import mage.filter.FilterCard;
import mage.game.events.GameEvent;
/**
*
* @author LevelX
*/
public class WhirlingDervish extends CardImpl<WhirlingDervish> {
private static final String ruleText = "At the beginning of each end step, if {this} dealt damage to an opponent this turn, put a +1/+1 counter on it.";
private static final FilterCard filter = new FilterCard("black");
static {
filter.setColor(ObjectColor.BLACK);
filter.setUseColor(true);
}
public WhirlingDervish(UUID ownerId) {
super(ownerId, 90, "Whirling Dervish", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{G}{G}");
this.expansionSetCode = "TSB";
this.subtype.add("Human");
this.subtype.add("Monk");
this.color.setGreen(true);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Protection from black
this.addAbility(new ProtectionAbility(filter));
// At the beginning of each end step, if Whirling Dervish dealt damage to an opponent this turn, put a +1/+1 counter on it.
TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each end step", true, new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
this.addAbility(new ConditionalTriggeredAbility(triggered, new DealtDamageToAnOpponent(), ruleText));
}
public WhirlingDervish(final WhirlingDervish card) {
super(card);
}
@Override
public WhirlingDervish copy() {
return new WhirlingDervish(this);
}
}

View file

@ -0,0 +1,54 @@
/*
* 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.abilities.condition.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.game.Game;
import mage.watchers.common.PlayerDamagedBySourceWatcher;
/**
* @author LevelX
*/
public class DealtDamageToAnOpponent implements Condition {
public DealtDamageToAnOpponent() {
}
@Override
public boolean apply(Game game, Ability source) {
for (UUID opponentId: game.getOpponents(source.getControllerId())) {
PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", opponentId);
if (watcher != null && watcher.damageSources.contains(source.getSourceId()))
return true;
}
return false;
}
}

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.abilities.effects.common;
import mage.Constants.Outcome;
import mage.Constants.Zone;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
/**
*
* @author LevelX
*/
public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEffect {
protected FilterCard filter; // which kind of cards to reveal
protected DynamicValue numberToPick;
protected boolean revealPickedCards = true;
protected Zone targetPickedCards = Zone.HAND; // Hand, graveyard, library bottom, library top
protected int foundCardsToPick = 0;
public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick, FilterCard pickFilter, boolean putOnTop) {
super(numberOfCards, mayShuffleAfter, putOnTop);
this.numberToPick = numberToPick;
this.filter = pickFilter;
}
public LookLibraryAndPickControllerEffect(final LookLibraryAndPickControllerEffect effect) {
super(effect);
this.numberToPick = effect.numberToPick.clone();
this.filter = effect.filter.copy();
this.revealPickedCards = effect.revealPickedCards;
this.targetPickedCards = effect.targetPickedCards;
}
@Override
public LookLibraryAndPickControllerEffect copy() {
return new LookLibraryAndPickControllerEffect(this);
}
@Override
protected void cardLooked(Card card, Game game, Ability source) {
if (numberToPick.calculate(game, source) > 0 && filter.match(card))
++foundCardsToPick;
}
@Override
protected void actionWithSelectedCards(Cards cards, Game game, Ability source, String windowName) {
// You may reveal a creature card from among them and put it into your hand.
Player player = game.getPlayer(source.getControllerId());
if (player != null && foundCardsToPick > 0 && player.chooseUse(Outcome.DrawCard, "Do you wish to reveal "+filter.getMessage()+" and put it into your hand?", game)) {
FilterCard pickFilter = filter.copy();
pickFilter.setMessage(filter.getMessage()+" to reveal and put into your hand");
TargetCard target = new TargetCard(Zone.PICK, pickFilter);
if (player.choose(Outcome.DrawCard, cards, target, game)) {
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
card.moveToZone(targetPickedCards, source.getId(), game, false);
if (revealPickedCards) {
Cards reveal = new CardsImpl(Zone.OUTSIDE);
reveal.add(card);
player.revealCards(windowName, reveal, game);
}
}
}
}
}
@Override
public String getText(Mode mode) {
StringBuilder sb = new StringBuilder();
if (numberToPick.calculate(null, null) > 0) {
sb.append(". You may reveal a ");
sb.append(filter.getMessage()).append(" from among them and put it into your ").append(targetPickedCards.toString().toLowerCase());
sb.append(". Put the rest ");
if (putOnTop)
sb.append("back ");
else
sb.append("on the bottom of your library ");
sb.append("in any order");
}
// get text frame from super class and inject action text
return setText(mode, sb.toString());
}
}

View file

@ -52,35 +52,43 @@ import mage.target.TargetCard;
*/
public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryControllerEffect> {
private DynamicValue numberOfCards;
private boolean mayShuffleAfter;
protected DynamicValue numberOfCards;
protected boolean mayShuffleAfter = false;
protected boolean putOnTop = true; // if false on put back on bottom of library
public LookLibraryControllerEffect() {
this(1);
}
public LookLibraryControllerEffect(int numberOfCards) {
this(numberOfCards, false);
this(numberOfCards, false, true);
}
public LookLibraryControllerEffect(DynamicValue numberOfCards) {
this(numberOfCards, false);
}
public LookLibraryControllerEffect(int numberOfCards, boolean mayShuffleAfter) {
this(new StaticValue(numberOfCards), mayShuffleAfter);
this(numberOfCards, false, true);
}
public LookLibraryControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter) {
public LookLibraryControllerEffect(int numberOfCards, boolean mayShuffleAfter) {
this(numberOfCards, mayShuffleAfter, true);
}
public LookLibraryControllerEffect(int numberOfCards, boolean mayShuffleAfter, boolean putOnTop) {
this(new StaticValue(numberOfCards), mayShuffleAfter, putOnTop);
}
public LookLibraryControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, boolean putOnTop) {
super(Outcome.Benefit);
this.numberOfCards = numberOfCards;
this.mayShuffleAfter = mayShuffleAfter;
}
this.putOnTop = putOnTop;
}
public LookLibraryControllerEffect(final LookLibraryControllerEffect effect) {
super(effect);
this.numberOfCards = effect.numberOfCards.clone();
this.mayShuffleAfter = effect.mayShuffleAfter;
this.putOnTop = effect.putOnTop;
}
@Override
@ -92,6 +100,7 @@ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryContro
@Override
public boolean apply(Game game, Ability source) {
String windowName ="Reveal";
if (source instanceof SpellAbility) {
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard != null)
@ -108,25 +117,58 @@ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryContro
return false;
}
// take cards from library and look at them
Cards cards = new CardsImpl(Zone.PICK);
int count = Math.min(player.getLibrary().size(), this.numberOfCards.calculate(game, source));
for (int i = 0; i < count; i++) {
Card card = player.getLibrary().removeFromTop(game);
if (card != null) {
cards.add(card);
this.cardLooked(card, game, source);
game.setZone(card.getId(), Zone.PICK);
}
}
player.lookAtCards(windowName, cards, game);
TargetCard target = new TargetCard(Zone.PICK, new FilterCard("card to put on your library (last chosen will be on top)"));
this.actionWithSelectedCards(cards, game, source, windowName);
this.putCardsBack(source, player, cards, game);
this.mayShuffle(player, game);
return true;
}
/**
*
* @param card
* @param game
* @param source
*/
protected void cardLooked(Card card, Game game, Ability source) {
return;
}
protected void actionWithSelectedCards(Cards cards, Game game, Ability source, String windowName) {
return;
}
/**
* Put the rest of the cards back to library
*
* @param source
* @param player
* @param cards
* @param game
*/
protected void putCardsBack(Ability source, Player player, Cards cards, Game game) {
TargetCard target = new TargetCard(Zone.PICK, new FilterCard(this.getPutBackText()));
target.setRequired(true);
while (cards.size() > 1) {
player.choose(Outcome.Neutral, cards, target, game);
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
card.moveToZone(Zone.LIBRARY, source.getId(), game, true);
card.moveToZone(Zone.LIBRARY, source.getId(), game, putOnTop);
}
target.clearChosen();
}
@ -134,19 +176,41 @@ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryContro
Card card = cards.get(cards.iterator().next(), game);
card.moveToZone(Zone.LIBRARY, source.getId(), game, true);
}
}
/**
* Check to shuffle library if allowed
* @param player
* @param game
*/
protected void mayShuffle(Player player, Game game) {
if (this.mayShuffleAfter) {
if (player.chooseUse(Constants.Outcome.Benefit, "Shuffle you library?", game)) {
player.shuffleLibrary(game);
}
}
return true;
}
protected String getPutBackText() {
StringBuilder sb = new StringBuilder("card to put ");
if (putOnTop)
sb.append("on your library (last chosen will be on top)");
else
sb.append("on bottom of your library (last chosen will be on bottom)");
return sb.toString();
}
@Override
public String getText(Mode mode) {
int number = numberOfCards.calculate(null, null);
return setText(mode, "");
}
public String setText(Mode mode, String middleText) {
int numberLook = numberOfCards.calculate(null, null);
// int numberPick = numberToPick.calculate(null, null) ;
StringBuilder sb = new StringBuilder("Look at the top ");
switch(number) {
switch(numberLook) {
case 0:
sb.append(" X ");
break;
@ -166,20 +230,29 @@ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryContro
sb.append("five");
break;
default:
sb.append(number);
sb.append(numberLook);
break;
}
if (number != 1)
if (numberLook != 1)
sb.append(" cards ");
sb.append("of your Library");
if (number == 0)
if (numberLook == 0)
sb.append(", where {X} is the number of cards ").append(numberOfCards.getMessage());
if (number > 1)
sb.append(", then put them back in any order");
if (!middleText.isEmpty()) {
sb.append(middleText);
}
else {
if (numberLook > 1)
sb.append(", then put them back in any order");
}
if (this.mayShuffleAfter)
sb.append(". You may shuffle your library");
return sb.toString();
}
}

View file

@ -51,12 +51,17 @@ public class ReturnFromExileEffect extends OneShotEffect<ReturnFromExileEffect>
this(exileId, zone, false);
}
public ReturnFromExileEffect(UUID exileId, Zone zone, String text) {
this(exileId, zone, false);
staticText = text;
}
public ReturnFromExileEffect(UUID exileId, Zone zone, boolean tapped) {
super(Outcome.PutCardInPlay);
this.exileId = exileId;
this.zone = zone;
this.tapped = tapped;
setText();
setText();
}
public ReturnFromExileEffect(final ReturnFromExileEffect effect) {

View file

@ -58,6 +58,7 @@ public class SacrificeAllEffect extends OneShotEffect<SacrificeAllEffect> {
super(Outcome.Sacrifice);
this.amount = amount;
this.filter = filter;
setText();
}
public SacrificeAllEffect(final SacrificeAllEffect effect) {

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.abilities.effects.common;
import mage.Constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author LevelX
*/
public class TapEnchantedEffect extends OneShotEffect<TapEnchantedEffect> {
public TapEnchantedEffect() {
super(Outcome.Tap);
staticText = "tap enchanted creature";
}
public TapEnchantedEffect(final TapEnchantedEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
Permanent attach = game.getPermanent(permanent.getAttachedTo());
if (attach != null) {
attach.tap(game);
return true;
}
}
return false;
}
@Override
public TapEnchantedEffect copy() {
return new TapEnchantedEffect(this);
}
}

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.abilities.effects.common;
import mage.Constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author LevelX
*/
public class UntapEnchantedEffect extends OneShotEffect<UntapEnchantedEffect> {
public UntapEnchantedEffect() {
super(Outcome.Untap);
staticText = "untap enchanted creature";
}
public UntapEnchantedEffect(final UntapEnchantedEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
Permanent attach = game.getPermanent(permanent.getAttachedTo());
if (attach != null) {
attach.untap(game);
return true;
}
}
return false;
}
@Override
public UntapEnchantedEffect copy() {
return new UntapEnchantedEffect(this);
}
}

View file

@ -72,6 +72,7 @@ import org.apache.log4j.Logger;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import mage.watchers.common.PlayerDamagedBySourceWatcher;
public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializable {
@ -490,8 +491,12 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
saveState();
}
state.getWatchers().add(new MorbidWatcher());
state.getWatchers().add(new CastSpellLastTurnWatcher());
for (UUID playerId: state.getPlayerList(startingPlayerId)) {
state.getWatchers().add(new PlayerDamagedBySourceWatcher(playerId));
}
state.getWatchers().add(new MorbidWatcher());
state.getWatchers().add(new CastSpellLastTurnWatcher());
//20100716 - 103.5
for (UUID playerId: state.getPlayerList(startingPlayerId)) {

View file

@ -37,32 +37,34 @@ import mage.game.events.GameEvent.EventType;
import mage.watchers.WatcherImpl;
/**
*
* Watcher stores whitch sources did damage to a player
*
* @author LevelX
*/
public class PlayerDamagedByWatcher extends WatcherImpl<PlayerDamagedByWatcher> {
public class PlayerDamagedBySourceWatcher extends WatcherImpl<PlayerDamagedBySourceWatcher> {
public List<UUID> damagedPlayers = new ArrayList<UUID>();
public List<UUID> damageSources = new ArrayList<UUID>();
public PlayerDamagedByWatcher() {
super("PlayerDamagedByWatcher", WatcherScope.CARD);
public PlayerDamagedBySourceWatcher(UUID playerId) {
super("PlayerDamagedBySource", WatcherScope.PLAYER);
setControllerId(playerId);
}
public PlayerDamagedByWatcher(final PlayerDamagedByWatcher watcher) {
public PlayerDamagedBySourceWatcher(final PlayerDamagedBySourceWatcher watcher) {
super(watcher);
this.damagedPlayers = watcher.damagedPlayers;
this.damageSources = watcher.damageSources;
}
@Override
public PlayerDamagedByWatcher copy() {
return new PlayerDamagedByWatcher(this);
public PlayerDamagedBySourceWatcher copy() {
return new PlayerDamagedBySourceWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == EventType.DAMAGED_PLAYER) {
if (sourceId.equals(event.getSourceId()) && !damagedPlayers.contains(event.getTargetId())) {
damagedPlayers.add(event.getTargetId());
if (event.getTargetId().equals(controllerId) && !damageSources.contains(event.getSourceId())) {
damageSources.add(event.getSourceId());
}
}
}
@ -70,6 +72,6 @@ public class PlayerDamagedByWatcher extends WatcherImpl<PlayerDamagedByWatcher>
@Override
public void reset() {
super.reset();
damagedPlayers.clear();
damageSources.clear();
}
}