Merge origin/master

This commit is contained in:
fireshoes 2016-05-23 18:39:13 -05:00
commit 3d0409e1bb
35 changed files with 2470 additions and 243 deletions

View file

@ -231,8 +231,11 @@ public enum UserStatsRepository {
outcome = 0.5;
}
ResultProtos.UserStatsProto player1StatsProto = getUserStatsProto(player1.getName(), matchEndTimeMs);
ResultProtos.UserStatsProto player2StatsProto = getUserStatsProto(player2.getName(), matchEndTimeMs);
// get players stats
UserStats player1Stats = getOrCreateUserStats(player1.getName(), tableEndTimeMs);
ResultProtos.UserStatsProto player1StatsProto = player1Stats.getProto();
UserStats player2Stats = getOrCreateUserStats(player2.getName(), tableEndTimeMs);
ResultProtos.UserStatsProto player2StatsProto = player2Stats.getProto();
ResultProtos.UserStatsProto.Builder player1StatsBuilder =
ResultProtos.UserStatsProto.newBuilder(player1StatsProto);
@ -305,8 +308,8 @@ public enum UserStatsRepository {
}
this.update(new UserStats(player1StatsBuilder.build(), matchEndTimeMs));
this.update(new UserStats(player2StatsBuilder.build(), matchEndTimeMs));
this.update(new UserStats(player1StatsBuilder.build(), player1Stats.getEndTimeMs()));
this.update(new UserStats(player2StatsBuilder.build(), player2Stats.getEndTimeMs()));
}
private void updateRating(
@ -351,16 +354,14 @@ public enum UserStatsRepository {
.setLastGameTimeMs(tableEndTimeMs);
}
private ResultProtos.UserStatsProto getUserStatsProto(String playerName, long endTimeMs) {
UserStats player1Stats = this.getUser(playerName);
ResultProtos.UserStatsProto player1StatsProto;
if (player1Stats != null) {
player1StatsProto = player1Stats.getProto();
} else {
player1StatsProto = ResultProtos.UserStatsProto.newBuilder().setName(playerName).build();
this.add(new UserStats(player1StatsProto, endTimeMs));
private UserStats getOrCreateUserStats(String playerName, long endTimeMs) {
UserStats userStats = this.getUser(playerName);
if (userStats == null) {
ResultProtos.UserStatsProto userStatsProto = ResultProtos.UserStatsProto.newBuilder().setName(playerName).build();
userStats = new UserStats(userStatsProto, endTimeMs);
this.add(userStats);
}
return player1StatsProto;
return userStats;
}
public void closeDB() {

View file

@ -0,0 +1,101 @@
/*
* 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.darksteel;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.dynamicvalue.common.PermanentsTargetOpponentControlsCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.common.FilterArtifactPermanent;
import mage.filter.predicate.other.OwnerIdPredicate;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.target.TargetPlayer;
/**
*
* @author wetterlicht
*/
public class BurdenOfGreed extends CardImpl {
public BurdenOfGreed(UUID ownerId) {
super(ownerId, 38, "Burden of Greed", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{3}{B}");
this.expansionSetCode = "DST";
// Target player loses 1 life for each tapped artifact he or she controls.
getSpellAbility().addTarget(new TargetPlayer());
getSpellAbility().addEffect(new LoseLifeTargetEffect(new BurdenOfGreedCount()));
}
public BurdenOfGreed(final BurdenOfGreed card) {
super(card);
}
@Override
public BurdenOfGreed copy() {
return new BurdenOfGreed(this);
}
}
class BurdenOfGreedCount implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
if (sourceAbility.getFirstTarget() == null) {
return 0;
}
FilterArtifactPermanent filter = new FilterArtifactPermanent();
filter.add(new TappedPredicate());
filter.add(new ControllerIdPredicate(sourceAbility.getFirstTarget()));
return game.getBattlefield().count(filter, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game);
}
@Override
public DynamicValue copy() {
return new BurdenOfGreedCount();
}
@Override
public String toString() {
return "1";
}
@Override
public String getMessage() {
return "tapped artifact he or she controls";
}
}

View file

@ -0,0 +1,90 @@
/*
* 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.darksteel;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.abilities.keyword.ShroudAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterControlledArtifactPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPlaneswalkerPermanent;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.AnotherPredicate;
/**
*
* @author wetterlicht
*/
public class DrillSkimmer extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("you control another artifact creature");
static {
filter.add(new AnotherPredicate());
filter.add(new CardTypePredicate(CardType.ARTIFACT));
}
public DrillSkimmer(UUID ownerId) {
super(ownerId, 118, "Drill-Skimmer", Rarity.COMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}");
this.expansionSetCode = "DST";
this.subtype.add("Thopter");
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Drill-Skimmer has shroud as long as you control another artifact creature.
Condition condition = new PermanentsOnTheBattlefieldCondition(filter, PermanentsOnTheBattlefieldCondition.CountType.MORE_THAN, 0);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new ConditionalContinuousEffect(new GainAbilitySourceEffect(ShroudAbility.getInstance(), Duration.WhileOnBattlefield),
condition, "{this} has shroud as long as you control another artifact creature.")));
}
public DrillSkimmer(final DrillSkimmer card) {
super(card);
}
@Override
public DrillSkimmer copy() {
return new DrillSkimmer(this);
}
}

View file

@ -0,0 +1,143 @@
/*
* 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.darksteel;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author wetterlicht
*/
public class DroolingOgre extends CardImpl {
public DroolingOgre(UUID ownerId) {
super(ownerId, 58, "Drooling Ogre", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.expansionSetCode = "DST";
this.subtype.add("Ogre");
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Whenever a player casts an artifact spell, that player gains control of Drooling Ogre.
this.addAbility(new DroolingOgreTriggeredAbility());
}
public DroolingOgre(final DroolingOgre card) {
super(card);
}
@Override
public DroolingOgre copy() {
return new DroolingOgre(this);
}
private static class DroolingOgreEffect extends OneShotEffect {
public DroolingOgreEffect() {
super(Outcome.GainControl);
this.staticText = "that player gains control of {this}";
}
private DroolingOgreEffect(DroolingOgreEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player newController = game.getPlayer(this.getTargetPointer().getFirst(game, source));
if (newController != null && controller != null && !controller.equals(newController)) {
ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, newController.getId());
effect.setTargetPointer(new FixedTarget(source.getSourceId()));
game.addEffect(effect, source);
return true;
}
return false;
}
@Override
public Effect copy() {
return new DroolingOgreEffect(this);
}
}
class DroolingOgreTriggeredAbility extends TriggeredAbilityImpl {
public DroolingOgreTriggeredAbility() {
super(Zone.BATTLEFIELD, new DroolingOgreEffect(), false);
}
public DroolingOgreTriggeredAbility(final DroolingOgreTriggeredAbility ability) {
super(ability);
}
@Override
public DroolingOgreTriggeredAbility copy() {
return new DroolingOgreTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell != null && spell.getCardType().contains(CardType.ARTIFACT)) {
this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getPlayerId()));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever a player casts an artifact spell, that player gains control of {this}.";
}
}
}

View file

