From 601d1be24f0f197da41bd7c3c882a45a47c9eed6 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 26 Mar 2014 16:58:55 +0100 Subject: [PATCH] Added Tidespout Tyrant, Shallow Grave, Xantid Swarm, Goblin War Strike, Wound Reflection, Children of Korlis and Sneak Attack. --- .../championsofkamigawa/ThroughTheBreach.java | 2 +- .../mage/sets/dissension/TidespoutTyrant.java | 72 +++++++++ .../src/mage/sets/mirage/ShallowGrave.java | 123 +++++++++++++++ .../mage/sets/scourge/GoblinWarStrike.java | 74 +++++++++ .../src/mage/sets/scourge/XantidSwarm.java | 148 ++++++++++++++++++ .../mage/sets/shadowmoor/WoundReflection.java | 103 ++++++++++++ .../sets/timespiral/ChildrenOfKorlis.java | 102 ++++++++++++ .../src/mage/sets/urzassaga/SneakAttack.java | 131 ++++++++++++++++ Mage/src/mage/game/GameImpl.java | 2 +- .../common/PlayerLostLifeWatcher.java | 2 +- 10 files changed, 756 insertions(+), 3 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/dissension/TidespoutTyrant.java create mode 100644 Mage.Sets/src/mage/sets/mirage/ShallowGrave.java create mode 100644 Mage.Sets/src/mage/sets/scourge/GoblinWarStrike.java create mode 100644 Mage.Sets/src/mage/sets/scourge/XantidSwarm.java create mode 100644 Mage.Sets/src/mage/sets/shadowmoor/WoundReflection.java create mode 100644 Mage.Sets/src/mage/sets/timespiral/ChildrenOfKorlis.java create mode 100644 Mage.Sets/src/mage/sets/urzassaga/SneakAttack.java diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/ThroughTheBreach.java b/Mage.Sets/src/mage/sets/championsofkamigawa/ThroughTheBreach.java index 281508cd4d..c17f0046f8 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/ThroughTheBreach.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/ThroughTheBreach.java @@ -113,7 +113,7 @@ class ThroughTheBreachEffect extends OneShotEffect { ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom); effect.setTargetPointer(new FixedTarget(permanent.getId())); game.addEffect(effect, source); - SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("sacrifice boosted " + card.getName()); + SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("sacrifice " + card.getName()); sacrificeEffect.setTargetPointer(new FixedTarget(card.getId())); DelayedTriggeredAbility delayedAbility = new AtEndOfTurnDelayedTriggeredAbility(sacrificeEffect); delayedAbility.setSourceId(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/dissension/TidespoutTyrant.java b/Mage.Sets/src/mage/sets/dissension/TidespoutTyrant.java new file mode 100644 index 0000000000..5d289aee1f --- /dev/null +++ b/Mage.Sets/src/mage/sets/dissension/TidespoutTyrant.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.dissension; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.TargetPermanent; + +/** + * + * @author LevelX2 + */ +public class TidespoutTyrant extends CardImpl { + + public TidespoutTyrant(UUID ownerId) { + super(ownerId, 34, "Tidespout Tyrant", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{U}{U}{U}"); + this.expansionSetCode = "DIS"; + this.subtype.add("Djinn"); + + this.color.setBlue(true); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever you cast a spell, return target permanent to its owner's hand. + Ability ability = new SpellCastControllerTriggeredAbility(new ReturnToHandTargetEffect(), false); + ability.addTarget(new TargetPermanent(true)); + this.addAbility(ability); + } + + public TidespoutTyrant(final TidespoutTyrant card) { + super(card); + } + + @Override + public TidespoutTyrant copy() { + return new TidespoutTyrant(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/ShallowGrave.java b/Mage.Sets/src/mage/sets/mirage/ShallowGrave.java new file mode 100644 index 0000000000..c126c7b556 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirage/ShallowGrave.java @@ -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.mirage; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.delayed.AtEndOfTurnDelayedTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.effects.common.continious.GainAbilityTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +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.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class ShallowGrave extends CardImpl { + + public ShallowGrave(UUID ownerId) { + super(ownerId, 39, "Shallow Grave", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{1}{B}"); + this.expansionSetCode = "MIR"; + + this.color.setBlack(true); + + // Return the top creature card of your graveyard to the battlefield. That creature gains haste until end of turn. Exile it at the beginning of the next end step. + this.getSpellAbility().addEffect(new ShallowGraveEffect()); + + } + + public ShallowGrave(final ShallowGrave card) { + super(card); + } + + @Override + public ShallowGrave copy() { + return new ShallowGrave(this); + } +} + +class ShallowGraveEffect extends OneShotEffect { + + public ShallowGraveEffect() { + super(Outcome.Benefit); + this.staticText = "Return the top creature card of your graveyard to the battlefield. That creature gains haste until end of turn. Exile it at the beginning of the next end step"; + } + + public ShallowGraveEffect(final ShallowGraveEffect effect) { + super(effect); + } + + @Override + public ShallowGraveEffect copy() { + return new ShallowGraveEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Card lastCreatureCard = null; + for (Card card :controller.getGraveyard().getCards(game)) { + if (card.getCardType().contains(CardType.CREATURE)) { + lastCreatureCard = card; + } + } + if (lastCreatureCard != null) { + if (controller.putOntoBattlefieldWithInfo(lastCreatureCard, game, Zone.GRAVEYARD, source.getSourceId())) { + FixedTarget fixedTarget = new FixedTarget(lastCreatureCard.getId()); + // Gains Haste + ContinuousEffect hasteEffect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); + hasteEffect.setTargetPointer(fixedTarget); + game.addEffect(hasteEffect, source); + // Exile it at end of turn + ExileTargetEffect exileEffect = new ExileTargetEffect(null,"",Zone.BATTLEFIELD); + exileEffect.setTargetPointer(fixedTarget); + DelayedTriggeredAbility delayedAbility = new AtEndOfTurnDelayedTriggeredAbility(exileEffect); + delayedAbility.setSourceId(source.getSourceId()); + delayedAbility.setControllerId(source.getControllerId()); + game.addDelayedTriggeredAbility(delayedAbility); + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/scourge/GoblinWarStrike.java b/Mage.Sets/src/mage/sets/scourge/GoblinWarStrike.java new file mode 100644 index 0000000000..e5f712bec1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/scourge/GoblinWarStrike.java @@ -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.scourge; + +import java.util.UUID; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.TargetPlayer; + +/** + * + * @author LevelX2 + */ +public class GoblinWarStrike extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Goblins you control"); + + static { + filter.add(new SubtypePredicate("Goblin")); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public GoblinWarStrike(UUID ownerId) { + super(ownerId, 96, "Goblin War Strike", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{R}"); + this.expansionSetCode = "SCG"; + + this.color.setRed(true); + + // Goblin War Strike deals damage equal to the number of Goblins you control to target player. + this.getSpellAbility().addEffect(new DamageTargetEffect(new PermanentsOnBattlefieldCount(filter))); + this.getSpellAbility().addTarget(new TargetPlayer(true)); + } + + public GoblinWarStrike(final GoblinWarStrike card) { + super(card); + } + + @Override + public GoblinWarStrike copy() { + return new GoblinWarStrike(this); + } +} diff --git a/Mage.Sets/src/mage/sets/scourge/XantidSwarm.java b/Mage.Sets/src/mage/sets/scourge/XantidSwarm.java new file mode 100644 index 0000000000..c109e1ea05 --- /dev/null +++ b/Mage.Sets/src/mage/sets/scourge/XantidSwarm.java @@ -0,0 +1,148 @@ +/* + * 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.scourge; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.keyword.FlyingAbility; +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.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class XantidSwarm extends CardImpl { + + public XantidSwarm(UUID ownerId) { + super(ownerId, 135, "Xantid Swarm", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{G}"); + this.expansionSetCode = "SCG"; + this.subtype.add("Insect"); + + this.color.setGreen(true); + this.power = new MageInt(0); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever Xantid Swarm attacks, defending player can't cast spells this turn. + Ability ability = new XantidSwarmTriggeredAbility(new XantidSwarmReplacementEffect()); + + this.addAbility(ability); + } + + public XantidSwarm(final XantidSwarm card) { + super(card); + } + + @Override + public XantidSwarm copy() { + return new XantidSwarm(this); + } +} + +class XantidSwarmTriggeredAbility extends TriggeredAbilityImpl { + + public XantidSwarmTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect); + } + + public XantidSwarmTriggeredAbility(final XantidSwarmTriggeredAbility ability) { + super(ability); + } + + @Override + public XantidSwarmTriggeredAbility copy() { + return new XantidSwarmTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(this.getSourceId())) { + UUID defender = game.getCombat().getDefendingPlayerId(this.getSourceId(), game); + this.getEffects().get(0).setTargetPointer(new FixedTarget(defender)); + return true; + } + return false; + } + + @Override + public String getRule() { + return new StringBuilder("Whenever {this} attacks, ").append(super.getRule()).toString(); + } +} + +class XantidSwarmReplacementEffect extends ReplacementEffectImpl { + + public XantidSwarmReplacementEffect() { + super(Duration.EndOfTurn, Outcome.Benefit); + staticText = "defending player can't cast spells this turn"; + } + + public XantidSwarmReplacementEffect(final XantidSwarmReplacementEffect effect) { + super(effect); + } + + @Override + public XantidSwarmReplacementEffect copy() { + return new XantidSwarmReplacementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.CAST_SPELL ) { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null && player.getId().equals(event.getPlayerId())) { + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/WoundReflection.java b/Mage.Sets/src/mage/sets/shadowmoor/WoundReflection.java new file mode 100644 index 0000000000..85a92f22fd --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/WoundReflection.java @@ -0,0 +1,103 @@ +/* + * 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.shadowmoor; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.game.Game; +import mage.players.Player; +import mage.watchers.common.PlayerLostLifeWatcher; + +/** + * + * @author LevelX2 + */ +public class WoundReflection extends CardImpl { + + public WoundReflection(UUID ownerId) { + super(ownerId, 81, "Wound Reflection", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{5}{B}"); + this.expansionSetCode = "SHM"; + + this.color.setBlack(true); + + // At the beginning of each end step, each opponent loses life equal to the life he or she lost this turn. + this.addAbility(new BeginningOfEndStepTriggeredAbility(new WoundReflectionEffect(), TargetController.ANY, false)); + } + + public WoundReflection(final WoundReflection card) { + super(card); + } + + @Override + public WoundReflection copy() { + return new WoundReflection(this); + } +} + +class WoundReflectionEffect extends OneShotEffect { + + public WoundReflectionEffect() { + super(Outcome.LoseLife); + this.staticText = "each opponent loses life equal to the life he or she lost this turn"; + } + + public WoundReflectionEffect(final WoundReflectionEffect effect) { + super(effect); + } + + @Override + public WoundReflectionEffect copy() { + return new WoundReflectionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get("PlayerLostLifeWatcher"); + if (controller != null && watcher != null) { + for (UUID playerId : game.getOpponents(controller.getId())) { + Player opponent = game.getPlayer(playerId); + if (opponent != null) { + int lifeLost = watcher.getLiveLost(playerId); + if (lifeLost > 0) { + opponent.loseLife(lifeLost, game); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/ChildrenOfKorlis.java b/Mage.Sets/src/mage/sets/timespiral/ChildrenOfKorlis.java new file mode 100644 index 0000000000..36e3d8e8a4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/ChildrenOfKorlis.java @@ -0,0 +1,102 @@ +/* + * 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.timespiral; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.watchers.common.PlayerLostLifeWatcher; + +/** + * + * @author LevelX2 + */ +public class ChildrenOfKorlis extends CardImpl { + + public ChildrenOfKorlis(UUID ownerId) { + super(ownerId, 8, "Children of Korlis", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{W}"); + this.expansionSetCode = "TSP"; + this.subtype.add("Human"); + this.subtype.add("Rebel"); + this.subtype.add("Cleric"); + + this.color.setWhite(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Sacrifice Children of Korlis: You gain life equal to the life you've lost this turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, + new GainLifeEffect(new SourceControllerLostLifeCount(),"You gain life equal to the life you've lost this turn"), + new SacrificeSourceCost())); + } + + public ChildrenOfKorlis(final ChildrenOfKorlis card) { + super(card); + } + + @Override + public ChildrenOfKorlis copy() { + return new ChildrenOfKorlis(this); + } +} + +class SourceControllerLostLifeCount implements DynamicValue { + + @Override + public int calculate(Game game, Ability sourceAbility) { + PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get("PlayerLostLifeWatcher"); + if (watcher != null) { + return watcher.getLiveLost(sourceAbility.getControllerId()); + } + return 0; + } + + @Override + public DynamicValue copy() { + return new SourceControllerLostLifeCount(); + } + + @Override + public String toString() { + return "X"; + } + + @Override + public String getMessage() { + return "life you've lost this turn"; + } +} diff --git a/Mage.Sets/src/mage/sets/urzassaga/SneakAttack.java b/Mage.Sets/src/mage/sets/urzassaga/SneakAttack.java new file mode 100644 index 0000000000..4dd848ab3a --- /dev/null +++ b/Mage.Sets/src/mage/sets/urzassaga/SneakAttack.java @@ -0,0 +1,131 @@ +/* + * 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.urzassaga; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.delayed.AtEndOfTurnDelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.abilities.effects.common.continious.GainAbilityTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +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.FilterCreatureCard; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInHand; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class SneakAttack extends CardImpl { + + public SneakAttack(UUID ownerId) { + super(ownerId, 218, "Sneak Attack", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); + this.expansionSetCode = "USG"; + + this.color.setRed(true); + + // {R}: You may put a creature card from your hand onto the battlefield. That creature gains haste. Sacrifice the creature at the beginning of the next end step. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new SneakAttackEffect(), new ManaCostsImpl("{R}"))); + } + + public SneakAttack(final SneakAttack card) { + super(card); + } + + @Override + public SneakAttack copy() { + return new SneakAttack(this); + } +} + +class SneakAttackEffect extends OneShotEffect { + + private static final String choiceText = "Put a creature card from your hand onto the battlefield?"; + + public SneakAttackEffect() { + super(Outcome.Benefit); + this.staticText = "You may put a creature card from your hand onto the battlefield. That creature gains haste. Sacrifice the creature at the beginning of the next end step"; + } + + public SneakAttackEffect(final SneakAttackEffect effect) { + super(effect); + } + + @Override + public SneakAttackEffect copy() { + return new SneakAttackEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + if (player.chooseUse(Outcome.PutCreatureInPlay, choiceText, game)) { + TargetCardInHand target = new TargetCardInHand(new FilterCreatureCard()); + if (player.choose(Outcome.PutCreatureInPlay, target, source.getSourceId(), game)) { + Card card = game.getCard(target.getFirstTarget()); + if (card != null) { + if (player.putOntoBattlefieldWithInfo(card, game, Zone.HAND, source.getSourceId())) { + Permanent permanent = game.getPermanent(card.getId()); + ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom); + effect.setTargetPointer(new FixedTarget(permanent.getId())); + game.addEffect(effect, source); + + SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("sacrifice " + card.getName()); + sacrificeEffect.setTargetPointer(new FixedTarget(card.getId())); + DelayedTriggeredAbility delayedAbility = new AtEndOfTurnDelayedTriggeredAbility(sacrificeEffect); + delayedAbility.setSourceId(source.getSourceId()); + delayedAbility.setControllerId(source.getControllerId()); + game.addDelayedTriggeredAbility(delayedAbility); + + return true; + } + } + return false; + } + } + return true; + } + return false; + } +} diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 57836d15e5..54333661cc 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -1172,7 +1172,7 @@ public abstract class GameImpl> implements Game, Serializa @Override public void addDelayedTriggeredAbility(DelayedTriggeredAbility delayedAbility) { - DelayedTriggeredAbility newAbility = (DelayedTriggeredAbility) delayedAbility.copy(); + DelayedTriggeredAbility newAbility = delayedAbility.copy(); newAbility.newId(); state.addDelayedTriggeredAbility(newAbility); } diff --git a/Mage/src/mage/watchers/common/PlayerLostLifeWatcher.java b/Mage/src/mage/watchers/common/PlayerLostLifeWatcher.java index 57fce02753..4bd73ad2fc 100644 --- a/Mage/src/mage/watchers/common/PlayerLostLifeWatcher.java +++ b/Mage/src/mage/watchers/common/PlayerLostLifeWatcher.java @@ -47,7 +47,7 @@ import mage.watchers.WatcherImpl; */ public class PlayerLostLifeWatcher extends WatcherImpl { - private Map amountOfLifeLostThisTurn = new HashMap(); + private final Map amountOfLifeLostThisTurn = new HashMap<>(); public PlayerLostLifeWatcher() { super("PlayerLostLifeWatcher", WatcherScope.GAME);