diff --git a/Mage.Sets/src/mage/sets/returntoravnica/KorozdaGuildmage.java b/Mage.Sets/src/mage/sets/returntoravnica/KorozdaGuildmage.java new file mode 100644 index 0000000000..ea152b9f13 --- /dev/null +++ b/Mage.Sets/src/mage/sets/returntoravnica/KorozdaGuildmage.java @@ -0,0 +1,95 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.returntoravnica; + +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.SacrificeCostCreaturesToughness; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continious.BoostTargetEffect; +import mage.abilities.effects.common.continious.GainAbilityTargetEffect; +import mage.abilities.keyword.IntimidateAbility; +import mage.cards.CardImpl; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.permanent.token.SaprolingToken; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class KorozdaGuildmage extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a nontoken creature"); + + static { + filter.add(Predicates.not(new TokenPredicate())); + } + + public KorozdaGuildmage(UUID ownerId) { + super(ownerId, 176, "Korozda Guildmage", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{B}{G}"); + this.expansionSetCode = "RTR"; + this.subtype.add("Elf"); + this.subtype.add("Shaman"); + this.color.setBlack(true); + this.color.setGreen(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {1}{B}{G}: Target creature gets +1/+1 and gains intimidate until end of turn. + Ability ability = new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new BoostTargetEffect(1,1, Constants.Duration.EndOfTurn),new ManaCostsImpl("{1}{B}{G}")); + ability.addEffect(new GainAbilityTargetEffect(IntimidateAbility.getInstance(), Constants.Duration.EndOfTurn)); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // {2}{B}{G}, Sacrifice a nontoken creature: Put X 1/1 green Saproling creature tokens onto the battlefield, where X is the sacrificed creature's toughness. + ability = new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new CreateTokenEffect(new SaprolingToken(),new SacrificeCostCreaturesToughness()),new ManaCostsImpl("{2}{B}{G}")); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1,1,filter, true, true))); + this.addAbility(ability); + + } + + public KorozdaGuildmage(final KorozdaGuildmage card) { + super(card); + } + + @Override + public KorozdaGuildmage copy() { + return new KorozdaGuildmage(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/returntoravnica/TreasuredFind.java b/Mage.Sets/src/mage/sets/returntoravnica/TreasuredFind.java new file mode 100644 index 0000000000..cea7a3d773 --- /dev/null +++ b/Mage.Sets/src/mage/sets/returntoravnica/TreasuredFind.java @@ -0,0 +1,64 @@ +/* + * 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.returntoravnica; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.abilities.effects.common.ExileSpellEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.cards.CardImpl; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author LevelX2 + */ +public class TreasuredFind extends CardImpl { + + public TreasuredFind(UUID ownerId) { + super(ownerId, 204, "Treasured Find", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{B}{G}"); + this.expansionSetCode = "RTR"; + this.color.setBlack(true); + this.color.setGreen(true); + + // Return target card from your graveyard to your hand. Exile Treasured Find. + this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard()); + this.getSpellAbility().addEffect(ExileSpellEffect.getInstance()); + } + + public TreasuredFind(final TreasuredFind card) { + super(card); + } + + @Override + public TreasuredFind copy() { + return new TreasuredFind(this); + } +} diff --git a/Mage.Sets/src/mage/sets/returntoravnica/TrestleTroll.java b/Mage.Sets/src/mage/sets/returntoravnica/TrestleTroll.java new file mode 100644 index 0000000000..724d683b29 --- /dev/null +++ b/Mage.Sets/src/mage/sets/returntoravnica/TrestleTroll.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.returntoravnica; + +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; + +/** + * + * @author LevelX2 + */ +public class TrestleTroll extends CardImpl { + + public TrestleTroll(UUID ownerId) { + super(ownerId, 205, "Trestle Troll", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}{G}"); + this.expansionSetCode = "RTR"; + this.subtype.add("Troll"); + this.color.setBlack(true); + this.color.setGreen(true); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // Reach (This creature can block creatures with flying.) + this.addAbility(ReachAbility.getInstance()); + + // {1}{B}{G}: Regenerate Trestle Troll. + this.addAbility(new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{1}{B}{G}"))); + } + + public TrestleTroll(final TrestleTroll card) { + super(card); + } + + @Override + public TrestleTroll copy() { + return new TrestleTroll(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/returntoravnica/VraskaTheUnseen.java b/Mage.Sets/src/mage/sets/returntoravnica/VraskaTheUnseen.java new file mode 100644 index 0000000000..759108e36a --- /dev/null +++ b/Mage.Sets/src/mage/sets/returntoravnica/VraskaTheUnseen.java @@ -0,0 +1,221 @@ +/* + * 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.returntoravnica; + +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Duration; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.DamagedPlaneswalkerEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.Token; +import mage.game.turn.Step; +import mage.players.Player; +import mage.target.common.TargetNonlandPermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * If an effect creates a copy of one of the Assassin creature tokens, the copy + * will also have the triggered ability. + * + * Each Assassin token's triggered ability will trigger whenever it deals combat + * damage to any player, including you. + * + * + * @author LevelX2 + */ +public class VraskaTheUnseen extends CardImpl { + + public VraskaTheUnseen(UUID ownerId) { + super(ownerId, 208, "Vraska the Unseen", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{3}{B}{G}"); + this.expansionSetCode = "RTR"; + this.subtype.add("Vraska"); + + this.color.setBlack(true); + this.color.setGreen(true); + + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(5)), false)); + + // +1: Until your next turn, whenever a creature deals combat damage to Vraska the Unseen, destroy that creature. + this.addAbility(new LoyaltyAbility(new VraskaTheUnseenGainAbilityEffect(new VraskaTheUnseenTriggeredAbility()),1)); + + // -3: Destroy target nonland permanent. + LoyaltyAbility ability = new LoyaltyAbility(new DestroyTargetEffect(), -3); + ability.addTarget(new TargetNonlandPermanent()); + this.addAbility(ability); + + // -7: Put three 1/1 black Assassin creature tokens onto the battlefield with "Whenever this creature deals combat damage to a player, that player loses the game." + this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new AssassinToken(), 3), -7)); + } + + public VraskaTheUnseen(final VraskaTheUnseen card) { + super(card); + } + + @Override + public VraskaTheUnseen copy() { + return new VraskaTheUnseen(this); + } +} + + +class VraskaTheUnseenGainAbilityEffect extends ContinuousEffectImpl { + + protected Ability ability; + + public VraskaTheUnseenGainAbilityEffect(Ability ability) { + super(Duration.Custom, Constants.Layer.AbilityAddingRemovingEffects_6, Constants.SubLayer.NA, Constants.Outcome.AddAbility); + this.ability = ability; + staticText = "Until your next turn, whenever a creature deals combat damage to Vraska the Unseen, destroy that creature"; + } + + public VraskaTheUnseenGainAbilityEffect(final VraskaTheUnseenGainAbilityEffect effect) { + super(effect); + this.ability = effect.ability.copy(); + } + + @Override + public VraskaTheUnseenGainAbilityEffect copy() { + return new VraskaTheUnseenGainAbilityEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + permanent.addAbility(ability, game); + return true; + } + return false; + } + + @Override + public boolean isInactive(Ability source, Game game) { + if (game.getPhase().getStep().getType() == Constants.PhaseStep.UNTAP && game.getStep().getStepPart() == Step.StepPart.PRE) + { + if (game.getActivePlayerId().equals(source.getControllerId())) { + return true; + } + } + return false; + } +} + +class AssassinToken extends Token { + AssassinToken() { + super("Assassin", "1/1 black Assassin creature tokens with \"Whenever this creature deals combat damage to a player, that player loses the game.\""); + cardType.add(Constants.CardType.CREATURE); + color.setBlack(true); + subtype.add("Assassin"); + power = new MageInt(1); + toughness = new MageInt(1); + addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new VraskaTheUnseenLoseGameEffect(),false, true)); + } +} + +class VraskaTheUnseenLoseGameEffect extends OneShotEffect { + + public VraskaTheUnseenLoseGameEffect() { + super(Constants.Outcome.Damage); + this.staticText = "that player loses the game"; + } + + public VraskaTheUnseenLoseGameEffect(final VraskaTheUnseenLoseGameEffect effect) { + super(effect); + } + + @Override + public VraskaTheUnseenLoseGameEffect copy() { + return new VraskaTheUnseenLoseGameEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player target = game.getPlayer(this.getTargetPointer().getFirst(game, source)); + if (target != null) { + target.lost(game); + return true; + } + return false; + } +} + +class VraskaTheUnseenTriggeredAbility extends TriggeredAbilityImpl { + + public VraskaTheUnseenTriggeredAbility() { + super(Zone.BATTLEFIELD, new DestroyTargetEffect()); + } + + public VraskaTheUnseenTriggeredAbility(final VraskaTheUnseenTriggeredAbility ability) { + super(ability); + } + + @Override + public VraskaTheUnseenTriggeredAbility copy() { + return new VraskaTheUnseenTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.DAMAGED_PLANESWALKER && ((DamagedPlaneswalkerEvent) event).isCombatDamage() && event.getTargetId() == sourceId) { + + Permanent damageSource = game.getPermanent(event.getSourceId()); + if (damageSource != null && damageSource.getCardType().contains(CardType.CREATURE)) { + Effect effect = this.getEffects().get(0); + effect.setTargetPointer(new FixedTarget(damageSource.getId())); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Until your next turn, whenever a creature deals combat damage to Vraska the Unseen, destroy that creature"; + } + +} \ No newline at end of file diff --git a/Mage/src/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesToughness.java b/Mage/src/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesToughness.java new file mode 100644 index 0000000000..411038be33 --- /dev/null +++ b/Mage/src/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesToughness.java @@ -0,0 +1,44 @@ +package mage.abilities.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author LevelX2 + */ +public class SacrificeCostCreaturesToughness implements DynamicValue { + @Override + public int calculate(Game game, Ability sourceAbility) { + for (Cost cost: sourceAbility.getCosts()) { + if (cost instanceof SacrificeTargetCost) { + SacrificeTargetCost sacrificeCost = (SacrificeTargetCost) cost; + int toughnessSum = 0; + for (Permanent permanent :sacrificeCost.getPermanents()) { + toughnessSum += permanent.getToughness().getValue(); + } + return toughnessSum; + } + } + return 0; + } + + @Override + public DynamicValue clone() { + return new SacrificeCostCreaturesToughness(); + } + + @Override + public String toString() { + return "X"; + } + + + @Override + public String getMessage() { + return "the sacrificed creature's toughness"; + } +}