@ -0,0 +1,100 @@
/*
* 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.darksteel;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.common.FilterArtifactPermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
/**
*
* @author wetterlicht
*/
public class EmissaryOfDespair extends CardImpl {
public EmissaryOfDespair(UUID ownerId) {
super(ownerId, 42, "Emissary of Despair", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{B}{B}");
this.expansionSetCode = "DST";
this.subtype.add("Spirit");
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever Emissary of Despair deals combat damage to a player, that player loses 1 life for each artifact he or she controls.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new LoseLifeTargetEffect(new EmissaryOfDespairCount()), false, true));
}
public EmissaryOfDespair(final EmissaryOfDespair card) {
super(card);
}
@Override
public EmissaryOfDespair copy() {
return new EmissaryOfDespair(this);
}
}
class EmissaryOfDespairCount implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
if (effect.getTargetPointer().getFirst(game, sourceAbility) == null) {
return 0;
}
FilterArtifactPermanent filter = new FilterArtifactPermanent();
filter.add(new ControllerIdPredicate(effect.getTargetPointer().getFirst(game, sourceAbility)));
return game.getBattlefield().count(filter, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game);
}
@Override
public DynamicValue copy() {
return new EmissaryOfDespairCount();
}
@Override
public String toString() {
return "1";
}
@Override
public String getMessage() {
return "artifact he or she controls";
}
}

View file

@ -0,0 +1,123 @@
/*
* 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.darksteel;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author wetterlicht
*/
public class MurderousSpoils extends CardImpl {
private static final FilterCreaturePermanent FILTER = new FilterCreaturePermanent("nonblack creature");
static {
FILTER.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK)));
}
public MurderousSpoils(UUID ownerId) {
super(ownerId, 48, "Murderous Spoils", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{5}{B}");
this.expansionSetCode = "DST";
// Destroy target nonblack creature. It can't be regenerated. You gain control of all Equipment that was attached to it.
this.getSpellAbility().addTarget(new TargetCreaturePermanent(FILTER));
this.getSpellAbility().addEffect(new MurderousSpoilsEffect());
}
public MurderousSpoils(final MurderousSpoils card) {
super(card);
}
@Override
public MurderousSpoils copy() {
return new MurderousSpoils(this);
}
}
class MurderousSpoilsEffect extends OneShotEffect {
public MurderousSpoilsEffect() {
super(Outcome.DestroyPermanent);
staticText = "Destroy target nonblack creature. It can't be regenerated. You gain control of all Equipment that was attached to it.";
}
public MurderousSpoilsEffect(final MurderousSpoilsEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent target = game.getPermanent(source.getFirstTarget());
if (target != null) {
List<Permanent> attachments = new ArrayList<Permanent>();
for (UUID uuid : target.getAttachments()) {
Permanent attached = game.getBattlefield().getPermanent(uuid);
if (attached.getSubtype().contains("Equipment")) {
attachments.add(attached);
}
}
for (Permanent p : attachments) {
ContinuousEffect gainControl = new GainControlTargetEffect(Duration.Custom);
gainControl.setTargetPointer(new FixedTarget(p, game));
game.addEffect(gainControl, source);
}
target.destroy(source.getId(), game, true);
return true;
}
return false;
}
@Override
public MurderousSpoilsEffect copy() {
return new MurderousSpoilsEffect(this);
}
}

View file

@ -0,0 +1,90 @@
/*
* 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.darksteel;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect;
import mage.abilities.effects.common.TapEnchantedEffect;
import mage.abilities.effects.common.UntapSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterArtifactCard;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInHand;
/**
*
* @author wetterlicht
*/
public class PsychicOverload extends CardImpl {
public PsychicOverload(UUID ownerId) {
super(ownerId, 28, "Psychic Overload", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}");
this.expansionSetCode = "DST";
this.subtype.add("Aura");
// Enchant permanent
TargetPermanent auraTarget = new TargetPermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// When Psychic Overload enters the battlefield, tap enchanted permanent.
this.addAbility(new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()));
// Enchanted permanent doesn't untap during its controller's untap step.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepEnchantedEffect()));
// Enchanted permanent has "Discard two artifact cards: Untap this permanent."
Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapSourceEffect(), new DiscardTargetCost(new TargetCardInHand(2, new FilterArtifactCard("two artifact cards"))));
Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA, Duration.WhileOnBattlefield, "Enchanted permanent has \"Discard two artifact cards: Untap this permanent.\"");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public PsychicOverload(final PsychicOverload card) {
super(card);
}
@Override
public PsychicOverload copy() {
return new PsychicOverload(this);
}
}

View file

