From 4c25816be1de18a6dfaf5e13642875f60620bea1 Mon Sep 17 00:00:00 2001 From: MarcoMarin Date: Tue, 19 Apr 2016 12:50:48 -0300 Subject: [PATCH 1/3] midway through FEM + fixed Oubliette, Tawnos Coffin --- .../mage/sets/antiquities/TawnossCoffin.java | 163 +++++++++++++++++- .../mage/sets/arabiannights/Oubliette.java | 53 +++--- .../mage/sets/fallenempires/DelifsCone.java | 104 +++++++++++ .../mage/sets/fallenempires/DelifsCube.java | 119 +++++++++++++ .../sets/fallenempires/DwarvenSoldier.java | 71 ++++++++ .../sets/fallenempires/FarrelitePriest.java | 139 +++++++++++++++ .../sets/fallenempires/FarrelsMantle.java | 138 +++++++++++++++ .../sets/fallenempires/GoblinFlotilla.java | 92 ++++++++++ .../mage/sets/fallenempires/GoblinKites.java | 118 +++++++++++++ .../fallenempires/InitiatesOfTheEbonHand.java | 139 +++++++++++++++ .../src/mage/sets/fallenempires/Necrite.java | 110 ++++++++++++ .../src/mage/sets/fallenempires/Orgg.java | 54 ++++++ .../mage/sets/fallenempires/SoulExchange.java | 52 ++++++ .../sets/fifthedition/DwarvenSoldier.java | 52 ++++++ .../fifthedition/InitiatesOfTheEbonHand.java | 52 ++++++ .../src/mage/sets/fifthedition/Necrite.java | 52 ++++++ .../src/mage/sets/fifthedition/Orgg.java | 54 ++++++ .../sets/mastersedition/DwarvenSoldier.java | 52 ++++++ .../sets/masterseditionii/FarrelsMantle.java | 52 ++++++ .../mage/sets/masterseditionii/Necrite.java | 52 ++++++ .../sets/masterseditionii/SoulExchange.java | 111 ++++++++++++ Mage.Sets/src/mage/sets/timeshifted/Orgg.java | 87 ++++++++++ .../common/DoUnlessControllerPaysEffect.java | 135 +++++++++++++++ .../main/java/mage/counters/CounterType.java | 1 + 24 files changed, 2022 insertions(+), 30 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/fallenempires/DelifsCone.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/DelifsCube.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/DwarvenSoldier.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/FarrelsMantle.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/GoblinFlotilla.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/GoblinKites.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/Necrite.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/Orgg.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/SoulExchange.java create mode 100644 Mage.Sets/src/mage/sets/fifthedition/DwarvenSoldier.java create mode 100644 Mage.Sets/src/mage/sets/fifthedition/InitiatesOfTheEbonHand.java create mode 100644 Mage.Sets/src/mage/sets/fifthedition/Necrite.java create mode 100644 Mage.Sets/src/mage/sets/fifthedition/Orgg.java create mode 100644 Mage.Sets/src/mage/sets/mastersedition/DwarvenSoldier.java create mode 100644 Mage.Sets/src/mage/sets/masterseditionii/FarrelsMantle.java create mode 100644 Mage.Sets/src/mage/sets/masterseditionii/Necrite.java create mode 100644 Mage.Sets/src/mage/sets/masterseditionii/SoulExchange.java create mode 100644 Mage.Sets/src/mage/sets/timeshifted/Orgg.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DoUnlessControllerPaysEffect.java diff --git a/Mage.Sets/src/mage/sets/antiquities/TawnossCoffin.java b/Mage.Sets/src/mage/sets/antiquities/TawnossCoffin.java index e51da975d0..7ef027a2ce 100644 --- a/Mage.Sets/src/mage/sets/antiquities/TawnossCoffin.java +++ b/Mage.Sets/src/mage/sets/antiquities/TawnossCoffin.java @@ -36,14 +36,28 @@ import mage.abilities.common.SkipUntapOptionalAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTargetForSourceEffect; import mage.abilities.effects.common.ReturnFromExileForSourceEffect; +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.counters.Counter; +import mage.counters.Counters; +import mage.filter.Filter; +import mage.filter.FilterCard; +import mage.filter.common.FilterEnchantmentPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.Token; +import mage.target.Target; import mage.target.common.TargetCreaturePermanent; /** @@ -52,6 +66,8 @@ import mage.target.common.TargetCreaturePermanent; */ public class TawnossCoffin extends CardImpl { + public Counters godHelpMe=null; + public TawnossCoffin(UUID ownerId) { super(ownerId, 33, "Tawnos's Coffin", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}"); this.expansionSetCode = "ATQ"; @@ -59,15 +75,15 @@ public class TawnossCoffin extends CardImpl { // You may choose not to untap Tawnos's Coffin during your untap step. this.addAbility(new SkipUntapOptionalAbility()); // {3}, {tap}: Exile target creature and all Auras attached to it. Note the number and kind of counters that were on that creature. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetForSourceEffect(), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TawnossCoffinEffect(), new TapSourceCost()); ability.addCost(new ManaCostsImpl("{3}")); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); //When Tawnos's Coffin leaves the battlefield... - Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD, true), false); + Ability ability2 = new LeavesBattlefieldTriggeredAbility(new TawnossCoffinReturnEffect(), false); this.addAbility(ability2); //or becomes untapped, return the exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it, and if you do, return the exiled Aura cards to the battlefield under their owner's control attached to that permanent. - Ability ability3 = new BecomesUnTappedSourceTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD, true), false); + Ability ability3 = new BecomesUnTappedSourceTriggeredAbility(new TawnossCoffinReturnEffect(), false); this.addAbility(ability3); } @@ -113,4 +129,143 @@ class BecomesUnTappedSourceTriggeredAbility extends TriggeredAbilityImpl { public String getRule() { return "When {this} becomes untapped, " + super.getRule(); } -} \ No newline at end of file +} + + +class TawnossCoffinEffect extends OneShotEffect { + + private static final FilterEnchantmentPermanent filter = new FilterEnchantmentPermanent(); + + static { + filter.add(new SubtypePredicate("Aura")); + } + + public TawnossCoffinEffect() { + super(Outcome.Detriment); + this.staticText = "Exile target creature and all Auras attached to it. Note the number and kind of counters that were on that creature. When TawnossCoffin leaves the battlefield, return the exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the exiled Aura cards to the battlefield under their owner's control attached to that permanent."; + } + + public TawnossCoffinEffect(final TawnossCoffinEffect effect) { + super(effect); + } + + @Override + public TawnossCoffinEffect copy() { + return new TawnossCoffinEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + // Exile enchanted creature and all Auras attached to it. + Permanent enchantment = game.getPermanent(source.getSourceId()); + if (enchantment == null) { + enchantment = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); + } + UUID targetId=source.getFirstTarget(); + + if (targetId==null) return false; // if previous scan somehow failed, simply quit + + if (enchantment != null) { //back to code (mostly) copied from Flickerform + Permanent enchantedCreature = game.getPermanent(targetId); + if (enchantedCreature != null) { + UUID exileZoneId = source.getSourceId(); + enchantedCreature.moveToExile(exileZoneId, enchantment.getName(), source.getSourceId(), game); + for (UUID attachementId : enchantedCreature.getAttachments()) { + Permanent attachment = game.getPermanent(attachementId); + if (attachment != null && filter.match(attachment, game)) { + attachment.moveToExile(exileZoneId, enchantment.getName(), source.getSourceId(), game); + } + } + + //((TawnossCoffin)enchantment.getMainCard()).godHelpMe = enchantedCreature.getCounters(game); //why doesn't work? should return the same card, no? + ((TawnossCoffin)game.getCard(source.getSourceId())).godHelpMe = enchantedCreature.getCounters(game).copy(); + + if (!(enchantedCreature instanceof Token)) { + + // If you do, return the other cards exiled this way to the battlefield under their owners' control attached to that creature + /*LeavesBattlefieldTriggeredAbility triggeredAbility = new LeavesBattlefieldTriggeredAbility( + new TawnossCoffinReturnEffect(), false); + enchantment.addAbility(triggeredAbility, source.getSourceId(), game); + */ + } + return true; + } + } + + return false; + } +} + +class TawnossCoffinReturnEffect extends OneShotEffect { + + private static final FilterCard filterAura = new FilterCard(); + + static { + filterAura.add(new CardTypePredicate(CardType.ENCHANTMENT)); + filterAura.add(new SubtypePredicate("Aura")); + } + + + public TawnossCoffinReturnEffect() { + super(Outcome.Benefit); + this.staticText = "return the exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the exiled Aura cards to the battlefield under their owner's control attached to that permanent."; + + } + + public TawnossCoffinReturnEffect(final TawnossCoffinReturnEffect effect) { + super(effect); + } + + @Override + public TawnossCoffinReturnEffect copy() { + return new TawnossCoffinReturnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + ExileZone exileZone = game.getExile().getExileZone(source.getSourceId()); + + FilterCard filter = new FilterCard(); + filter.add(new CardTypePredicate(CardType.CREATURE)); + //There should be only 1 there, but the for each loop seems the most practical to get to it + for (Card enchantedCard : exileZone.getCards(filter, game)){ + if (enchantedCard == null) continue; + enchantedCard.putOntoBattlefield(game, Zone.EXILED, source.getSourceId(), enchantedCard.getOwnerId()); + Permanent newPermanent = game.getPermanent(enchantedCard.getId()); + if (newPermanent != null) { + newPermanent.tap(game); + for (Card enchantment : exileZone.getCards(game)) { + if (filterAura.match(enchantment, game)) { + boolean canTarget = false; + for (Target target : enchantment.getSpellAbility().getTargets()) { + Filter filter2 = target.getFilter(); + if (filter2.match(newPermanent, game)) { + canTarget = true; + break; + } + } + if (!canTarget) { + // Aura stays exiled + continue; + } + game.getState().setValue("attachTo:" + enchantment.getId(), newPermanent); + } + if (enchantment.putOntoBattlefield(game, Zone.EXILED, source.getSourceId(), enchantment.getOwnerId())) { + if (filterAura.match(enchantment, game)) { + newPermanent.addAttachment(enchantment.getId(), game); + } + } + } + Card oubliette = game.getCard(source.getSourceId()); + if (oubliette == null) return false;//1st stab at getting those counters back + for(Counter c : ((TawnossCoffin)oubliette).godHelpMe.values()){ //would be nice if could just use that copy function to set the whole field + if(c!=null) newPermanent.getCounters(game).addCounter(c); + } + + } + return true; + } + + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/arabiannights/Oubliette.java b/Mage.Sets/src/mage/sets/arabiannights/Oubliette.java index ec1e072e2a..f098891b36 100644 --- a/Mage.Sets/src/mage/sets/arabiannights/Oubliette.java +++ b/Mage.Sets/src/mage/sets/arabiannights/Oubliette.java @@ -74,8 +74,8 @@ public class Oubliette extends CardImpl { this.addAbility(ability1); // When Oubliette leaves the battlefield, return the exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the exiled Aura cards to the battlefield under their owner's control attached to that permanent. - //Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD, true), false); - //this.addAbility(ability2); + Ability ability2 = new LeavesBattlefieldTriggeredAbility(new OublietteReturnEffect(), false); + this.addAbility(ability2); } public Oubliette(final Oubliette card) { @@ -99,7 +99,7 @@ class OublietteEffect extends OneShotEffect { public OublietteEffect() { super(Outcome.Detriment); - this.staticText = "4Exile target creature and all Auras attached to it. Note the number and kind of counters that were on that creature. When Oubliette leaves the battlefield, return the exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the exiled Aura cards to the battlefield under their owner's control attached to that permanent."; + this.staticText = "Exile target creature and all Auras attached to it. Note the number and kind of counters that were on that creature. When Oubliette leaves the battlefield, return the exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the exiled Aura cards to the battlefield under their owner's control attached to that permanent."; } public OublietteEffect(final OublietteEffect effect) { @@ -125,7 +125,7 @@ class OublietteEffect extends OneShotEffect { if (enchantment != null) { //back to code (mostly) copied from Flickerform Permanent enchantedCreature = game.getPermanent(targetId); if (enchantedCreature != null) { - UUID exileZoneId = UUID.randomUUID(); + UUID exileZoneId = source.getSourceId(); enchantedCreature.moveToExile(exileZoneId, enchantment.getName(), source.getSourceId(), game); for (UUID attachementId : enchantedCreature.getAttachments()) { Permanent attachment = game.getPermanent(attachementId); @@ -134,16 +134,20 @@ class OublietteEffect extends OneShotEffect { } } - //((Oubliette)enchantment.getMainCard()).godHelpMe = enchantedCreature.getCounters(game); - //((Oubliette)game.getCard(source.getSourceId())).godHelpMe = enchantedCreature.getCounters(game).copy(); - + //((Oubliette)enchantment.getMainCard()).godHelpMe = enchantedCreature.getCounters(game); //why doesn't work? should return the same card, no? + ((Oubliette)game.getCard(source.getSourceId())).godHelpMe = enchantedCreature.getCounters(game).copy(); + /* if (!(enchantedCreature instanceof Token)) { // If you do, return the other cards exiled this way to the battlefield under their owners' control attached to that creature LeavesBattlefieldTriggeredAbility triggeredAbility = new LeavesBattlefieldTriggeredAbility( - new OublietteReturnEffect(enchantedCreature.getId(), exileZoneId, enchantment), false); - enchantment.addAbility(triggeredAbility, source.getSourceId(), game); - } + new OublietteReturnEffect(), false); + //enchantment.addAbility(triggeredAbility, source.getSourceId(), game, false); + //Card card = game.getCard(source.getSourceId()); + //game.getState().addOtherAbility(card, triggeredAbility); + + + }*/ return true; } } @@ -161,24 +165,15 @@ class OublietteReturnEffect extends OneShotEffect { filterAura.add(new SubtypePredicate("Aura")); } - private final UUID enchantedCardId; - private final UUID exileZoneId; - private final Permanent oubliette; - public OublietteReturnEffect(UUID enchantedCardId, UUID exileZoneId, Permanent oubliette) { + public OublietteReturnEffect() { super(Outcome.Benefit); - this.enchantedCardId = enchantedCardId; - this.exileZoneId = exileZoneId; - this.oubliette = oubliette; this.staticText = "return the exiled card to the battlefield under its owner's control tapped with the noted number and kind of counters on it. If you do, return the exiled Aura cards to the battlefield under their owner's control attached to that permanent."; } public OublietteReturnEffect(final OublietteReturnEffect effect) { super(effect); - this.enchantedCardId = effect.enchantedCardId; - this.exileZoneId = effect.exileZoneId; - this.oubliette = effect.oubliette; } @Override @@ -188,19 +183,23 @@ class OublietteReturnEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - ExileZone exileZone = game.getExile().getExileZone(exileZoneId); - Card enchantedCard = exileZone.get(enchantedCardId, game); - if (enchantedCard != null) { + ExileZone exileZone = game.getExile().getExileZone(source.getSourceId()); + + FilterCard filter = new FilterCard(); + filter.add(new CardTypePredicate(CardType.CREATURE)); + //There should be only 1 there, but the for each loop seems the most practical to get to it + for (Card enchantedCard : exileZone.getCards(filter, game)){ + if (enchantedCard == null) continue; enchantedCard.putOntoBattlefield(game, Zone.EXILED, source.getSourceId(), enchantedCard.getOwnerId()); - Permanent newPermanent = game.getPermanent(enchantedCardId); + Permanent newPermanent = game.getPermanent(enchantedCard.getId()); if (newPermanent != null) { newPermanent.tap(game); for (Card enchantment : exileZone.getCards(game)) { if (filterAura.match(enchantment, game)) { boolean canTarget = false; for (Target target : enchantment.getSpellAbility().getTargets()) { - Filter filter = target.getFilter(); - if (filter.match(newPermanent, game)) { + Filter filter2 = target.getFilter(); + if (filter2.match(newPermanent, game)) { canTarget = true; break; } @@ -217,6 +216,7 @@ class OublietteReturnEffect extends OneShotEffect { } } } + Card oubliette = game.getCard(source.getSourceId()); if (oubliette == null) return false;//1st stab at getting those counters back for(Counter c : ((Oubliette)oubliette).godHelpMe.values()){ //would be nice if could just use that copy function to set the whole field if(c!=null) newPermanent.getCounters(game).addCounter(c); @@ -225,6 +225,7 @@ class OublietteReturnEffect extends OneShotEffect { } return true; } + return false; } } diff --git a/Mage.Sets/src/mage/sets/fallenempires/DelifsCone.java b/Mage.Sets/src/mage/sets/fallenempires/DelifsCone.java new file mode 100644 index 0000000000..1fa452762d --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/DelifsCone.java @@ -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.fallenempires; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +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.permanent.Permanent; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author MarcoMarin + */ +public class DelifsCone extends CardImpl { + + public DelifsCone(UUID ownerId) { + super(ownerId, 169, "Delif's Cone", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{0}"); + this.expansionSetCode = "FEM"; + + Ability ability2 = new AttacksAndIsNotBlockedTriggeredAbility(new DelifsConeEffect(), true); + ability2.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn)); + // {tap}, Sacrifice Delif's Cone: This turn, when target creature you control attacks and isn't blocked, you may gain life equal to its power. If you do, it assigns no combat damage this turn. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new GainAbilityTargetEffect(ability2, Duration.EndOfTurn), + new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetControlledCreaturePermanent()); + + this.addAbility(ability); + + } + + public DelifsCone(final DelifsCone card) { + super(card); + } + + @Override + public DelifsCone copy() { + return new DelifsCone(this); + } +} +class DelifsConeEffect extends OneShotEffect{ + + public DelifsConeEffect() { + super(Outcome.Damage); + this.setText("you may gain life equal to its power"); + } + + public DelifsConeEffect(final DelifsConeEffect effect) { + super(effect); + } + + @Override + public DelifsConeEffect copy() { + return new DelifsConeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent perm = game.getPermanent(source.getSourceId()); + GainLifeEffect lifeEffect = new GainLifeEffect(perm.getPower().getValue()); + return lifeEffect.apply(game, source); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fallenempires/DelifsCube.java b/Mage.Sets/src/mage/sets/fallenempires/DelifsCube.java new file mode 100644 index 0000000000..1e129dda28 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/DelifsCube.java @@ -0,0 +1,119 @@ +/* + * 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.fallenempires; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.RegenerateTargetEffect; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +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.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author MarcoMarin + */ +public class DelifsCube extends CardImpl { + + public DelifsCube(UUID ownerId) { + super(ownerId, 170, "Delif's Cube", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{1}"); + this.expansionSetCode = "FEM"; + + Ability ability2 = new AttacksAndIsNotBlockedTriggeredAbility(new DelifsCubeEffect(this.getId()), false); + ability2.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn)); + // {2}, {tap}: This turn, when target creature you control attacks and isn't blocked, it assigns no combat damage this turn and you put a cube counter on Delif's Cube. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new GainAbilityTargetEffect(ability2, Duration.EndOfTurn), + new ManaCostsImpl("{2}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetControlledCreaturePermanent()); + + this.addAbility(ability); + // {2}, Remove a cube counter from Delif's Cube: Regenerate target creature. + SimpleActivatedAbility ability3 = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new RegenerateTargetEffect(), + new ManaCostsImpl("{2}")); + ability3.addCost(new RemoveCountersSourceCost(CounterType.CUBE.createInstance())); + ability3.addTarget(new TargetControlledCreaturePermanent()); + + this.addAbility(ability3); + } + + public DelifsCube(final DelifsCube card) { + super(card); + } + + @Override + public DelifsCube copy() { + return new DelifsCube(this); + } +} + +class DelifsCubeEffect extends OneShotEffect{ + + private UUID cubeId; + + public DelifsCubeEffect(UUID cubeId) { + super(Outcome.Benefit); + this.cubeId = cubeId; + this.setText("This turn, when target creature you control attacks and isn't blocked, it assigns no combat damage this turn and you put a cube counter on Delif's Cube."); + } + + public DelifsCubeEffect(final DelifsCubeEffect effect) { + super(effect); + this.cubeId = effect.cubeId; + } + + @Override + public DelifsCubeEffect copy() { + return new DelifsCubeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent perm = game.getPermanent(cubeId); + if (perm == null) return false; + perm.addCounters(CounterType.CUBE.createInstance(), game); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fallenempires/DwarvenSoldier.java b/Mage.Sets/src/mage/sets/fallenempires/DwarvenSoldier.java new file mode 100644 index 0000000000..a8400e5e08 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/DwarvenSoldier.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.BlocksOrBecomesBlockedByCreatureTriggeredAbility; +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.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author MarcoMarin + */ +public class DwarvenSoldier extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Orc", "Orc creature"); + + public DwarvenSoldier(UUID ownerId) { + super(ownerId, 107, "Dwarven Soldier", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Dwarf"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Whenever Dwarven Soldier blocks or becomes blocked by one or more Orcs, Dwarven Soldier gets +0/+2 until end of turn. + this.addAbility(new BlocksOrBecomesBlockedByCreatureTriggeredAbility(new BoostSourceEffect(0, 2, Duration.EndOfTurn), filter, false)); + } + + public DwarvenSoldier(final DwarvenSoldier card) { + super(card); + } + + @Override + public DwarvenSoldier copy() { + return new DwarvenSoldier(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java b/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java new file mode 100644 index 0000000000..8378dda0a8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java @@ -0,0 +1,139 @@ +/* + * 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.fallenempires; + +import java.util.UUID; +import mage.MageInt; +import static mage.Mana.WhiteMana; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.BasicManaEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author MarcoMarin + */ +public class FarrelitePriest extends CardImpl { + + public FarrelitePriest(UUID ownerId) { + super(ownerId, 137, "Farrelite Priest", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Human"); + this.subtype.add("Cleric"); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // {1}: Add {W} to your mana pool. If this ability has been activated four or more times this turn, sacrifice Farrelite Priest at the beginning of the next end step. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new BasicManaEffect(WhiteMana(1)), + new ManaCostsImpl("{1}")); + ability.addEffect(new FarrelitePriestEffect()); + this.addAbility(ability); + } + + public FarrelitePriest(final FarrelitePriest card) { + super(card); + } + + @Override + public FarrelitePriest copy() { + return new FarrelitePriest(this); + } +} +class FarrelitePriestEffect extends OneShotEffect { + + public FarrelitePriestEffect() { + super(Outcome.Damage); + this.staticText = "If this ability has been activated four or more times this turn, sacrifice {this} at the beginning of the next end step"; + } + + public FarrelitePriestEffect(final FarrelitePriestEffect effect) { + super(effect); + } + + @Override + public FarrelitePriestEffect copy() { + return new FarrelitePriestEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "FarrelitePriest"); + if (amount == null) { + amount = 0; + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new FarrelitePriestResetEffect()); + game.addDelayedTriggeredAbility(delayedAbility, source); + } + amount++; + game.getState().setValue(source.getSourceId().toString() + "FarrelitePriest", amount); + + return true; + } +} + +class FarrelitePriestResetEffect extends OneShotEffect { + + public FarrelitePriestResetEffect() { + super(Outcome.Neutral); + this.staticText = "If this ability has been activated four or more times this turn, sacrifice {this} at the beginning of the next end step"; + } + + public FarrelitePriestResetEffect(final FarrelitePriestResetEffect effect) { + super(effect); + } + + @Override + public FarrelitePriestResetEffect copy() { + return new FarrelitePriestResetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "FarrelitePriest"); + if (amount != null && amount >= 4) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + permanent.sacrifice(source.getSourceId(), game); + } + } + game.getState().setValue(source.getSourceId().toString() + "FarrelitePriest", null); + + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fallenempires/FarrelsMantle.java b/Mage.Sets/src/mage/sets/fallenempires/FarrelsMantle.java new file mode 100644 index 0000000000..ad62e3c1bf --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/FarrelsMantle.java @@ -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.fallenempires; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +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.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.game.permanent.Permanent; + +/** + * + * @author MarcoMarin + */ +public class FarrelsMantle extends CardImpl { + + + public FarrelsMantle(UUID ownerId) { + super(ownerId, 138, "Farrel's Mantle", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Whenever enchanted creature attacks and isn't blocked, its controller may have it deal damage equal to its power plus 2 to another target creature. If that player does, the attacking creature assigns no combat damage this turn. + FilterPermanent filter = new FilterCreaturePermanent(); + filter.add(Predicates.not(new AttachmentByUUIDPredicate(this.getId()))); + + Ability ability2 = new AttacksAndIsNotBlockedTriggeredAbility(new FarrelsMantleEffect(), true); + ability2.addTarget(new TargetPermanent(filter)); + ability2.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn)); + + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(ability2, AttachmentType.AURA))); + + } + + public FarrelsMantle(final FarrelsMantle card) { + super(card); + } + + @Override + public FarrelsMantle copy() { + return new FarrelsMantle(this); + } +} +class AttachmentByUUIDPredicate implements Predicate { + + private final UUID id; + + public AttachmentByUUIDPredicate(UUID id) { + this.id = id; + } + + @Override + public boolean apply(Permanent input, Game game) { + return input.getAttachments().contains(id); + } + + @Override + public String toString() { + return "AttachmentUUID(" + id + ')'; + } +} + +class FarrelsMantleEffect extends OneShotEffect{ + + public FarrelsMantleEffect() { + super(Outcome.Damage); + this.setText("its controller may have it deal damage equal to its power plus 2 to another target creature."); + } + + public FarrelsMantleEffect(final FarrelsMantleEffect effect) { + super(effect); + } + + @Override + public FarrelsMantleEffect copy() { + return new FarrelsMantleEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent perm = game.getPermanent(source.getSourceId()); + DamageTargetEffect dmgEffect = new DamageTargetEffect(2+perm.getPower().getValue()); + return dmgEffect.apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/GoblinFlotilla.java b/Mage.Sets/src/mage/sets/fallenempires/GoblinFlotilla.java new file mode 100644 index 0000000000..32c0bf7cf1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/GoblinFlotilla.java @@ -0,0 +1,92 @@ +/* + * 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.fallenempires; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.common.BlocksOrBecomesBlockedByCreatureTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.IslandwalkAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.abilities.effects.common.DoUnlessControllerPaysEffect; + +/** + * + * @author MarcoMarin + */ +public class GoblinFlotilla extends CardImpl { + + public GoblinFlotilla(UUID ownerId) { + super(ownerId, 113, "Goblin Flotilla", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Goblin"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Islandwalk + this.addAbility(new IslandwalkAbility()); + // At the beginning of each combat, unless you pay {R}, whenever Goblin Flotilla blocks or becomes blocked by a creature this combat, that creature gains first strike until end of turn. + this.addAbility(new BeginningOfCombatTriggeredAbility(new DoUnlessControllerPaysEffect( + new GainAbilitySourceEffect(new BlocksOrBecomesBlockedByCreatureTriggeredAbility(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, "Blocks or Blocked by Goblin Flotilla"), false), Duration.EndOfCombat) + //new GoblinFlotillaEffect() + , new ManaCostsImpl("{R}"), "Pay Goblin Flotilla combat effect?"), TargetController.ANY, false)); + } + + public GoblinFlotilla(final GoblinFlotilla card) { + super(card); + } + + @Override + public GoblinFlotilla copy() { + return new GoblinFlotilla(this); + } +} +/* +class GoblinFlotillaEffect extends OneShotEffect { + GoblinFlotillaEffect() { + super(Outcome.BoostCreature); + staticText = "unless you pay {R}, whenever Goblin Flotilla blocks or becomes blocked by a creature this combat, that creature gains first strike until end of turn."; + } + + GoblinFlotillaEffect(final GoblinFlotillaEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + new GainAbilitySourceEffect(new BlocksOrBecomesBlockedByCreatureTriggeredAbility(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), false), Duration.EndOfCombat); + } +}*/ \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fallenempires/GoblinKites.java b/Mage.Sets/src/mage/sets/fallenempires/GoblinKites.java new file mode 100644 index 0000000000..f002cab954 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/GoblinKites.java @@ -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.fallenempires; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +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.TargetController; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author MarcoMarin + */ +public class GoblinKites extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("controlled creature with power 2 or less"); + + static { + filter.add(new PowerPredicate(Filter.ComparisonType.LessThan, 3)); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public GoblinKites(UUID ownerId) { + super(ownerId, 117, "Goblin Kites", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); + this.expansionSetCode = "FEM"; + + // {R}: Target creature you control with toughness 2 or less gains flying until end of turn. Flip a coin at the beginning of the next end step. If you lose the flip, sacrifice that creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{R}")); + ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addEffect(new GainAbilityTargetEffect(new BeginningOfEndStepTriggeredAbility(new GoblinKitesEffect(), TargetController.NEXT, false), Duration.EndOfTurn)); + this.addAbility(ability); + } + + public GoblinKites(final GoblinKites card) { + super(card); + } + + @Override + public GoblinKites copy() { + return new GoblinKites(this); + } +} +class GoblinKitesEffect extends OneShotEffect { + + public GoblinKitesEffect() { + super(Outcome.Damage); + staticText = "flip a coin. If you lose the flip, sacrifice {this}"; + } + + public GoblinKitesEffect(GoblinKitesEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (controller != null && permanent != null) { + if (controller.flipCoin(game)) { + return true; + } else { + new SacrificeSourceEffect().apply(game, source); + return true; + } + } + return false; + } + + @Override + public GoblinKitesEffect copy() { + return new GoblinKitesEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java b/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java new file mode 100644 index 0000000000..6ec6d8beb7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java @@ -0,0 +1,139 @@ +/* + * 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.fallenempires; + +import java.util.UUID; +import mage.MageInt; +import static mage.Mana.BlackMana; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.BasicManaEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author MarcoMarin + */ +public class InitiatesOfTheEbonHand extends CardImpl { + + public InitiatesOfTheEbonHand(UUID ownerId) { + super(ownerId, 16, "Initiates of the Ebon Hand", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{B}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Cleric"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {1}: Add {B} to your mana pool. If this ability has been activated four or more times this turn, sacrifice Initiates of the Ebon Hand at the beginning of the next end step. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new BasicManaEffect(BlackMana(1)), + new ManaCostsImpl("{1}")); + ability.addEffect(new InitiatesOfTheEbonHandEffect()); + this.addAbility(ability); + } + + public InitiatesOfTheEbonHand(final InitiatesOfTheEbonHand card) { + super(card); + } + + @Override + public InitiatesOfTheEbonHand copy() { + return new InitiatesOfTheEbonHand(this); + } +} + +class InitiatesOfTheEbonHandEffect extends OneShotEffect { + + public InitiatesOfTheEbonHandEffect() { + super(Outcome.Damage); + this.staticText = "If this ability has been activated four or more times this turn, sacrifice {this} at the beginning of the next end step"; + } + + public InitiatesOfTheEbonHandEffect(final InitiatesOfTheEbonHandEffect effect) { + super(effect); + } + + @Override + public InitiatesOfTheEbonHandEffect copy() { + return new InitiatesOfTheEbonHandEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand"); + if (amount == null) { + amount = 0; + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new InitiatesOfTheEbonHandResetEffect()); + game.addDelayedTriggeredAbility(delayedAbility, source); + } + amount++; + game.getState().setValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand", amount); + + return true; + } +} + +class InitiatesOfTheEbonHandResetEffect extends OneShotEffect { + + public InitiatesOfTheEbonHandResetEffect() { + super(Outcome.Neutral); + this.staticText = "If this ability has been activated four or more times this turn, sacrifice {this} at the beginning of the next end step"; + } + + public InitiatesOfTheEbonHandResetEffect(final InitiatesOfTheEbonHandResetEffect effect) { + super(effect); + } + + @Override + public InitiatesOfTheEbonHandResetEffect copy() { + return new InitiatesOfTheEbonHandResetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand"); + if (amount != null && amount >= 4) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + permanent.sacrifice(source.getSourceId(), game); + } + } + game.getState().setValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand", null); + + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fallenempires/Necrite.java b/Mage.Sets/src/mage/sets/fallenempires/Necrite.java new file mode 100644 index 0000000000..6da52cbdbc --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/Necrite.java @@ -0,0 +1,110 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.Target; +import mage.target.TargetPermanent; + +/** + * + * @author MarcoMarin + */ +public class Necrite extends CardImpl { + + public Necrite(UUID ownerId) { + super(ownerId, 22, "Necrite", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Thrull"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever Necrite attacks and isn't blocked, you may sacrifice it. If you do, destroy target creature defending player controls. It can't be regenerated. + DoIfCostPaid effect = new DoIfCostPaid(new DestroyTargetEffect(true), new SacrificeSourceCost(), "Sacrifice {this} to destroy target creature defending player controls?"); + effect.setText("you may sacrifice it. If you do, destroy target creature defending player controls. It can't be regenerated."); + effect.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn)); + Ability ability = new NecriteTriggeredAbility(effect); + this.addAbility(ability); + + } + + public Necrite(final Necrite card) { + super(card); + } + + @Override + public Necrite copy() { + return new Necrite(this); + } +} + +class NecriteTriggeredAbility extends AttacksAndIsNotBlockedTriggeredAbility{ + + public NecriteTriggeredAbility(Effect effect) { + super(effect); + } + + public NecriteTriggeredAbility(final NecriteTriggeredAbility ability) { + super(ability); + } + + @Override + public NecriteTriggeredAbility copy() { + return new NecriteTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (super.checkTrigger(event, game)){ + UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(getSourceId(), game); + FilterPermanent filter = new FilterCreaturePermanent(); + filter.add(new ControllerIdPredicate(defendingPlayerId)); + Target target = new TargetPermanent(filter); + this.addTarget(target); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fallenempires/Orgg.java b/Mage.Sets/src/mage/sets/fallenempires/Orgg.java new file mode 100644 index 0000000000..5f5233f8b6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/Orgg.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author MarcoMarin + */ +public class Orgg extends mage.sets.timeshifted.Orgg { + + public Orgg(UUID ownerId) { + super(ownerId); + this.cardNumber = 131; + this.expansionSetCode = "FEM"; + this.rarity = Rarity.RARE; + } + + public Orgg(final Orgg card) { + super(card); + } + + @Override + public Orgg copy() { + return new Orgg(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/SoulExchange.java b/Mage.Sets/src/mage/sets/fallenempires/SoulExchange.java new file mode 100644 index 0000000000..6d24cabbe9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/SoulExchange.java @@ -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.fallenempires; + +import java.util.UUID; + +/** + * + * @author MarcoMarin + */ +public class SoulExchange extends mage.sets.masterseditionii.SoulExchange { + + public SoulExchange(UUID ownerId) { + super(ownerId); + this.cardNumber = 28; + this.expansionSetCode = "FEM"; + } + + public SoulExchange(final SoulExchange card) { + super(card); + } + + @Override + public SoulExchange copy() { + return new SoulExchange(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/DwarvenSoldier.java b/Mage.Sets/src/mage/sets/fifthedition/DwarvenSoldier.java new file mode 100644 index 0000000000..5bdf0509cc --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/DwarvenSoldier.java @@ -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.fifthedition; + +import java.util.UUID; + +/** + * + * @author MarcoMarin + */ +public class DwarvenSoldier extends mage.sets.fallenempires.DwarvenSoldier { + + public DwarvenSoldier(UUID ownerId) { + super(ownerId); + this.cardNumber = 221; + this.expansionSetCode = "5ED"; + } + + public DwarvenSoldier(final DwarvenSoldier card) { + super(card); + } + + @Override + public DwarvenSoldier copy() { + return new DwarvenSoldier(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/InitiatesOfTheEbonHand.java b/Mage.Sets/src/mage/sets/fifthedition/InitiatesOfTheEbonHand.java new file mode 100644 index 0000000000..2a8138ca4f --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/InitiatesOfTheEbonHand.java @@ -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.fifthedition; + +import java.util.UUID; + +/** + * + * @author MarcoMarin + */ +public class InitiatesOfTheEbonHand extends mage.sets.fallenempires.InitiatesOfTheEbonHand { + + public InitiatesOfTheEbonHand(UUID ownerId) { + super(ownerId); + this.cardNumber = 31; + this.expansionSetCode = "5ED"; + } + + public InitiatesOfTheEbonHand(final InitiatesOfTheEbonHand card) { + super(card); + } + + @Override + public InitiatesOfTheEbonHand copy() { + return new InitiatesOfTheEbonHand(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/Necrite.java b/Mage.Sets/src/mage/sets/fifthedition/Necrite.java new file mode 100644 index 0000000000..3cd23e5601 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/Necrite.java @@ -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.fifthedition; + +import java.util.UUID; + +/** + * + * @author MarcoMarin + */ +public class Necrite extends mage.sets.fallenempires.Necrite { + + public Necrite(UUID ownerId) { + super(ownerId); + this.cardNumber = 43; + this.expansionSetCode = "5ED"; + } + + public Necrite(final Necrite card) { + super(card); + } + + @Override + public Necrite copy() { + return new Necrite(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/Orgg.java b/Mage.Sets/src/mage/sets/fifthedition/Orgg.java new file mode 100644 index 0000000000..6f6a2d0821 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/Orgg.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fifthedition; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author MarcoMarin + */ +public class Orgg extends mage.sets.timeshifted.Orgg { + + public Orgg(UUID ownerId) { + super(ownerId); + this.cardNumber = 259; + this.expansionSetCode = "5ED"; + this.rarity = Rarity.RARE; + } + + public Orgg(final Orgg card) { + super(card); + } + + @Override + public Orgg copy() { + return new Orgg(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mastersedition/DwarvenSoldier.java b/Mage.Sets/src/mage/sets/mastersedition/DwarvenSoldier.java new file mode 100644 index 0000000000..4bd41ab976 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mastersedition/DwarvenSoldier.java @@ -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.mastersedition; + +import java.util.UUID; + +/** + * + * @author MarcoMarin + */ +public class DwarvenSoldier extends mage.sets.fallenempires.DwarvenSoldier { + + public DwarvenSoldier(UUID ownerId) { + super(ownerId); + this.cardNumber = 92; + this.expansionSetCode = "MED"; + } + + public DwarvenSoldier(final DwarvenSoldier card) { + super(card); + } + + @Override + public DwarvenSoldier copy() { + return new DwarvenSoldier(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditionii/FarrelsMantle.java b/Mage.Sets/src/mage/sets/masterseditionii/FarrelsMantle.java new file mode 100644 index 0000000000..b0a4c76d7f --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/FarrelsMantle.java @@ -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.masterseditionii; + +import java.util.UUID; + +/** + * + * @author MarcoMarin + */ +public class FarrelsMantle extends mage.sets.fallenempires.FarrelsMantle { + + public FarrelsMantle(UUID ownerId) { + super(ownerId); + this.cardNumber = 13; + this.expansionSetCode = "ME2"; + } + + public FarrelsMantle(final FarrelsMantle card) { + super(card); + } + + @Override + public FarrelsMantle copy() { + return new FarrelsMantle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditionii/Necrite.java b/Mage.Sets/src/mage/sets/masterseditionii/Necrite.java new file mode 100644 index 0000000000..05605d22d1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/Necrite.java @@ -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.masterseditionii; + +import java.util.UUID; + +/** + * + * @author MarcoMarin + */ +public class Necrite extends mage.sets.fallenempires.Necrite { + + public Necrite(UUID ownerId) { + super(ownerId); + this.cardNumber = 106; + this.expansionSetCode = "ME2"; + } + + public Necrite(final Necrite card) { + super(card); + } + + @Override + public Necrite copy() { + return new Necrite(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditionii/SoulExchange.java b/Mage.Sets/src/mage/sets/masterseditionii/SoulExchange.java new file mode 100644 index 0000000000..71b74b2aa6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/SoulExchange.java @@ -0,0 +1,111 @@ +/* + * 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.masterseditionii; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.ExileTargetCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.counters.CounterType; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author MarcoMarin + */ +public class SoulExchange extends CardImpl { + + public SoulExchange(UUID ownerId) { + super(ownerId, 111, "Soul Exchange", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{B}{B}"); + this.expansionSetCode = "ME2"; + + // As an additional cost to cast Soul Exchange, exile a creature you control. + Cost cost = new ExileTargetCost(new TargetControlledCreaturePermanent()); + this.getSpellAbility().addCost(cost); + // Return target creature card from your graveyard to the battlefield. Put a +2/+2 counter on that creature if the exiled creature was a Thrull. + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card from your graveyard"))); + this.getSpellAbility().addEffect(new SoulExchangeEffect()); + + } + + public SoulExchange(final SoulExchange card) { + super(card); + } + + @Override + public SoulExchange copy() { + return new SoulExchange(this); + } +} + +class SoulExchangeEffect extends OneShotEffect{ + + public SoulExchangeEffect() { + super(Outcome.Benefit); + this.setText("Return target creature card from your graveyard to the battlefield. Put a +2/+2 counter on that creature if the exiled creature was a Thrull."); + } + + public SoulExchangeEffect(final SoulExchangeEffect effect) { + super(effect); + } + + @Override + public SoulExchangeEffect copy() { + return new SoulExchangeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + ReturnFromGraveyardToBattlefieldTargetEffect effect = new ReturnFromGraveyardToBattlefieldTargetEffect(); + if (!effect.apply(game, source)) return false; + + for (Cost c : source.getCosts()){ + if (!c.getTargets().isEmpty()){ + UUID t = c.getTargets().getFirstTarget(); + Permanent exiled = game.getPermanentOrLKIBattlefield(t); + if (exiled == null) return false; + if (exiled.getSubtype().contains("Thrull")){ + game.getPermanent(source.getFirstTarget()).addCounters(CounterType.P2P2.createInstance(), game); + } + } + } + + + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/timeshifted/Orgg.java b/Mage.Sets/src/mage/sets/timeshifted/Orgg.java new file mode 100644 index 0000000000..117ccb6d94 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timeshifted/Orgg.java @@ -0,0 +1,87 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timeshifted; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.combat.CantAttackIfDefenderControlsPermanent; +import mage.abilities.effects.common.combat.CantBlockCreaturesSourceEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.permanent.TappedPredicate; + +/** + * + * @author MarcoMarin + */ +public class Orgg extends CardImpl { + + static final private FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creature with power 3 or greater"); + static final private FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creatures with power 3 or greater"); + + static { + filter.add(Predicates.and(new PowerPredicate(Filter.ComparisonType.GreaterThan, 2), Predicates.not(new TappedPredicate()))); + filter2.add(new PowerPredicate(Filter.ComparisonType.GreaterThan, 2)); + } + public Orgg(UUID ownerId) { + super(ownerId, 67, "Orgg", Rarity.SPECIAL, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + this.expansionSetCode = "TSB"; + this.subtype.add("Orgg"); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + // Orgg can't attack if defending player controls an untapped creature with power 3 or greater. + Effect effect = new CantAttackIfDefenderControlsPermanent(filter); + effect.setText("{this} can't attack if defending player controls an untapped creature with power 3 or greater."); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + // Orgg can't block creatures with power 3 or greater. + Effect effectBlock = new CantBlockCreaturesSourceEffect(filter2); + effectBlock.setText("{this} can't block creatures with power 3 or greater."); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effectBlock)); + } + + public Orgg(final Orgg card) { + super(card); + } + + @Override + public Orgg copy() { + return new Orgg(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/DoUnlessControllerPaysEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessControllerPaysEffect.java new file mode 100644 index 0000000000..586e1ae4c5 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessControllerPaysEffect.java @@ -0,0 +1,135 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.effects.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.costs.Cost; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.Effects; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author MarcoMarin + */ +public class DoUnlessControllerPaysEffect extends OneShotEffect { + + protected Effects executingEffects = new Effects(); + private final Cost cost; + private String chooseUseText; + + public DoUnlessControllerPaysEffect(Effect effect, Cost cost) { + this(effect, cost, null); + } + + public DoUnlessControllerPaysEffect(Effect effect, Cost cost, String chooseUseText) { + super(Outcome.Benefit); + this.executingEffects.add(effect); + this.cost = cost; + this.chooseUseText = chooseUseText; + } + + public DoUnlessControllerPaysEffect(final DoUnlessControllerPaysEffect effect) { + super(effect); + this.executingEffects = effect.executingEffects.copy(); + this.cost = effect.cost.copy(); + this.chooseUseText = effect.chooseUseText; + } + + public void addEffect(Effect effect) { + executingEffects.add(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller != null && sourceObject != null) { + String message; + if (chooseUseText == null) { + String effectText = executingEffects.getText(source.getModes().getMode()); + message = "Pay " + cost.getText() + " to prevent (" + effectText.substring(0, effectText.length() - 1) + ")?"; + } else { + message = chooseUseText; + } + message = CardUtil.replaceSourceName(message, sourceObject.getName()); + boolean result = true; + boolean doEffect = true; + + // check if controller is willing to pay + if (cost.canPay(source, source.getSourceId(), controller.getId(), game) && controller.chooseUse(Outcome.Detriment, message, source, game)) { + cost.clearPaid(); + if (cost.pay(source, game, source.getSourceId(), controller.getId(), false, null)) { + if (!game.isSimulation()) { + game.informPlayers(controller.getLogName() + " pays the cost to prevent the effect"); + } + doEffect = false; + } + } + + // do the effects if not paid + if (doEffect) { + for (Effect effect : executingEffects) { + effect.setTargetPointer(this.targetPointer); + if (effect instanceof OneShotEffect) { + result &= effect.apply(game, source); + } else { + game.addEffect((ContinuousEffect) effect, source); + } + } + } + return result; + } + return false; + } + + protected Player getPayingPlayer(Game game, Ability source) { + return game.getPlayer(source.getControllerId()); + } + + @Override + public String getText(Mode mode) { + if (!staticText.isEmpty()) { + return staticText; + } + String effectsText = executingEffects.getText(mode); + return effectsText.substring(0, effectsText.length() - 1) + " unless controller pays " + cost.getText(); + } + + @Override + public DoUnlessControllerPaysEffect copy() { + return new DoUnlessControllerPaysEffect(this); + } +} diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index ea6455df24..5a1a359cff 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -46,6 +46,7 @@ public enum CounterType { CORPSE("corpse"), CREDIT("credit"), CRYSTAL("crystal"), + CUBE("cube"), DELAY("delay"), DEPLETION("depletion"), DESPAIR("despair"), From eb960a34ad40eb379f488f7bc4a77db0da258d7e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 21 Apr 2016 11:46:02 +0200 Subject: [PATCH 2/3] * Dragon Whelp - Made the activation handling more reusable friendly and object sensitive (zone change counter). --- .../src/mage/sets/magic2010/DragonWhelp.java | 34 +--- .../other/LimitedCountedActivationsTest.java | 158 ++++++++++++++++++ .../java/mage/abilities/ActivationInfo.java | 77 +++++++++ 3 files changed, 239 insertions(+), 30 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java create mode 100644 Mage/src/main/java/mage/abilities/ActivationInfo.java diff --git a/Mage.Sets/src/mage/sets/magic2010/DragonWhelp.java b/Mage.Sets/src/mage/sets/magic2010/DragonWhelp.java index 1963f833b9..091a8fe99e 100644 --- a/Mage.Sets/src/mage/sets/magic2010/DragonWhelp.java +++ b/Mage.Sets/src/mage/sets/magic2010/DragonWhelp.java @@ -30,6 +30,7 @@ package mage.sets.magic2010; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.ActivationInfo; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; @@ -45,7 +46,6 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; -import mage.util.CardUtil; /** * @@ -84,17 +84,6 @@ public class DragonWhelp extends CardImpl { class DragonWhelpEffect extends OneShotEffect { - class ActivationInfo { - - public int turnNum; - public int activationCounter; - - public ActivationInfo(int turnNum, int activationCounter) { - this.turnNum = turnNum; - this.activationCounter = activationCounter; - } - } - public DragonWhelpEffect() { super(Outcome.Damage); this.staticText = "If this ability has been activated four or more times this turn, sacrifice {this} at the beginning of the next end step"; @@ -111,28 +100,13 @@ class DragonWhelpEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - ActivationInfo activationInfo = getActivationInfo(source, game); - ++activationInfo.activationCounter; - setActivationInfo(activationInfo, source, game); - if (activationInfo.activationCounter == 4) { + ActivationInfo activationInfo = ActivationInfo.getInstance(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); + activationInfo.addActivation(game); + if (activationInfo.getActivationCounter() == 4) { DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()); game.addDelayedTriggeredAbility(delayedAbility, source); } return true; } - private ActivationInfo getActivationInfo(Ability source, Game game) { - Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn", source.getSourceId(), game)); - Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount", source.getSourceId(), game)); - if (turnNum == null || activationCount == null) { - turnNum = game.getTurnNum(); - activationCount = 0; - } - return new ActivationInfo(turnNum, activationCount); - } - - private void setActivationInfo(ActivationInfo activationInfo, Ability source, Game game) { - game.getState().setValue(CardUtil.getCardZoneString("activationsTurn", source.getSourceId(), game), activationInfo.turnNum); - game.getState().setValue(CardUtil.getCardZoneString("activationsCount", source.getSourceId(), game), activationInfo.activationCounter); - } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java new file mode 100644 index 0000000000..15fdefd210 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java @@ -0,0 +1,158 @@ +/* + * 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 org.mage.test.cards.abilities.other; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class LimitedCountedActivationsTest extends CardTestPlayerBase { + + /** + * Tests usage of ActivationInfo class + */ + @Test + public void testDragonWhelpActivatedThreeTimes() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertPermanentCount(playerA, "Dragon Whelp", 1); + + assertLife(playerA, 20); + assertLife(playerB, 15); + } + + @Test + public void testDragonWhelpActivatedFourTimes() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertPermanentCount(playerA, "Dragon Whelp", 0); + assertGraveyardCount(playerA, "Dragon Whelp", 1); + + assertLife(playerA, 20); + assertLife(playerB, 14); + } + + @Test + public void testDragonWhelpActivatedFiveTimes() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertPermanentCount(playerA, "Dragon Whelp", 0); + assertGraveyardCount(playerA, "Dragon Whelp", 1); + + assertLife(playerA, 20); + assertLife(playerB, 13); + } + + @Test + public void testDragonWhelpTwoObjects() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + // Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. + addCard(Zone.HAND, playerA, "Reanimate", 1); + // Target creature gains haste until end of turn. + addCard(Zone.HAND, playerA, "Unnatural Speed", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + // Destroy target nonartifact, nonblack creature. It can't be regenerated. + addCard(Zone.HAND, playerB, "Terror", 1); // {1}{B} + + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Terror", "Dragon Whelp"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Dragon Whelp"); + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Unnatural Speed", "Dragon Whelp"); + + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertGraveyardCount(playerA, "Unnatural Speed", 1); + assertGraveyardCount(playerA, "Reanimate", 1); + + assertGraveyardCount(playerB, "Terror", 1); + + assertPermanentCount(playerA, "Dragon Whelp", 1); + assertPowerToughness(playerA, "Dragon Whelp", 2, 3); + assertGraveyardCount(playerA, "Dragon Whelp", 0); + + assertLife(playerA, 16); + assertLife(playerB, 15); + } +} diff --git a/Mage/src/main/java/mage/abilities/ActivationInfo.java b/Mage/src/main/java/mage/abilities/ActivationInfo.java new file mode 100644 index 0000000000..84d6b1b8db --- /dev/null +++ b/Mage/src/main/java/mage/abilities/ActivationInfo.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities; + +import java.util.UUID; +import mage.game.Game; + +/** + * The ActivationInfo class holds the information how often an ability of an + * object was activated during a turn. It handles the check, if the object is + * still the same, so for example if a permanent left battlefield and returns, + * the counting of activations happens for each object. + * + * @author LevelX2 + */ +public class ActivationInfo { + + protected int turnNum; + protected int activationCounter; + + public static ActivationInfo getInstance(Game game, UUID sourceId) { + return ActivationInfo.getInstance(game, sourceId, game.getState().getZoneChangeCounter(sourceId)); + } + + public static ActivationInfo getInstance(Game game, UUID sourceId, int zoneChangeCounter) { + String key = "ActivationInfo" + sourceId.toString() + zoneChangeCounter; + ActivationInfo activationInfo = (ActivationInfo) game.getState().getValue(key); + if (activationInfo == null) { + activationInfo = new ActivationInfo(game); + game.getState().setValue(key, activationInfo); + } + return activationInfo; + } + + protected ActivationInfo(Game game) { + this.turnNum = game.getTurnNum(); + this.activationCounter = 0; + } + + public void addActivation(Game game) { + if (game.getTurnNum() != turnNum) { + activationCounter = 1; + turnNum = game.getTurnNum(); + } else { + activationCounter++; + } + } + + public int getActivationCounter() { + return activationCounter; + } +} From 0c0dd82480ba62827a54876888a195af707c2b42 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 21 Apr 2016 17:13:57 +0200 Subject: [PATCH 3/3] * Some changes to activation count and sacrifice source triggers. --- .../sets/fallenempires/FarrelitePriest.java | 53 ++++--------------- .../fallenempires/InitiatesOfTheEbonHand.java | 52 ++++-------------- .../mage/sets/journeyintonyx/BrainMaggot.java | 4 +- .../other/LimitedCountedActivationsTest.java | 47 ++++++++++++++++ .../cards/abilities/other/NecromancyTest.java | 41 +++++++------- .../cards/triggers/dies/BrainMaggotTest.java | 12 ++--- .../main/java/mage/abilities/AbilityImpl.java | 2 - .../mage/abilities/TriggeredAbilityImpl.java | 4 +- ...LeaveReturnExiledToBattlefieldAbility.java | 4 +- .../effects/common/SacrificeSourceEffect.java | 21 +++++--- 10 files changed, 116 insertions(+), 124 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java b/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java index 8378dda0a8..bbf2927b12 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java +++ b/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java @@ -31,19 +31,20 @@ import java.util.UUID; import mage.MageInt; import static mage.Mana.WhiteMana; import mage.abilities.Ability; +import mage.abilities.ActivationInfo; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; /** * @@ -60,11 +61,11 @@ public class FarrelitePriest extends CardImpl { this.toughness = new MageInt(3); // {1}: Add {W} to your mana pool. If this ability has been activated four or more times this turn, sacrifice Farrelite Priest at the beginning of the next end step. - SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + SimpleManaAbility ability = new SimpleManaAbility(Zone.BATTLEFIELD, new BasicManaEffect(WhiteMana(1)), new ManaCostsImpl("{1}")); ability.addEffect(new FarrelitePriestEffect()); - this.addAbility(ability); + this.addAbility(ability); } public FarrelitePriest(final FarrelitePriest card) { @@ -76,6 +77,7 @@ public class FarrelitePriest extends CardImpl { return new FarrelitePriest(this); } } + class FarrelitePriestEffect extends OneShotEffect { public FarrelitePriestEffect() { @@ -94,46 +96,13 @@ class FarrelitePriestEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "FarrelitePriest"); - if (amount == null) { - amount = 0; - DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new FarrelitePriestResetEffect()); + ActivationInfo activationInfo = ActivationInfo.getInstance(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); + activationInfo.addActivation(game); + if (activationInfo.getActivationCounter() == 4) { + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()); game.addDelayedTriggeredAbility(delayedAbility, source); } - amount++; - game.getState().setValue(source.getSourceId().toString() + "FarrelitePriest", amount); - return true; } + } - -class FarrelitePriestResetEffect extends OneShotEffect { - - public FarrelitePriestResetEffect() { - super(Outcome.Neutral); - this.staticText = "If this ability has been activated four or more times this turn, sacrifice {this} at the beginning of the next end step"; - } - - public FarrelitePriestResetEffect(final FarrelitePriestResetEffect effect) { - super(effect); - } - - @Override - public FarrelitePriestResetEffect copy() { - return new FarrelitePriestResetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "FarrelitePriest"); - if (amount != null && amount >= 4) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.sacrifice(source.getSourceId(), game); - } - } - game.getState().setValue(source.getSourceId().toString() + "FarrelitePriest", null); - - return true; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java b/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java index 6ec6d8beb7..64b3b57cb8 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java +++ b/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java @@ -31,19 +31,20 @@ import java.util.UUID; import mage.MageInt; import static mage.Mana.BlackMana; import mage.abilities.Ability; +import mage.abilities.ActivationInfo; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; /** * @@ -59,11 +60,11 @@ public class InitiatesOfTheEbonHand extends CardImpl { this.toughness = new MageInt(1); // {1}: Add {B} to your mana pool. If this ability has been activated four or more times this turn, sacrifice Initiates of the Ebon Hand at the beginning of the next end step. - SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + SimpleManaAbility ability = new SimpleManaAbility(Zone.BATTLEFIELD, new BasicManaEffect(BlackMana(1)), new ManaCostsImpl("{1}")); ability.addEffect(new InitiatesOfTheEbonHandEffect()); - this.addAbility(ability); + this.addAbility(ability); } public InitiatesOfTheEbonHand(final InitiatesOfTheEbonHand card) { @@ -94,46 +95,13 @@ class InitiatesOfTheEbonHandEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand"); - if (amount == null) { - amount = 0; - DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new InitiatesOfTheEbonHandResetEffect()); + ActivationInfo activationInfo = ActivationInfo.getInstance(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); + activationInfo.addActivation(game); + if (activationInfo.getActivationCounter() == 4) { + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()); game.addDelayedTriggeredAbility(delayedAbility, source); } - amount++; - game.getState().setValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand", amount); - return true; } + } - -class InitiatesOfTheEbonHandResetEffect extends OneShotEffect { - - public InitiatesOfTheEbonHandResetEffect() { - super(Outcome.Neutral); - this.staticText = "If this ability has been activated four or more times this turn, sacrifice {this} at the beginning of the next end step"; - } - - public InitiatesOfTheEbonHandResetEffect(final InitiatesOfTheEbonHandResetEffect effect) { - super(effect); - } - - @Override - public InitiatesOfTheEbonHandResetEffect copy() { - return new InitiatesOfTheEbonHandResetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand"); - if (amount != null && amount >= 4) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.sacrifice(source.getSourceId(), game); - } - } - game.getState().setValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand", null); - - return true; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java b/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java index dd4a185cce..ee3fb7215d 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java @@ -49,7 +49,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentToken; import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetOpponent; @@ -188,8 +187,7 @@ class BrainMaggotReturnExiledCardEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); if (sourceObject != null && controller != null) { - int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() - 1; - ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter)); + ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter())); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (exile != null && sourcePermanent != null) { controller.moveCards(exile, Zone.HAND, source, game); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java index 15fdefd210..250ba777cf 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java @@ -155,4 +155,51 @@ public class LimitedCountedActivationsTest extends CardTestPlayerBase { assertLife(playerA, 16); assertLife(playerB, 15); } + + @Test + public void testDragonWhelpDontSacrificeNewObject() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + // Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. + addCard(Zone.HAND, playerA, "Reanimate", 1); + // Target creature gains haste until end of turn. + addCard(Zone.HAND, playerA, "Unnatural Speed", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + // Destroy target nonartifact, nonblack creature. It can't be regenerated. + addCard(Zone.HAND, playerB, "Terror", 1); // {1}{B} + + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Terror", "Dragon Whelp"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Dragon Whelp"); + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Unnatural Speed", "Dragon Whelp"); + + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertGraveyardCount(playerA, "Unnatural Speed", 1); + assertGraveyardCount(playerA, "Reanimate", 1); + + assertGraveyardCount(playerB, "Terror", 1); + + assertPermanentCount(playerA, "Dragon Whelp", 1); + assertPowerToughness(playerA, "Dragon Whelp", 2, 3); + assertGraveyardCount(playerA, "Dragon Whelp", 0); + + assertLife(playerA, 16); + assertLife(playerB, 15); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NecromancyTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NecromancyTest.java index 5b2a9ae2f6..4cf6203543 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NecromancyTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NecromancyTest.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package org.mage.test.cards.abilities.other; import mage.constants.PhaseStep; @@ -39,20 +38,18 @@ import org.mage.test.serverside.base.CardTestPlayerBase; */ public class NecromancyTest extends CardTestPlayerBase { - /** - * Necromancy - * Enchantment, 2B (3) - * You may cast Necromancy as though it had flash. If you cast it any time a - * sorcery couldn't have been cast, the controller of the permanent it - * becomes sacrifices it at the beginning of the next cleanup step. - * When Necromancy enters the battlefield, if it's on the battlefield, it - * becomes an Aura with "enchant creature put onto the battlefield with - * Necromancy." Put target creature card from a graveyard onto the - * battlefield under your control and attach Necromancy to it. When - * Necromancy leaves the battlefield, that creature's controller sacrifices it. + /** + * Necromancy Enchantment, 2B (3) You may cast Necromancy as though it had + * flash. If you cast it any time a sorcery couldn't have been cast, the + * controller of the permanent it becomes sacrifices it at the beginning of + * the next cleanup step. When Necromancy enters the battlefield, if it's on + * the battlefield, it becomes an Aura with "enchant creature put onto the + * battlefield with Necromancy." Put target creature card from a graveyard + * onto the battlefield under your control and attach Necromancy to it. When + * Necromancy leaves the battlefield, that creature's controller sacrifices + * it. * */ - @Test public void testNecromancy() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); @@ -60,7 +57,7 @@ public class NecromancyTest extends CardTestPlayerBase { addCard(Zone.GRAVEYARD, playerA, "Craw Wurm"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Necromancy"); - + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -77,7 +74,7 @@ public class NecromancyTest extends CardTestPlayerBase { addCard(Zone.GRAVEYARD, playerA, "Craw Wurm"); castSpell(1, PhaseStep.UPKEEP, playerA, "Necromancy"); - + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -87,14 +84,20 @@ public class NecromancyTest extends CardTestPlayerBase { } + /** + * Check if Necromancy is sacrificed if cast as instant and if the + * reanimated creature will be sacrificed. + */ @Test public void testNecromancyFlashSacrifice() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + // If you cast it any time a sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step. + // When Necromancy leaves the battlefield, that creature's controller sacrifices it. addCard(Zone.HAND, playerA, "Necromancy"); - addCard(Zone.GRAVEYARD, playerA, "Craw Wurm"); + addCard(Zone.GRAVEYARD, playerA, "Craw Wurm"); // 6/4 castSpell(1, PhaseStep.UPKEEP, playerA, "Necromancy"); - + setStopAt(2, PhaseStep.BEGIN_COMBAT); execute(); @@ -114,7 +117,7 @@ public class NecromancyTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Necromancy"); // enchanting the Craw Wurm castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disenchant", "Necromancy"); // if Necromancy leaves, the enchanted creature has to leave too - + setStopAt(1, PhaseStep.END_TURN); execute(); @@ -124,5 +127,5 @@ public class NecromancyTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Necromancy", 1); assertGraveyardCount(playerA, "Craw Wurm", 1); } - + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java index 5bfd5cab69..49b840a07b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java @@ -36,13 +36,13 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * * @author LevelX2 */ - public class BrainMaggotTest extends CardTestPlayerBase { /** - * When Brain Maggot enters the battlefield, target opponent reveals his or her hand and - * you choose a nonland card from it. Exile that card until Brain Maggot leaves the battlefield. - * + * When Brain Maggot enters the battlefield, target opponent reveals his or + * her hand and you choose a nonland card from it. Exile that card until + * Brain Maggot leaves the battlefield. + * */ @Test public void testCardFromHandWillBeExiled() { @@ -61,10 +61,10 @@ public class BrainMaggotTest extends CardTestPlayerBase { assertExileCount("Bloodflow Connoisseur", 1); } - @Test public void testCardFromHandWillBeExiledAndReturn() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + // When Brain Maggot enters the battlefield, target opponent reveals his or her hand and you choose a nonland card from it. Exile that card until Brain Maggot leaves the battlefield. addCard(Zone.HAND, playerA, "Brain Maggot", 2); addCard(Zone.HAND, playerB, "Bloodflow Connoisseur", 1); @@ -105,4 +105,4 @@ public class BrainMaggotTest extends CardTestPlayerBase { assertHandCount(playerB, "Bloodflow Connoisseur", 1); assertExileCount("Bloodflow Connoisseur", 0); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index cb4de5e1ec..497fc66ddb 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -1191,8 +1191,6 @@ public abstract class AbilityImpl implements Ability { public void setSourceObject(MageObject sourceObject, Game game) { if (sourceObject == null) { this.sourceObject = game.getObject(sourceId); - // if permanent get card /permanent instead of spell - } else { this.sourceObject = sourceObject; } diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java index 016369ac85..54e6926dcc 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java @@ -70,7 +70,9 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge public void trigger(Game game, UUID controllerId) { //20091005 - 603.4 if (checkInterveningIfClause(game)) { - setSourceObject(null, game); + if (!(this instanceof DelayedTriggeredAbility)) { + setSourceObject(null, game); + } game.addTriggeredAbility(this); } } diff --git a/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java index 3da2208a19..996b05d9c6 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java @@ -40,7 +40,6 @@ import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.PermanentToken; import mage.players.Player; import mage.util.CardUtil; @@ -107,8 +106,7 @@ class ReturnExiledPermanentsEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); if (sourceObject != null && controller != null) { - int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() - 1; - UUID exileZone = CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter); + UUID exileZone = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); if (exileZone != null) { ExileZone exile = game.getExile().getExileZone(exileZone); if (exile != null) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java index bb1f89ea2c..2dfc09db98 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java @@ -1,16 +1,16 @@ /* * 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 @@ -20,12 +20,11 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.effects.common; import mage.MageObject; @@ -34,6 +33,7 @@ import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.game.stack.Spell; /** * @@ -58,6 +58,15 @@ public class SacrificeSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { MageObject sourceObject = source.getSourceObjectIfItStillExists(game); + if (sourceObject == null) { + // Check if the effect was installed by the spell the source was cast by (e.g. Necromancy), if not don't sacrifice the permanent + if (source.getSourceObject(game) instanceof Spell) { + sourceObject = game.getPermanent(source.getSourceId()); + if (sourceObject.getZoneChangeCounter(game) > source.getSourceObjectZoneChangeCounter() + 1) { + return false; + } + } + } if (sourceObject instanceof Permanent) { Permanent permanent = (Permanent) sourceObject; // you can only sacrifice a permanent you control