@ -0,0 +1,118 @@
/*
* 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.darksteel;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.permanent.token.BeastToken;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetOpponent;
/**
*
* @author wetterlicht
*/
public class PulseOfTheTangle extends CardImpl {
public PulseOfTheTangle(UUID ownerId) {
super(ownerId, 80, "Pulse of the Tangle", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{1}{G}{G}");
this.expansionSetCode = "DST";
// Put a 3/3 green Beast creature token onto the battlefield. Then if an opponent controls more creatures than you, return Pulse of the Tangle to its owner's hand.
this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken()));
this.getSpellAbility().addEffect(new PulseOfTheTangleReturnToHandEffect());
}
public PulseOfTheTangle(final PulseOfTheTangle card) {
super(card);
}
@Override
public PulseOfTheTangle copy() {
return new PulseOfTheTangle(this);
}
}
class PulseOfTheTangleReturnToHandEffect extends OneShotEffect {
PulseOfTheTangleReturnToHandEffect() {
super(Outcome.Benefit);
this.staticText = "Then if an opponent controls more creatures than you, return {this} to its owner's hand";
}
PulseOfTheTangleReturnToHandEffect(final PulseOfTheTangleReturnToHandEffect effect) {
super(effect);
}
@Override
public PulseOfTheTangleReturnToHandEffect copy() {
return new PulseOfTheTangleReturnToHandEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
FilterControlledCreaturePermanent controllerFilter = new FilterControlledCreaturePermanent();
PermanentsOnBattlefieldCount controllerCount = new PermanentsOnBattlefieldCount(controllerFilter);
int controllerAmount = controllerCount.calculate(game, source, this);
boolean check = false;
if (controller != null) {
for (UUID opponentID : game.getOpponents(controller.getId())) {
if (opponentID != null) {
FilterCreaturePermanent opponentFilter = new FilterCreaturePermanent();
opponentFilter.add(new ControllerIdPredicate(opponentID));
PermanentsOnBattlefieldCount opponentCreatureCount = new PermanentsOnBattlefieldCount(opponentFilter);
check = opponentCreatureCount.calculate(game, source, this) > controllerAmount;
if (check) {
break;
}
}
}
if (check) {
Card card = game.getCard(source.getSourceId());
controller.moveCards(card, Zone.HAND, source, game);
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,60 @@
/*
* 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.darksteel;
import java.util.UUID;
import mage.abilities.effects.common.PutOnLibraryTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.target.common.TargetArtifactPermanent;
/**
*
* @author wetterlicht
*/
public class RebukingCeremony extends CardImpl {
public RebukingCeremony(UUID ownerId) {
super(ownerId, 82, "Rebuking Ceremony", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{G}{G}");
this.expansionSetCode = "DST";
// Put two target artifacts on top of their owners' libraries.
getSpellAbility().addEffect(new PutOnLibraryTargetEffect(true));
getSpellAbility().addTarget(new TargetArtifactPermanent(2));
}
public RebukingCeremony(final RebukingCeremony card) {
super(card);
}
@Override
public RebukingCeremony copy() {
return new RebukingCeremony(this);
}
}

View file

@ -0,0 +1,74 @@
/*
* 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.darksteel;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BecomesBlockedAllTriggeredAbility;
import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility;
import mage.abilities.common.BecomesBlockedTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.CardTypePredicate;
/**
*
* @author wetterlicht
*/
public class TelJiladWolf extends CardImpl {
private static FilterCreaturePermanent filter = new FilterCreaturePermanent("artifact creature");
static{
filter.add(new CardTypePredicate(CardType.ARTIFACT));
}
public TelJiladWolf(UUID ownerId) {
super(ownerId, 88, "Tel-Jilad Wolf", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}");
this.expansionSetCode = "DST";
this.subtype.add("Wolf");
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Tel-Jilad Wolf becomes blocked by an artifact creature, Tel-Jilad Wolf gets +3/+3 until end of turn.
this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(new BoostSourceEffect(3, 3, Duration.EndOfTurn), filter, false));
}
public TelJiladWolf(final TelJiladWolf card) {
super(card);
}
@Override
public TelJiladWolf copy() {
return new TelJiladWolf(this);
}
}

View file

@ -0,0 +1,109 @@
/*
* 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.darksteel;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.common.FilterArtifactPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetArtifactPermanent;
/**
*
* @author wetterlicht
*/
public class Unforge extends CardImpl {
private static FilterArtifactPermanent filter = new FilterArtifactPermanent("equipment");
static{
filter.add(new SubtypePredicate("Equipment"));
}
public Unforge(UUID ownerId) {
super(ownerId, 71, "Unforge", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{R}");
this.expansionSetCode = "DST";
// Destroy target Equipment. If that Equipment was attached to a creature, Unforge deals 2 damage to that creature.
getSpellAbility().addTarget(new TargetArtifactPermanent(filter));
getSpellAbility().addEffect(new DestroyTargetEffect());
getSpellAbility().addEffect(new UnforgeEffect());
}
public Unforge(final Unforge card) {
super(card);
}
@Override
public Unforge copy() {
return new Unforge(this);
}
}
class UnforgeEffect extends OneShotEffect{
public UnforgeEffect(){
super(Outcome.Damage);
staticText = "If that Equipment was attached to a creature, Unforge deals 2 damage to that creature.";
}
public UnforgeEffect(final UnforgeEffect effect){
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent equipment = game.getPermanentOrLKIBattlefield(this.getTargetPointer().getFirst(game, source));
if(equipment != null){
Permanent creature = game.getPermanent(equipment.getAttachedTo());
if(creature != null){
creature.damage(2, source.getId(), game, false, true);
return true;
}
}
return false;
}
@Override
public Effect copy() {
return new UnforgeEffect(this);
}
}

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.sets.darksteel;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.DrawCardTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetSpell;
/**
*
* @author wetterlicht
*/
public class Vex extends CardImpl {
public Vex(UUID ownerId) {
super(ownerId, 36, "Vex", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{U}");
this.expansionSetCode = "DST";
// Counter target spell. That spell's controller may draw a card.
getSpellAbility().addTarget(new TargetSpell());
getSpellAbility().addEffect(new VexEffect());
}
public Vex(final Vex card) {
super(card);
}
@Override
public Vex copy() {
return new Vex(this);
}
}
class VexEffect extends OneShotEffect {
public VexEffect() {
super(Outcome.Neutral);
this.staticText = "That spell's controller may draw a card";
}
public VexEffect(final VexEffect effect) {
super(effect);
}
@Override
public VexEffect copy() {
return new VexEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
UUID targetId = source.getFirstTarget();
Player controller = null;
boolean countered = false;
if (targetId != null) {
controller = game.getPlayer(game.getControllerId(targetId));
}
if (targetId != null
&& game.getStack().counter(targetId, source.getSourceId(), game)) {
countered = true;
}
if (controller != null) {
controller.drawCards(1, game);
}
return countered;
}
}

View file

@ -0,0 +1,76 @@
/*
* 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.futuresight;
import java.util.UUID;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.ExileSpellEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.SuspendAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.counters.CounterType;
import mage.target.common.TargetCreatureOrPlayer;
/**
*
* @author emerald000
*/
public class ArcBlade extends CardImpl {
public ArcBlade(UUID ownerId) {
super(ownerId, 94, "Arc Blade", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{R}{R}");
this.expansionSetCode = "FUT";
// Arc Blade deals 2 damage to target creature or player.
this.getSpellAbility().addEffect(new DamageTargetEffect(2));
// Exile Arc Blade
this.getSpellAbility().addEffect(ExileSpellEffect.getInstance());
// with three time counters on it.
Effect effect = new AddCountersSourceEffect(CounterType.TIME.createInstance(), new StaticValue(3), false, true);
effect.setText("with 3 time counters on it");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
// Suspend 3-{2}{R}
this.addAbility(new SuspendAbility(3, new ManaCostsImpl<>("{2}{R}"), this));
}
public ArcBlade(final ArcBlade card) {
super(card);
}
@Override
public ArcBlade copy() {
return new ArcBlade(this);
}
}

View file

@ -27,9 +27,6 @@
*/
package mage.sets.journeyintonyx;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
@ -47,7 +44,6 @@ import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -55,7 +51,7 @@ import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreatureOrPlayer;
import mage.watchers.Watcher;
import mage.watchers.common.CardsAmountDrawnThisTurnWatcher;
/**
*
@ -83,7 +79,7 @@ public class KeranosGodOfStorms extends CardImpl {
// Reveal the first card you draw on each of your turns.
// Whenever you reveal a land card this way, draw a card.
// Whenever you reveal a nonland card this way, Keranos deals 3 damage to target creature or player.
this.addAbility(new KeranosGodOfStormsTriggeredAbility(), new CardsDrawnDuringTurnWatcher());
this.addAbility(new KeranosGodOfStormsTriggeredAbility(), new CardsAmountDrawnThisTurnWatcher());
}
@ -122,7 +118,8 @@ class KeranosGodOfStormsTriggeredAbility extends TriggeredAbilityImpl {
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(this.getControllerId())) {
if (game.getActivePlayerId().equals(this.getControllerId())) {
CardsDrawnDuringTurnWatcher watcher = (CardsDrawnDuringTurnWatcher) game.getState().getWatchers().get("CardsDrawnDuringTurn");
CardsAmountDrawnThisTurnWatcher watcher =
(CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.BASIC_KEY);
if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) != 1) {
return false;
}
@ -148,56 +145,7 @@ class KeranosGodOfStormsTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return "Reveal the first card you draw on each of your turns. Whenever you reveal a land card this way, draw a card. Whenever you reveal a nonland card this way, Keranos deals 3 damage to target creature or player.";
return "Reveal the first card you draw on each of your turns. Whenever you reveal a land card this way, draw a card. " +
"Whenever you reveal a nonland card this way, Keranos deals 3 damage to target creature or player.";
}
}
class CardsDrawnDuringTurnWatcher extends Watcher {
private final Map<UUID, Integer> amountOfCardsDrawnThisTurn = new HashMap<>();
public CardsDrawnDuringTurnWatcher() {
super("CardsDrawnDuringTurn", WatcherScope.GAME);
}
public CardsDrawnDuringTurnWatcher(final CardsDrawnDuringTurnWatcher watcher) {
super(watcher);
for (Entry<UUID, Integer> entry : watcher.amountOfCardsDrawnThisTurn.entrySet()) {
amountOfCardsDrawnThisTurn.put(entry.getKey(), entry.getValue());
}
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DREW_CARD) {
UUID playerId = event.getPlayerId();
if (playerId != null) {
Integer amount = amountOfCardsDrawnThisTurn.get(playerId);
if (amount == null) {
amount = 1;
} else {
amount++;
}
amountOfCardsDrawnThisTurn.put(playerId, amount);
}
}
}
public int getAmountCardsDrawn(UUID playerId) {
Integer amount = amountOfCardsDrawnThisTurn.get(playerId);
if (amount != null) {
return amount;
}
return 0;
}
@Override
public void reset() {
amountOfCardsDrawnThisTurn.clear();
}
@Override
public CardsDrawnDuringTurnWatcher copy() {
return new CardsDrawnDuringTurnWatcher(this);
}
}

View file

@ -28,12 +28,12 @@
package mage.sets.legends;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CounterUnlessPaysEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
@ -92,54 +92,31 @@ class InvokePrejudiceTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Card card = game.getCard(event.getSourceId());
if (card == null || !(card.getCardType().contains(CardType.CREATURE))) {
return false;
}
// Get colors of the card
boolean castCreatureIsWhite = card.getColor(game).isWhite();
boolean castCreatureIsBlue = card.getColor(game).isBlue();
boolean castCreatureIsBlack = card.getColor(game).isBlack();
boolean castCreatureIsRed = card.getColor(game).isRed();
boolean castCreatureIsGreen = card.getColor(game).isGreen();
// Compare to colours of creatures of controller on bf
boolean hasToPay = true;
boolean gotACreature = false;
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), getControllerId(), game)) {
gotACreature = true;
if (castCreatureIsWhite && permanent.getColor(game).isWhite()) {
hasToPay = false;
}
if (castCreatureIsBlue && permanent.getColor(game).isBlue()) {
hasToPay = false;
}
if (castCreatureIsBlack && permanent.getColor(game).isBlack()) {
hasToPay = false;
}
if (castCreatureIsRed && permanent.getColor(game).isRed()) {
hasToPay = false;
}
if (castCreatureIsGreen && permanent.getColor(game).isGreen()) {
hasToPay = false;
if (game.getOpponents(getControllerId()).contains(event.getPlayerId())) {
Spell spell = (Spell) game.getObject(event.getTargetId());
if (spell != null && spell.getCardType().contains(CardType.CREATURE)) {
boolean creatureSharesAColor = false;
ObjectColor spellColor = spell.getColor(game);
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterControlledCreaturePermanent(), getControllerId(), game)) {
if (spellColor.shares(permanent.getColor(game))) {
creatureSharesAColor = true;
break;
}
}
if (!creatureSharesAColor) {
for (Effect effect : getEffects()) {
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
}
return true;
}
}
}
if (hasToPay || !gotACreature) {
for (Effect effect : getEffects()) {
effect.setTargetPointer(new FixedTarget(card.getId()));
}
}
return hasToPay || !gotACreature;
return false;
}
@Override
public String getRule() {
return "Whenever an opponent casts a creature spell that doesn't share a color with a creature you control, counter that spell unless that player pays {X}, where X is its converted mana cost.";
return "Whenever an opponent casts a creature spell that doesn't share a color with a creature you control, " + super.getRule();
}
}
@ -163,14 +140,10 @@ class InvokePrejudiceEffect extends CounterUnlessPaysEffect {
public boolean apply(Game game, Ability source) {
boolean result = true;
Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source));
if (spell != null) {
Card card = spell.getCard();
if (card != null) {
CounterUnlessPaysEffect effect = new CounterUnlessPaysEffect(new GenericManaCost(card.getConvertedManaCost()));
effect.setTargetPointer(new FixedTarget(spell.getId()));
result = effect.apply(game, source);
}
CounterUnlessPaysEffect effect = new CounterUnlessPaysEffect(new GenericManaCost(spell.getConvertedManaCost()));
effect.setTargetPointer(getTargetPointer());
result = effect.apply(game, source);
}
return result;
}

View file

@ -44,6 +44,7 @@ import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.util.CardUtil;
/**
*
@ -87,11 +88,6 @@ class CoatOfArmsEffect extends ContinuousEffectImpl {
return new CoatOfArmsEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game);
@ -112,9 +108,11 @@ class CoatOfArmsEffect extends ContinuousEffectImpl {
for (Permanent permanent : permanents) {
if (!permanent.getId().equals(target.getId())) {
for (String subtype : targetSubtype) {
if (permanent.hasSubtype(subtype)) {
amount++;
break;
if (!CardUtil.isNonCreatureSubtype(subtype)) {
if (permanent.hasSubtype(subtype)) {
amount++;
break;
}
}
}
}

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.sets.morningtide;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.PreventionEffectImpl;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.players.Player;
/**
*
* @author emerald000
*/
public class BattletideAlchemist extends CardImpl {
public BattletideAlchemist(UUID ownerId) {
super(ownerId, 2, "Battletide Alchemist", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
this.expansionSetCode = "MOR";
this.subtype.add("Kithkin");
this.subtype.add("Cleric");
this.power = new MageInt(3);
this.toughness = new MageInt(4);
// If a source would deal damage to a player, you may prevent X of that damage, where X is the number of Clerics you control.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BattletideAlchemistEffect()));
}
public BattletideAlchemist(final BattletideAlchemist card) {
super(card);
}
@Override
public BattletideAlchemist copy() {
return new BattletideAlchemist(this);
}
}
class BattletideAlchemistEffect extends PreventionEffectImpl {
BattletideAlchemistEffect() {
super(Duration.WhileOnBattlefield);
this.staticText = "If a source would deal damage to a player, you may prevent X of that damage, where X is the number of Clerics you control";
}
BattletideAlchemistEffect(final BattletideAlchemistEffect effect) {
super(effect);
}
@Override
public BattletideAlchemistEffect copy() {
return new BattletideAlchemistEffect(this);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
boolean result = false;
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(event.getTargetId());
if (controller != null) {
int numberOfClericsControlled = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent("Cleric", "Clerics")).calculate(game, source, this);
int toPrevent = Math.min(numberOfClericsControlled, event.getAmount());
if (toPrevent > 0 && controller.chooseUse(Outcome.PreventDamage, "Prevent " + toPrevent + " damage to " + targetPlayer.getName() + "?", source, game)) {
GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, targetPlayer.getId(), source.getSourceId(), source.getControllerId(), toPrevent, false);
if (!game.replaceEvent(preventEvent)) {
if (event.getAmount() >= toPrevent) {
event.setAmount(event.getAmount() - toPrevent);
}
else {
event.setAmount(0);
result = true;
}
if (toPrevent > 0) {
game.informPlayers("Battletide Alchemist prevented " + toPrevent + " damage to " + targetPlayer.getName());
game.fireEvent(GameEvent.getEvent(
GameEvent.EventType.PREVENTED_DAMAGE,
targetPlayer.getId(),
source.getSourceId(),
source.getControllerId(),
toPrevent));
}
}
}
}
return result;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.DAMAGE_PLAYER;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return super.applies(event, source, game);
}
}

View file

@ -0,0 +1,117 @@
/*
* 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.morningtide;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
/**
*
* @author emerald000
*/
public class BoldwyrHeavyweights extends CardImpl {
public BoldwyrHeavyweights(UUID ownerId) {
super(ownerId, 85, "Boldwyr Heavyweights", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{R}{R}");
this.expansionSetCode = "MOR";
this.subtype.add("Giant");
this.subtype.add("Warrior");
this.power = new MageInt(8);
this.toughness = new MageInt(8);
// Trample
this.addAbility(TrampleAbility.getInstance());
// When Boldwyr Heavyweights enters the battlefield, each opponent may search his or her library for a creature card and put it onto the battlefield. Then each player who searched his or her library this way shuffles it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new BoldwyrHeavyweightsEffect()));
}
public BoldwyrHeavyweights(final BoldwyrHeavyweights card) {
super(card);
}
@Override
public BoldwyrHeavyweights copy() {
return new BoldwyrHeavyweights(this);
}
}
class BoldwyrHeavyweightsEffect extends OneShotEffect {
BoldwyrHeavyweightsEffect() {
super(Outcome.Detriment);
this.staticText = "each opponent may search his or her library for a creature card and put it onto the battlefield. Then each player who searched his or her library this way shuffles it";
}
BoldwyrHeavyweightsEffect(final BoldwyrHeavyweightsEffect effect) {
super(effect);
}
@Override
public BoldwyrHeavyweightsEffect copy() {
return new BoldwyrHeavyweightsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Set<Player> playersThatSearched = new HashSet<>(1);
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
Player opponent = game.getPlayer(opponentId);
if (opponent != null && opponent.chooseUse(Outcome.PutCreatureInPlay, "Search your library for a creature card and put it onto the battlefield?", source, game)) {
TargetCardInLibrary target = new TargetCardInLibrary(new FilterCreatureCard());
if (opponent.searchLibrary(target, game)) {
Card targetCard = opponent.getLibrary().getCard(target.getFirstTarget(), game);
if (targetCard != null) {
opponent.moveCards(targetCard, Zone.BATTLEFIELD, source, game);
playersThatSearched.add(opponent);
}
}
}
}
for (Player opponent : playersThatSearched) {
opponent.shuffleLibrary(source, game);
}
return true;
}
}

View file

@ -0,0 +1,109 @@
/*
* 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.morningtide;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetAttackingOrBlockingCreature;
/**
*
* @author emerald000
*/
public class CoordinatedBarrage extends CardImpl {
public CoordinatedBarrage(UUID ownerId) {
super(ownerId, 7, "Coordinated Barrage", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{W}");
this.expansionSetCode = "MOR";
// Choose a creature type. Coordinated Barrage deals damage to target attacking or blocking creature equal to the number of permanents you control of the chosen type.
this.getSpellAbility().addEffect(new CoordinatedBarrageEffect());
this.getSpellAbility().addTarget(new TargetAttackingOrBlockingCreature());
}
public CoordinatedBarrage(final CoordinatedBarrage card) {
super(card);
}
@Override
public CoordinatedBarrage copy() {
return new CoordinatedBarrage(this);
}
}
class CoordinatedBarrageEffect extends OneShotEffect {
CoordinatedBarrageEffect() {
super(Outcome.Damage);
this.staticText = "Choose a creature type. Coordinated Barrage deals damage to target attacking or blocking creature equal to the number of permanents you control of the chosen type";
}
CoordinatedBarrageEffect(final CoordinatedBarrageEffect effect) {
super(effect);
}
@Override
public CoordinatedBarrageEffect copy() {
return new CoordinatedBarrageEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Choice choice = new ChoiceImpl(true);
choice.setMessage("Choose a creature type");
choice.setChoices(CardRepository.instance.getCreatureTypes());
if (controller.choose(Outcome.Damage, choice, game)) {
String chosenType = choice.getChoice();
FilterControlledPermanent filter = new FilterControlledPermanent();
filter.add(new SubtypePredicate(chosenType));
int damageDealt = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (permanent != null) {
permanent.damage(damageDealt, source.getSourceId(), game, false, true);
}
return true;
}
}
return false;
}
}

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.morningtide;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.combat.CantBlockTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetLandPermanent;
/**
*
* @author emerald000
*/
public class HostileRealm extends CardImpl {
public HostileRealm(UUID ownerId) {
super(ownerId, 91, "Hostile Realm", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}");
this.expansionSetCode = "MOR";
this.subtype.add("Aura");
// Enchant land
TargetPermanent auraTarget = new TargetLandPermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Enchanted land has "{T}: Target creature can't block this turn."
Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBlockTargetEffect(Duration.EndOfTurn), new TapSourceCost());
gainedAbility.addTarget(new TargetCreaturePermanent());
Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA);
effect.setText("Enchanted land has \"{T}: Target creature can't block this turn.\"");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public HostileRealm(final HostileRealm card) {
super(card);
}
@Override
public HostileRealm copy() {
return new HostileRealm(this);
}
}

View file

@ -0,0 +1,79 @@
/*
* 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.morningtide;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
/**
*
* @author emerald000
*/
public class Stenchskipper extends CardImpl {
public Stenchskipper(UUID ownerId) {
super(ownerId, 79, "Stenchskipper", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.expansionSetCode = "MOR";
this.subtype.add("Elemental");
this.power = new MageInt(6);
this.toughness = new MageInt(5);
// Flying
this.addAbility(FlyingAbility.getInstance());
// At the beginning of the end step, if you control no Goblins, sacrifice Stenchskipper.
this.addAbility(new BeginningOfEndStepTriggeredAbility(
Zone.BATTLEFIELD,
new SacrificeSourceEffect(),
TargetController.ANY,
new PermanentsOnTheBattlefieldCondition(
new FilterControlledCreaturePermanent("Goblin", "if you control no Goblins"),
PermanentsOnTheBattlefieldCondition.CountType.FEWER_THAN,
1),
false));
}
public Stenchskipper(final Stenchskipper card) {
super(card);
}
@Override
public Stenchskipper copy() {
return new Stenchskipper(this);
}
}

View file

@ -0,0 +1,214 @@
/*
* 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.morningtide;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapTargetCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.combat.CantAttackAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
/**
*
* @author emerald000
*/
public class WeightOfConscience extends CardImpl {
public WeightOfConscience(UUID ownerId) {
super(ownerId, 28, "Weight of Conscience", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
this.expansionSetCode = "MOR";
this.subtype.add("Aura");
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Enchanted creature can't attack.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect(AttachmentType.AURA)));
// Tap two untapped creatures you control that share a creature type: Exile enchanted creature.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new WeightOfConscienceEffect(), new TapTargetCost(new WeightOfConscienceTarget())));
}
public WeightOfConscience(final WeightOfConscience card) {
super(card);
}
@Override
public WeightOfConscience copy() {
return new WeightOfConscience(this);
}
}
class WeightOfConscienceEffect extends OneShotEffect {
WeightOfConscienceEffect() {
super(Outcome.Exile);
staticText = "Exile enchanted creature";
}
WeightOfConscienceEffect(final WeightOfConscienceEffect effect) {
super(effect);
}
@Override
public WeightOfConscienceEffect copy() {
return new WeightOfConscienceEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (controller != null && enchantment != null && enchantment.getAttachedTo() != null) {
Permanent creature = game.getPermanent(enchantment.getAttachedTo());
if (creature != null) {
controller.moveCardsToExile(creature, source, game, true, null, "");
}
}
return false;
}
}
class WeightOfConscienceTarget extends TargetControlledCreaturePermanent {
private static final FilterControlledCreaturePermanent filterUntapped = new FilterControlledCreaturePermanent("untapped creatures you control that share a creature type");
static {
filterUntapped.add(Predicates.not(new TappedPredicate()));
}
WeightOfConscienceTarget() {
super(2, 2, filterUntapped, true);
}
WeightOfConscienceTarget(final WeightOfConscienceTarget target) {
super(target);
}
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Player player = game.getPlayer(sourceControllerId);
Set<UUID> possibleTargets = new HashSet<>(0);
if (player != null) {
// Choosing first target
if (this.getTargets().isEmpty()) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) {
for (String subtype : permanent.getSubtype()) {
if (!CardUtil.isNonCreatureSubtype(subtype)) {
if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype), sourceControllerId, game, 2)) {
possibleTargets.add(permanent.getId());
}
}
}
}
}
// Choosing second target
else {
UUID firstTargetId = this.getTargets().get(0);
Permanent firstTargetCreature = game.getPermanent(firstTargetId);
if (firstTargetCreature != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) {
if (!permanent.getId().equals(firstTargetId) && CardUtil.shareSubtypes(firstTargetCreature, permanent)) {
possibleTargets.add(permanent.getId());
}
}
}
}
}
return possibleTargets;
}
@Override
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
for (Permanent permanent1 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) {
for (Permanent permanent2 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) {
if (permanent1 != permanent2 && CardUtil.shareSubtypes(permanent1, permanent2)) {
return true;
}
}
}
return false;
}
@Override
public boolean canTarget(UUID id, Ability source, Game game) {
if (super.canTarget(id, game)) {
Permanent targetPermanent = game.getPermanent(id);
if (targetPermanent != null) {
if (this.getTargets().isEmpty()) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, source.getControllerId(), game)) {
for (String subtype : permanent.getSubtype()) {
if (!CardUtil.isNonCreatureSubtype(subtype)) {
if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype), source.getControllerId(), game, 2)) {
return true;
}
}
}
}
}
else {
Permanent firstTarget = game.getPermanent(this.getTargets().get(0));
if (firstTarget != null && CardUtil.shareSubtypes(firstTarget, targetPermanent)) {
return true;
}
}
}
}
return false;
}
@Override
public WeightOfConscienceTarget copy() {
return new WeightOfConscienceTarget(this);
}
}

View file

@ -0,0 +1,52 @@
/*
* 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;
/**
*
* @author emerald000
*/
public class Torchling extends mage.sets.venservskoth.Torchling {
public Torchling(UUID ownerId) {
super(ownerId);
this.cardNumber = 110;
this.expansionSetCode = "PLC";
}
public Torchling(final Torchling card) {
super(card);
}
@Override
public Torchling copy() {
return new Torchling(this);
}
}

View file

@ -28,13 +28,13 @@
package mage.sets.planechase2012;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
@ -54,7 +54,6 @@ public class LastStand extends CardImpl {
super(ownerId, 100, "Last Stand", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{W}{U}{B}{R}{G}");
this.expansionSetCode = "PC2";
// Target opponent loses 2 life for each Swamp you control. Last Stand deals damage equal to the number of Mountains you control to target creature. Put a 1/1 green Saproling creature token onto the battlefield for each Forest you control. You gain 2 life for each Plains you control. Draw a card for each Island you control, then discard that many cards.
this.getSpellAbility().addEffect(new LastStandEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
@ -108,7 +107,7 @@ class LastStandEffect extends OneShotEffect {
Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source));
if (opponent != null) {
int swamps = game.getBattlefield().count(filterSwamp, source.getSourceId(), source.getControllerId(), game);
opponent.damage(swamps, source.getSourceId(), game, false, true);
opponent.loseLife(swamps * 2, game);
}
// Last Stand deals damage equal to the number of Mountains you control to target creature.
Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget());
@ -125,7 +124,7 @@ class LastStandEffect extends OneShotEffect {
}
// You gain 2 life for each Plains you control.
int plains = game.getBattlefield().count(filterPlains, source.getSourceId(), source.getControllerId(), game);
controller.gainLife(plains, game);
controller.gainLife(plains * 2, game);
// Draw a card for each Island you control, then discard that many cards
int islands = game.getBattlefield().count(filterIsland, source.getSourceId(), source.getControllerId(), game);
if (islands > 0) {

View file

@ -45,6 +45,7 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.KickerAbility;
import mage.cards.CardImpl;
import mage.constants.AbilityType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
@ -111,6 +112,9 @@ class DralnusPetEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null && source.getAbilityType().equals(AbilityType.STATIC)) {
permanent = game.getPermanentEntering(source.getSourceId());
}
if (controller != null && permanent != null) {
SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY);
if (spellAbility != null

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.sets.stronghold;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromExileForSourceEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
* @author spjspj
*/
public class Portcullis extends CardImpl {
private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature");
public Portcullis(UUID ownerId) {
super(ownerId, 133, "Portcullis", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}");
this.expansionSetCode = "STH";
// Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature.
String rule = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature";
TriggeredAbility ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new PortcullisExileEffect(), filter, false, SetTargetPointer.PERMANENT, rule);
MoreThanXCreaturesOnBFCondition condition = new MoreThanXCreaturesOnBFCondition(2);
this.addAbility(new ConditionalTriggeredAbility(ability, condition, rule));
// Return that card to the battlefield under its owner's control when Portcullis leaves the battlefield.
Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false);
this.addAbility(ability2);
}
public Portcullis(final Portcullis card) {
super(card);
}
@Override
public Portcullis copy() {
return new Portcullis(this);
}
}
class MoreThanXCreaturesOnBFCondition implements Condition {
protected final int value;
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures on field");
public MoreThanXCreaturesOnBFCondition(int value) {
this.value = value;
}
@Override
public final boolean apply(Game game, Ability source) {
PermanentsOnBattlefieldCount amount = new PermanentsOnBattlefieldCount(filter);
int count = amount.calculate(game, source, null);
return count > value;
}
}
class PortcullisExileEffect extends OneShotEffect {
public PortcullisExileEffect() {
super(Outcome.Neutral);
this.staticText = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature.";
}
public PortcullisExileEffect(final PortcullisExileEffect effect) {
super(effect);
}
@Override
public PortcullisExileEffect copy() {
return new PortcullisExileEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
if (permanent != null && creature != null) {
Player controller = game.getPlayer(creature.getControllerId());
Zone currentZone = game.getState().getZone(creature.getId());
if (currentZone.equals(Zone.BATTLEFIELD)) {
controller.moveCardsToExile(creature, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName());
}
}
return false;
}
}

View file

@ -0,0 +1,138 @@
/*
* 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.venservskoth;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.ChooseNewTargetsTargetEffect;
import mage.abilities.effects.common.UntapSourceEffect;
import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.filter.FilterSpell;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.target.Target;
import mage.target.TargetSpell;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author emerald000
*/
public class Torchling extends CardImpl {
public Torchling(UUID ownerId) {
super(ownerId, 58, "Torchling", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{R}{R}");
this.expansionSetCode = "DDI";
this.subtype.add("Shapeshifter");
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// {R}: Untap Torchling.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapSourceEffect(), new ColoredManaCost(ColoredManaSymbol.R)));
// {R}: Target creature blocks Torchling this turn if able.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(), new ColoredManaCost(ColoredManaSymbol.R));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
// {R}: Change the target of target spell that targets only Torchling.
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChooseNewTargetsTargetEffect(true, true), new ColoredManaCost(ColoredManaSymbol.R));
FilterSpell filter = new FilterSpell("spell that targets only " + this.getName());
filter.add(new TorchlingTargetPredicate(this.getId()));
ability.addTarget(new TargetSpell(filter));
this.addAbility(ability);
// {1}: Torchling gets +1/-1 until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, -1, Duration.EndOfTurn), new GenericManaCost(1)));
// {1}: Torchling gets -1/+1 until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(-1, 1, Duration.EndOfTurn), new GenericManaCost(1)));
}
public Torchling(final Torchling card) {
super(card);
}
@Override
public Torchling copy() {
return new Torchling(this);
}
}
class TorchlingTargetPredicate implements Predicate<MageObject> {
private final UUID sourceId;
TorchlingTargetPredicate(UUID sourceId) {
this.sourceId = sourceId;
}
@Override
public boolean apply(MageObject input, Game game) {
Spell spell = game.getStack().getSpell(input.getId());
if (spell != null) {
int numberOfTargets = 0;
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
for (Mode mode : spellAbility.getModes().getSelectedModes()) {
for (Target target : mode.getTargets()) {
for (UUID targetId : target.getTargets()) {
if (!targetId.equals(sourceId)) {
return false;
}
else {
numberOfTargets++;
}
}
}
}
}
return numberOfTargets > 0;
}
return false;
}
@Override
public String toString() {
return "target spell that targets only {this}";
}
}

View file

@ -41,7 +41,7 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.watchers.Watcher;
import mage.watchers.common.CardsAmountDrawnThisTurnWatcher;
import java.util.UUID;
@ -57,9 +57,10 @@ public class ArchmageAscension extends CardImpl {
// At the beginning of each end step, if you drew two or more cards this turn, you may put a quest counter on Archmage Ascension.
this.addAbility(new ArchmageAscensionTriggeredAbility(), new CardsDrawnControllerWatcher());
this.addAbility(new ArchmageAscensionTriggeredAbility(), new CardsAmountDrawnThisTurnWatcher());
// As long as Archmage Ascension has six or more quest counters on it, if you would draw a card, you may instead search your library for a card, put that card into your hand, then shuffle your library.
// As long as Archmage Ascension has six or more quest counters on it, if you would draw a card,
// you may instead search your library for a card, put that card into your hand, then shuffle your library.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ArchmageAscensionReplacementEffect()));
}
@ -97,8 +98,9 @@ class ArchmageAscensionTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent archmage = game.getPermanent(super.getSourceId());
CardsDrawnControllerWatcher watcher = (CardsDrawnControllerWatcher) game.getState().getWatchers().get("CardsControllerDrawn");
return archmage != null && watcher != null && watcher.conditionMet();
CardsAmountDrawnThisTurnWatcher watcher =
(CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.BASIC_KEY);
return archmage != null && watcher != null && watcher.getAmountCardsDrawn(this.getControllerId()) >= 2;
}
@Override
@ -107,47 +109,12 @@ class ArchmageAscensionTriggeredAbility extends TriggeredAbilityImpl {
}
}
class CardsDrawnControllerWatcher extends Watcher {
int cardsDrawn;
public CardsDrawnControllerWatcher() {
super("CardsControllerDrawn", WatcherScope.GAME);
}
public CardsDrawnControllerWatcher(final CardsDrawnControllerWatcher watcher) {
super(watcher);
this.cardsDrawn = watcher.cardsDrawn;
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DREW_CARD
&& event.getPlayerId().equals(controllerId)) {
cardsDrawn += 1;
if (cardsDrawn >= 2) {
condition = true;
}
}
}
@Override
public void reset() {
super.reset();
cardsDrawn = 0;
}
@Override
public CardsDrawnControllerWatcher copy() {
return new CardsDrawnControllerWatcher(this);
}
}
class ArchmageAscensionReplacementEffect extends ReplacementEffectImpl {
public ArchmageAscensionReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "As long as {this} has six or more quest counters on it, if you would draw a card, you may instead search your library for a card, put that card into your hand, then shuffle your library";
staticText = "As long as {this} has six or more quest counters on it, if you would draw a card, " +
"you may instead search your library for a card, put that card into your hand, then shuffle your library";
}
public ArchmageAscensionReplacementEffect(final ArchmageAscensionReplacementEffect effect) {

View file

@ -27,8 +27,6 @@
*/
package mage.sets.zendikar;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
@ -40,12 +38,10 @@ import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.watchers.Watcher;
import mage.watchers.common.CardsAmountDrawnThisTurnWatcher;
/**
*
@ -59,7 +55,7 @@ public class RuneflareTrap extends CardImpl {
this.subtype.add("Trap");
// If an opponent drew three or more cards this turn, you may pay {R} rather than pay Runeflare Trap's mana cost.
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{R}"), RavenousTrapCondition.getInstance()), new CardsDrawnWatcher());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{R}"), RuneflareTrapCondition.getInstance()), new CardsAmountDrawnThisTurnWatcher());
// Runeflare Trap deals damage to target player equal to the number of cards in that player's hand.
this.getSpellAbility().addEffect(new DamageTargetEffect(new TargetPlayerCardsInHandCount()));
@ -115,7 +111,8 @@ class RuneflareTrapCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
CardsDrawnWatcher watcher = (CardsDrawnWatcher) game.getState().getWatchers().get("CardsDrawnWatcher");
CardsAmountDrawnThisTurnWatcher watcher =
(CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.BASIC_KEY);
return watcher != null && watcher.opponentDrewXOrMoreCards(source.getControllerId(), 3, game);
}
@ -124,53 +121,3 @@ class RuneflareTrapCondition implements Condition {
return "If an opponent drew three or more cards this turn";
}
}
class CardsDrawnWatcher extends Watcher {
private final Map<UUID, Integer> playerCardsDrawn = new HashMap<>();
public CardsDrawnWatcher() {
super("CardsDrawnWatcher", WatcherScope.GAME);
}
public CardsDrawnWatcher(final CardsDrawnWatcher watcher) {
super(watcher);
playerCardsDrawn.putAll(watcher.playerCardsDrawn);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DREW_CARD) {
if (playerCardsDrawn.containsKey(event.getPlayerId())) {
playerCardsDrawn.put(event.getPlayerId(), playerCardsDrawn.get(event.getPlayerId()) + 1);
} else {
playerCardsDrawn.put(event.getPlayerId(), 1);
}
}
}
@Override
public void reset() {
super.reset();
playerCardsDrawn.clear();
}
public boolean opponentDrewXOrMoreCards(UUID playerId, int x, Game game) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Map.Entry<UUID, Integer> entry : playerCardsDrawn.entrySet()) {
if (game.isOpponent(player, playerId)) {
if (entry.getValue() >= x) {
return true;
}
}
}
}
return false;
}
@Override
public CardsDrawnWatcher copy() {
return new CardsDrawnWatcher(this);
}
}

View file

@ -163,4 +163,26 @@ public class SuspendTest extends CardTestPlayerBase {
assertHandCount(playerA, "Ancestral Vision", 1);
}
/**
* Suppression Field incorrectly makes suspend cards cost 2 more to suspend.
* It made my Rift Bolt cost 2R to suspend instead of R
*
*/
@Test
public void testCostManipulation() {
// Rift Bolt deals 3 damage to target creature or player.
// Suspend 1-{R}
addCard(Zone.HAND, playerA, "Rift Bolt", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerB, "Suppression Field", 1);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Suspend");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertHandCount(playerA, "Rift Bolt", 0);
}
}

View file

@ -251,7 +251,8 @@ public class UndyingTest extends CardTestPlayerBase {
// Sacrifice a creature: Add {C}{C} to your mana pool.
addCard(Zone.BATTLEFIELD, playerA, "Ashnod's Altar", 1);
// Whenever a Human deals damage to you, destroy it.
// Other non-Human creatures you control get +1/+1 and have undying.
// Other non-Human creatures you control get +1/+1 and have undying
// (When this creature dies, if it had no +1/+1 counters on it, return it to the battlefield under its owner's control with a +1/+1 counter on it.).
addCard(Zone.BATTLEFIELD, playerA, "Mikaeus, the Unhallowed", 1);
// Flying

View file

@ -30,8 +30,10 @@ package mage.abilities.common;
import mage.constants.Zone;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
/**
@ -40,10 +42,17 @@ import mage.target.targetpointer.FixedTarget;
*/
public class BecomesBlockedByCreatureTriggeredAbility extends TriggeredAbilityImpl {
private static FilterCreaturePermanent filter = new FilterCreaturePermanent();
public BecomesBlockedByCreatureTriggeredAbility(Effect effect, boolean optional) {
super(Zone.BATTLEFIELD, effect, optional);
}
public BecomesBlockedByCreatureTriggeredAbility(Effect effect, FilterCreaturePermanent filter, boolean optional) {
super(Zone.BATTLEFIELD, effect, optional);
this.filter = filter;
}
public BecomesBlockedByCreatureTriggeredAbility(final BecomesBlockedByCreatureTriggeredAbility ability) {
super(ability);
}
@ -56,17 +65,20 @@ public class BecomesBlockedByCreatureTriggeredAbility extends TriggeredAbilityIm
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(this.getSourceId())) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(event.getSourceId()));
Permanent blocker = game.getPermanent(event.getSourceId());
if (filter.match(blocker, game)) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(event.getSourceId()));
}
return true;
}
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever {this} becomes blocked by a creature, " + super.getRule();
return "Whenever {this} becomes blocked by a " + filter.getMessage() + ", " + super.getRule();
}
@Override

View file

@ -32,7 +32,7 @@ import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.SpecialAction;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.condition.common.SuspendedCondition;
@ -142,7 +142,7 @@ import mage.target.targetpointer.FixedTarget;
* @author LevelX2
*
*/
public class SuspendAbility extends ActivatedAbilityImpl {
public class SuspendAbility extends SpecialAction {
private String ruleText;
private boolean gainedTemporary;
@ -160,7 +160,9 @@ public class SuspendAbility extends ActivatedAbilityImpl {
}
public SuspendAbility(int suspend, ManaCost cost, Card card, boolean shortRule) {
super(Zone.HAND, new SuspendExileEffect(suspend), cost);
super(Zone.HAND);
this.addCost(cost);
this.addEffect(new SuspendExileEffect(suspend));
this.usesStack = false;
if (suspend == Integer.MAX_VALUE) {
VariableManaCost xCosts = new VariableManaCost();

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.watchers.common;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.watchers.Watcher;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
*
* @author Quercitron
* @author LevelX2
* @author jeffwadsworth
*/
public class CardsAmountDrawnThisTurnWatcher extends Watcher {
public final static String BASIC_KEY = "CardsAmountDrawnThisTurnWatcher";
private final Map<UUID, Integer> amountOfCardsDrawnThisTurn = new HashMap<>();
public CardsAmountDrawnThisTurnWatcher() {
super(BASIC_KEY, WatcherScope.GAME);
}
public CardsAmountDrawnThisTurnWatcher(final CardsAmountDrawnThisTurnWatcher watcher) {
super(watcher);
amountOfCardsDrawnThisTurn.putAll(watcher.amountOfCardsDrawnThisTurn);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DREW_CARD) {
if (amountOfCardsDrawnThisTurn.containsKey(event.getPlayerId())) {
amountOfCardsDrawnThisTurn.put(event.getPlayerId(), amountOfCardsDrawnThisTurn.get(event.getPlayerId()) + 1);
} else {
amountOfCardsDrawnThisTurn.put(event.getPlayerId(), 1);
}
}
}
@Override
public void reset() {
super.reset();
amountOfCardsDrawnThisTurn.clear();
}
public boolean opponentDrewXOrMoreCards(UUID playerId, int x, Game game) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Map.Entry<UUID, Integer> entry : amountOfCardsDrawnThisTurn.entrySet()) {
if (game.isOpponent(player, entry.getKey())) {
if (entry.getValue() >= x) {
return true;
}
}
}
}
return false;
}
public int getAmountCardsDrawn(UUID playerId) {
Integer amount = amountOfCardsDrawnThisTurn.get(playerId);
if (amount != null) {
return amount;
}
return 0;
}
@Override
public CardsAmountDrawnThisTurnWatcher copy() {
return new CardsAmountDrawnThisTurnWatcher(this);
}
}

View file

@ -2,7 +2,7 @@
[![Join the chat at https://gitter.im/magefree/mage](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/magefree/mage?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
XMage allows you to play Magic against one or more online players or computer opponents. It includes full rules enforcement for over **13,000** unique cards (26,000 counting all cards from different editions). Starting with Shadowmoor, all regular sets have nearly all the cards implemented ([detailed overview](http://ct-magefree.rhcloud.com/stats)).
XMage allows you to play Magic against one or more online players or computer opponents. It includes full rules enforcement for over **13,000** unique cards (over 26,000 counting all cards from different editions). Starting with Morningtide, all regular sets have nearly all the cards implemented ([detailed overview](http://ct-magefree.rhcloud.com/stats)).
There are public servers where you can play XMage against other players. You can also host your own server to play against the AI and/or your friends.